Post log messages to Matrix #6

Merged
eric merged 4 commits from matrix_logging into main 2025-02-09 15:48:04 +00:00
10 changed files with 104 additions and 46 deletions

View File

@ -4,3 +4,8 @@ KRAKEN_API_SEC =
R_VALUE_TARGET = R_VALUE_TARGET =
INVESTMENT_COUNT = INVESTMENT_COUNT =
INVESTMENT_VOLUME = INVESTMENT_VOLUME =
LOG_LEVEL =
MATRIX_HOMESERVER_ADDRESS =
MATRIX_USER_ID =
MATRIX_USER_PASSWORD =
MATRIX_ROOM_ID =

View File

@ -0,0 +1,3 @@
# Kraken bot
A Python bot for day-trading cryptocurrencies on the Kraken exchange.

29
app.py
View File

@ -1,32 +1,19 @@
import logging import asyncio
import os
from dotenv import load_dotenv
from kraken_bot.KrakenBot import KrakenBot from kraken_bot.KrakenBot import KrakenBot
from kraken_bot.LinearRegression import LinearRegression from kraken_bot.LinearRegression import LinearRegression
from kraken_bot.HighLowCutoff import HighLowCutoff from kraken_bot.MyStrategy import MyStrategy
from dotenv import load_dotenv
load_dotenv() load_dotenv()
logger = logging.getLogger(__name__)
model = LinearRegression(
r_value_target = float(os.getenv('R_VALUE_TARGET'))
)
strategy = HighLowCutoff(
investment_count = int(os.getenv('INVESTMENT_COUNT')),
investment_volume = float(os.getenv('INVESTMENT_VOLUME')),
target_gain = float(os.getenv('TARGET_GAIN')),
max_loss = float(os.getenv('MAX_LOSS'))
)
bot = KrakenBot( bot = KrakenBot(
token = os.getenv('KRAKEN_API_TOKEN'),
secret = os.getenv('KRAKEN_API_SEC'),
tier = 'Pro', tier = 'Pro',
model = model, model = LinearRegression(),
trading_strategy = strategy trading_strategy = MyStrategy()
) )
if __name__ == '__main__': if __name__ == '__main__':
bot.update(full=True) asyncio.run(bot.update(full=True))
bot.execute() asyncio.run(bot.execute())

View File

@ -1,5 +1,4 @@
import krakenex import krakenex
import logging
import os import os
import scipy import scipy
import sys import sys
@ -7,16 +6,14 @@ import time
from pykrakenapi import KrakenAPI from pykrakenapi import KrakenAPI
from kraken_bot.MatrixLogger import MatrixLogger
class KrakenBot(KrakenAPI): class KrakenBot(KrakenAPI):
def __init__(self, token, secret, tier, model, trading_strategy): def __init__(self, tier, model, trading_strategy):
self.model = model self.model = model
self.trading_strategy = trading_strategy self.trading_strategy = trading_strategy
self.log = logging.getLogger(__name__) self.log = MatrixLogger(str(self.__class__.__name__))
self.log.setLevel( super().__init__(krakenex.API(os.getenv('KRAKEN_API_TOKEN'), os.getenv('KRAKEN_API_SEC')), tier=tier)
getattr(logging, os.getenv('LOG_LEVEL', 'INFO'), logging.INFO)
)
self.log.addHandler(logging.StreamHandler(sys.stdout))
super().__init__(krakenex.API(token, secret), tier=tier)
self.update(full=True) self.update(full=True)
def _delay_factor(self): def _delay_factor(self):
@ -75,7 +72,7 @@ class KrakenBot(KrakenAPI):
order.ordertype, order.type, order.pair, order.userref, order.volume, order.price, order.price2, order.trigger, order.ordertype, order.type, order.pair, order.userref, order.volume, order.price, order.price2, order.trigger,
order.leverage, order.oflags, order.timeinforce, order.starttm, order.expiretm, order.close_ordertype, order.leverage, order.oflags, order.timeinforce, order.starttm, order.expiretm, order.close_ordertype,
order.close_price, order.close_price2, order.deadline, order.validate, order.otp) order.close_price, order.close_price2, order.deadline, order.validate, order.otp)
self.log.info(order) self.log.info(f"Added order to %{order.type} %{order.volume} on {order.pair}")
self.update() self.update()
def update(self, full=False): def update(self, full=False):

View File

@ -1,17 +1,13 @@
import logging
import os import os
import pandas import pandas
from kraken_bot.Model import Model
from scipy.stats import linregress from scipy.stats import linregress
from kraken_bot.Model import Model
class LinearRegression(Model): class LinearRegression(Model):
def __init__(self, r_value_target): def __init__(self):
self.r_value_target = r_value_target self.r_value_target = float(os.getenv('R_VALUE_TARGET'))
self.log = logging.getLogger(__name__)
self.log.setLevel(
getattr(logging, os.getenv('LOG_LEVEL', 'INFO'), logging.INFO)
)
self.analysis = pandas.DataFrame({}) self.analysis = pandas.DataFrame({})
super().__init__( super().__init__(
interval = 1, interval = 1,
@ -54,5 +50,4 @@ class LinearRegression(Model):
) for asset_pair in self._filter_asset_pairs(tradable_asset_pairs).index ) for asset_pair in self._filter_asset_pairs(tradable_asset_pairs).index
}).transpose() }).transpose()
)) ))
self.log.info(f"Completed linear regression analysis of OHLC market data") self.log.debug(self.analysis)
self.log.info(self.analysis)

View File

@ -0,0 +1,62 @@
import asyncio
import logging
import os
from nio import AsyncClient, MatrixRoom, RoomMessageText
class MatrixHandler(logging.Handler):
def __init__(self):
super().__init__()
eric marked this conversation as resolved Outdated
Outdated
Review

AsyncClient will need to be executed like so:

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        pass

As such, it will need to be instantiated and started elsewhere with the necessary values passed in via parameters.

`AsyncClient` will need to be executed like so: ``` if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: pass ``` As such, it will need to be instantiated and started elsewhere with the necessary values passed in via parameters.
Outdated
Review

The HttpClient was used instead. Fortunately, the interface was compatible.

The `HttpClient` was used instead. Fortunately, the interface was compatible.
Outdated
Review

This is still an issue. The Matrix logger likely needs to be redesigned.

This is still an issue. The Matrix logger likely needs to be redesigned.
self.address = os.getenv('MATRIX_HOMESERVER_ADDRESS')
self.user_id = os.getenv('MATRIX_USER_ID')
self.user_password = os.getenv('MATRIX_USER_PASSWORD')
self.room_id = os.getenv('MATRIX_ROOM_ID')
self.device_id = os.getenv('MATRIX_DEVICE_ID')
def message_callback(self, room: MatrixRoom, event: RoomMessageText) -> None:
return
async def send_to_matrix(self, record):
client = AsyncClient(self.address, self.user_id)
await client.login(self.user_password, self.device_id)
client.add_event_callback(self.message_callback, RoomMessageText)
await client.room_send(
self.room_id,
message_type='m.room.message',
content={'msgtype': 'm.text', 'body': self.formatter.format(record)}
)
def emit(self, record):
asyncio.run(self.send_to_matrix(record))
class MatrixLogger:
def __init__(self, name):
self.log = logging.getLogger(name)
self.log.setLevel(os.getenv('LOG_LEVEL', 'INFO'))
console_handler = logging.StreamHandler()
console_handler.setLevel(os.getenv('LOG_LEVEL', 'INFO'))
console_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s'))
matrix_handler = MatrixHandler()
matrix_handler.setLevel(os.getenv('LOG_LEVEL', 'INFO'))
matrix_handler.setFormatter(logging.Formatter('%(levelname)s - %(name)s - %(message)s'))
self.log.addHandler(console_handler)
self.log.addHandler(matrix_handler)
def debug(self, message):
self.log.debug(message)
def info(self, message):
self.log.info(message)
def warning(self, message):
self.log.warning(message)
def error(self, message):
self.log.error(message)
def critical(self, message):
self.log.critical(message)

View File

@ -1,9 +1,12 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from kraken_bot.MatrixLogger import MatrixLogger
class Model(ABC): class Model(ABC):
def __init__(self, interval, ascending): def __init__(self, interval, ascending):
self.interval = interval self.interval = interval
self.ascending = ascending self.ascending = ascending
self.log = MatrixLogger(self.__class__.__name__)
@abstractmethod @abstractmethod
def since(): def since():

View File

@ -2,8 +2,8 @@ from kraken_bot.TradingStrategy import TradingStrategy
from kraken_bot.KrakenOrder import KrakenOrder from kraken_bot.KrakenOrder import KrakenOrder
class MyStrategy(TradingStrategy): class MyStrategy(TradingStrategy):
def __init__(self, investment_count, investment_volume): def __init__(self):
super().__init__(investment_count, investment_volume) super().__init__()
def update(self, tradable_asset_pairs, ohlc_data, market_analysis, account_balance): def update(self, tradable_asset_pairs, ohlc_data, market_analysis, account_balance):
self.orders = [] self.orders = []

View File

@ -1,10 +1,14 @@
import os
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from kraken_bot.KrakenOrder import KrakenOrder
from kraken_bot.MatrixLogger import MatrixLogger
class TradingStrategy(ABC): class TradingStrategy(ABC):
def __init__(self, investment_count, investment_volume): def __init__(self):
self.investment_count = investment_count self.investment_count = int(os.getenv('INVESTMENT_COUNT'))
self.investment_volume = investment_volume self.investment_volume = float(os.getenv('INVESTMENT_VOLUME'))
self.log = MatrixLogger(self.__class__.__name__)
self.orders = [] self.orders = []
@abstractmethod @abstractmethod

View File

@ -1,5 +1,7 @@
krakenex krakenex
matrix-nio
pykrakenapi pykrakenapi
python-dotenv python-dotenv
scipy
backtrader backtrader
matplotlib matplotlib