Skip to content

Commit

Permalink
3.0.0rc5
Browse files Browse the repository at this point in the history
  • Loading branch information
DogsTailFarmer committed Mar 3, 2024
1 parent 4990ff2 commit 37661c2
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 45 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 3.0.0rc5 - 2024-03-03
### Fix
* logging for Simulate mode

### Update
* Binance: handling `EXPIRED_IN_MATCH`

## 3.0.0rc1 - 2024-03-02
### Fix
# TODO * `cancel_order_call()`: not raised asyncio.TimeoutError on timeout
Expand Down
2 changes: 1 addition & 1 deletion martin_binance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__author__ = "Jerry Fedorenko"
__copyright__ = "Copyright © 2021 Jerry Fedorenko aka VM"
__license__ = "MIT"
__version__ = "3.0.0rc3"
__version__ = "3.0.0rc5"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down
14 changes: 13 additions & 1 deletion martin_binance/backtest/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
__author__ = "Jerry Fedorenko"
__copyright__ = "Copyright © 2024 Jerry Fedorenko aka VM"
__license__ = "MIT"
__version__ = "3.0.0rc2"
__version__ = "3.0.0rc4"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"


import asyncio
import importlib.util as iu
import logging.handlers
import stat
import sys
from decimal import Decimal
Expand All @@ -21,6 +22,7 @@
import optuna
import ujson as json

from martin_binance import LOG_PATH

OPTIMIZER = Path(__file__).absolute()
OPTIMIZER.chmod(OPTIMIZER.stat().st_mode | stat.S_IEXEC)
Expand Down Expand Up @@ -84,7 +86,17 @@ async def run_optimize(*args):


if __name__ == "__main__":
logger = logging.getLogger('logger_S')
logger.level = logging.INFO
formatter = logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s")
#
fh = logging.handlers.RotatingFileHandler(Path(LOG_PATH, sys.argv[5]), maxBytes=500000, backupCount=5)
fh.setFormatter(formatter)
fh.setLevel(logging.INFO)
logger.addHandler(fh)
#
study = optimize(sys.argv[1], sys.argv[2], int(sys.argv[3]), storage_name=sys.argv[4])
logger.info(f"Optimal parameters: {study.best_params} for get {study.best_value}")
new_value = study.best_value
_value = study.get_trials()[0].value
if new_value > _value:
Expand Down
20 changes: 11 additions & 9 deletions martin_binance/cli_0_BTCUSDT.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ ex.REVERSE_INIT_AMOUNT = Decimal('0')
ex.REVERSE_STOP = False # Stop after ending reverse cycle
# Backtest mode parameters
ex.MODE = 'T' # 'T' - Trade, 'TC' - Trade and Collect, 'S' - Simulate
ex.SAVE_DS = False # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 24 * 60 * 60 # sec, timetable for save data portion
ex.SAVE_DS = True # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 4 * 60 * 60 # sec, timetable for save data portion
ex.SELF_OPTIMIZATION = True # Cyclic self-optimization of parameters, together with MODE == 'TC'
ex.N_TRIALS = 250 # Number of optimization cycles for optuna study in self optimization mode
################################################################
Expand All @@ -114,15 +114,17 @@ def trade(strategy=None):
import logging.handlers
# For autoload last state
ex.LOAD_LAST_STATE = 1 if len(sys.argv) > 1 else 0
#
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}{'_S' if ex.MODE == 'S' else ''}.log")
ex.LAST_STATE_FILE = Path(LAST_STATE_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.json")
#
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
if ex.MODE == 'S':
_logger = logging.getLogger('logger_S')
else:
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.log")
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
_logger.propagate = False
#
if strategy is None:
Expand Down
20 changes: 11 additions & 9 deletions martin_binance/cli_1_BTCUSDT.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ ex.REVERSE_INIT_AMOUNT = Decimal('0')
ex.REVERSE_STOP = False # Stop after ending reverse cycle
# Backtest mode parameters
ex.MODE = 'T' # 'T' - Trade, 'TC' - Trade and Collect, 'S' - Simulate
ex.SAVE_DS = False # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 24 * 60 * 60 # sec, timetable for save data portion
ex.SAVE_DS = True # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 4 * 60 * 60 # sec, timetable for save data portion
ex.SELF_OPTIMIZATION = True # Cyclic self-optimization of parameters, together with MODE == 'TC'
ex.N_TRIALS = 250 # Number of optimization cycles for optuna study in self optimization mode
################################################################
Expand All @@ -114,15 +114,17 @@ def trade(strategy=None):
import logging.handlers
# For autoload last state
ex.LOAD_LAST_STATE = 1 if len(sys.argv) > 1 else 0
#
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}{'_S' if ex.MODE == 'S' else ''}.log")
ex.LAST_STATE_FILE = Path(LAST_STATE_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.json")
#
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
if ex.MODE == 'S':
_logger = logging.getLogger('logger_S')
else:
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.log")
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
_logger.propagate = False
#
if strategy is None:
Expand Down
20 changes: 11 additions & 9 deletions martin_binance/cli_2_TESTBTCTESTUSDT.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ ex.REVERSE_INIT_AMOUNT = Decimal('0')
ex.REVERSE_STOP = False # Stop after ending reverse cycle
# Backtest mode parameters
ex.MODE = 'T' # 'T' - Trade, 'TC' - Trade and Collect, 'S' - Simulate
ex.SAVE_DS = False # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 24 * 60 * 60 # sec, timetable for save data portion
ex.SAVE_DS = True # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 4 * 60 * 60 # sec, timetable for save data portion
ex.SELF_OPTIMIZATION = True # Cyclic self-optimization of parameters, together with MODE == 'TC'
ex.N_TRIALS = 250 # Number of optimization cycles for optuna study in self optimization mode
################################################################
Expand All @@ -114,15 +114,17 @@ def trade(strategy=None):
import logging.handlers
# For autoload last state
ex.LOAD_LAST_STATE = 1 if len(sys.argv) > 1 else 0
#
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}{'_S' if ex.MODE == 'S' else ''}.log")
ex.LAST_STATE_FILE = Path(LAST_STATE_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.json")
#
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
if ex.MODE == 'S':
_logger = logging.getLogger('logger_S')
else:
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.log")
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
_logger.propagate = False
#
if strategy is None:
Expand Down
20 changes: 11 additions & 9 deletions martin_binance/cli_3_BTCUSDT.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ ex.REVERSE_INIT_AMOUNT = Decimal('0')
ex.REVERSE_STOP = False # Stop after ending reverse cycle
# Backtest mode parameters
ex.MODE = 'T' # 'T' - Trade, 'TC' - Trade and Collect, 'S' - Simulate
ex.SAVE_DS = False # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 24 * 60 * 60 # sec, timetable for save data portion
ex.SAVE_DS = True # Save session result data (ticker, orders) for compare
ex.SAVE_PERIOD = 4 * 60 * 60 # sec, timetable for save data portion
ex.SELF_OPTIMIZATION = True # Cyclic self-optimization of parameters, together with MODE == 'TC'
ex.N_TRIALS = 250 # Number of optimization cycles for optuna study in self optimization mode
################################################################
Expand All @@ -114,15 +114,17 @@ def trade(strategy=None):
import logging.handlers
# For autoload last state
ex.LOAD_LAST_STATE = 1 if len(sys.argv) > 1 else 0
#
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}{'_S' if ex.MODE == 'S' else ''}.log")
ex.LAST_STATE_FILE = Path(LAST_STATE_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.json")
#
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
if ex.MODE == 'S':
_logger = logging.getLogger('logger_S')
else:
log_file = Path(LOG_PATH, f"{ex.ID_EXCHANGE}_{ex.SYMBOL}.log")
_logger = logging.getLogger('logger')
_logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10)
handler.setFormatter(logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s"))
_logger.addHandler(handler)
_logger.propagate = False
#
if strategy is None:
Expand Down
20 changes: 13 additions & 7 deletions martin_binance/strategy_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
__author__ = "Jerry Fedorenko"
__copyright__ = "Copyright © 2021 Jerry Fedorenko aka VM"
__license__ = "MIT"
__version__ = "3.0.0rc3"
__version__ = "3.0.0rc5"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand All @@ -13,6 +13,7 @@
import csv
import logging
import queue
import os
import random
import sqlite3
import time
Expand Down Expand Up @@ -44,7 +45,10 @@
from martin_binance.lib import Candle, TradingCapabilityManager, Ticker, FundsEntry, OrderBook, Style, LogLevel, \
any2str, PrivateTrade, Order, convert_from_minute, write_log, OrderUpdate, load_file, load_last_state, Klines

logger = logging.getLogger('logger')
if prm.MODE == 'S':
logger = logging.getLogger('logger_S')
else:
logger = logging.getLogger('logger')
loop = asyncio.get_event_loop()
color_init()

Expand Down Expand Up @@ -317,7 +321,8 @@ async def backtest_control(self):
f"{self.exchange}_{self.symbol}",
Path(self.session_root, Path(prm.PARAMS).name),
str(prm.N_TRIALS),
f"sqlite:///{storage_name}"
f"sqlite:///{storage_name}",
f"{prm.ID_EXCHANGE}_{prm.SYMBOL}_S.log"
)
_res = orjson.loads(_res)
except (asyncio.CancelledError, KeyboardInterrupt):
Expand All @@ -327,7 +332,7 @@ async def backtest_control(self):
else:
storage_name.replace(storage_name.with_name('study.db'))
if _res:
self.message_log(f"Updating strategy parameters from backtest optimal,"
self.message_log(f"Updating parameters from backtest,"
f" predicted value {_res.pop('_value')} ->"
f" {_res.pop('new_value')}",
color=Style.B_WHITE, tlg=True)
Expand Down Expand Up @@ -822,7 +827,7 @@ async def cancel_order_call(self, _id: int, cancel_all=False, count=0):
finally:
if _fetch_order:
res = await self.fetch_order(_id, _filled_update_call=True)
if res.get('status') == 'CANCELED':
if res.get('status') in ('CANCELED', 'EXPIRED_IN_MATCH'):
await self.cancel_order_handler(_id, cancel_all)
elif res.get('status') == 'FILLED':
if _id in self.canceled_order_id:
Expand Down Expand Up @@ -1632,8 +1637,9 @@ async def main(self, _symbol):
if restored:
loop.create_task(self.heartbeat(self.session))
loop.create_task(save_to_csv())
except SystemExit as e:
raise e
except (KeyboardInterrupt, SystemExit):
# noinspection PyProtectedMember, PyUnresolvedReferences
os._exit(1)

# region AbstractMethod
@abstractmethod
Expand Down

0 comments on commit 37661c2

Please sign in to comment.