Skip to content

Commit

Permalink
3.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
DogsTailFarmer committed Apr 3, 2024
1 parent f327f5e commit 42e1267
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 63 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 3.0.2 - 2024-04-03
### Fix
* `Backtesting`: updating the balances at slippage
* `class PrivateTrade:` convert trade_id to int()
* `Backtest control`: orjson.JSONDecodeError: unexpected character: line 1 column 1 (char 0)

### Update
* Up requirements for exchanges-wrapper==2.1.7
* Some minor improvement

## 3.0.1 - 2024-03-31
### Refined and added new features
* Project architecture
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.1"
__version__ = "3.0.2"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down
44 changes: 23 additions & 21 deletions martin_binance/backtest/exchange_simulator.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.1"
__version__ = "3.0.2"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down Expand Up @@ -49,13 +49,14 @@ def on_order_canceled(self, side: str, amount: Decimal, price: Decimal):
self.base['free'] += amount
self.base['locked'] -= amount

def on_order_filled(self, side: str, amount: Decimal, price: Decimal, fee: Decimal):
def on_order_filled(self, side: str, amount: Decimal, price: Decimal, last_price: Decimal, fee: Decimal):
if side == 'BUY':
self.base['free'] += amount - fee * amount / 100
self.quote['locked'] -= amount * price
self.quote['free'] += amount * (price - last_price)
else:
self.base['locked'] -= amount
self.quote['free'] += amount * price - fee * (amount * price) / 100
self.quote['free'] += amount * last_price - fee * (amount * last_price) / 100


class Order:
Expand Down Expand Up @@ -184,7 +185,6 @@ def create_order(
# Market event
self.market_ids.append(order_id)

# print(f"create_order.order: {vars(order)}")
return {'symbol': order.symbol,
'orderId': order.order_id,
'orderListId': order.order_list_id,
Expand Down Expand Up @@ -218,23 +218,23 @@ def cancel_order(self, order_id: int, ts: int):
self.grid_sell[ts] = self.orders_sell
except Exception as ex:
raise UserWarning(f"Order {order_id} not active: {ex}") from ex
else:
self.orders[order_id] = order
self.funds.on_order_canceled(order.side, order.orig_qty, order.price)
return {'symbol': order.symbol,
'origClientOrderId': order.client_order_id,
'orderId': order.order_id,
'orderListId': order.order_list_id,
'clientOrderId': 'qwert',
'price': str(order.price),
'origQty': str(order.orig_qty),
'executedQty': str(order.executed_qty),
'cummulativeQuoteQty': str(order.cummulative_quote_qty),
'status': order.status,
'timeInForce': order.time_in_force,
'type': order.type,
'side': order.side,
'selfTradePreventionMode': order.self_trade_prevention_mode}

self.orders[order_id] = order
self.funds.on_order_canceled(order.side, order.orig_qty - order.executed_qty, order.price)
return {'symbol': order.symbol,
'origClientOrderId': order.client_order_id,
'orderId': order.order_id,
'orderListId': order.order_list_id,
'clientOrderId': 'qwert',
'price': str(order.price),
'origQty': str(order.orig_qty),
'executedQty': str(order.executed_qty),
'cummulativeQuoteQty': str(order.cummulative_quote_qty),
'status': order.status,
'timeInForce': order.time_in_force,
'type': order.type,
'side': order.side,
'selfTradePreventionMode': order.self_trade_prevention_mode}

def on_ticker_update(self, ticker: {}, ts: int) -> [dict]:
filled_buy_id = []
Expand Down Expand Up @@ -330,9 +330,11 @@ def on_ticker_update(self, ticker: {}, ts: int) -> [dict]:
}
#
orders_filled.append(res)

self.funds.on_order_filled(
order.side,
order.last_executed_quantity,
order.price,
order.last_executed_price,
self.fee_taker if order_id in self.market_ids else self.fee_maker
)
Expand Down
9 changes: 5 additions & 4 deletions martin_binance/backtest/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ async def run_optimize(*args):
logger.addHandler(fh)
#
prm_best = json.loads(sys.argv[5])
logger.info(f"Previous best params: {prm_best}")
try:
study = optimize(
sys.argv[1],
Expand All @@ -115,11 +116,11 @@ async def run_optimize(*args):
logger.info(f"optimizer: {ex}")
else:
new_value = round(study.best_value, ndigits=6)
logger.info(f"Optimal parameters: {study.best_params} for get {new_value}")
bp = {k: int(any2str(v)) if isinstance(v, int) else float(any2str(v)) for k, v in study.best_params.items()}
logger.info(f"Optimal parameters: {bp} for get {new_value}")
_value = round(study.get_trials()[0].value, ndigits=6)
if not prm_best or new_value > _value:
res = study.best_params
res |= {'new_value': any2str(new_value), '_value': any2str(_value)}
print(json.dumps(res))
bp |= {'new_value': any2str(new_value), '_value': any2str(_value)}
print(json.dumps(bp))
else:
print(json.dumps({}))
12 changes: 5 additions & 7 deletions martin_binance/executor.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.1"
__version__ = "3.0.2"
__maintainer__ = "Jerry Fedorenko"
__contact__ = 'https://github.com/DogsTailFarmer'
##################################################################
Expand Down Expand Up @@ -124,7 +124,6 @@ def __init__(self, call_super=True):
#
schedule.every(5).minutes.do(self.event_grid_update)
schedule.every(5).seconds.do(self.event_processing)
schedule.every(1).minutes.do(self.event_grid_only_release)
schedule.every().minute.at(":30").do(self.event_grid_only_release)
schedule.every().minute.at(":35").do(self.event_update_tp)
schedule.every(2).seconds.do(self.event_exec_command)
Expand Down Expand Up @@ -416,7 +415,6 @@ def event_processing(self):
self.wait_wss_refresh['allow_grid_shift'],
self.wait_wss_refresh['additional_grid'],
self.wait_wss_refresh['grid_update'])
self.event_update_tp()
if self.wait_refunding_for_start or self.tp_order_hold or self.grid_hold:
self.get_buffered_funds()
if self.reverse_hold:
Expand All @@ -443,10 +441,10 @@ def event_processing(self):
self.start_reverse_time = self.get_time()

def event_update_tp(self):
if ADAPTIVE_TRADE_CONDITION and self.stable_state():
if self.tp_order_id and not self.tp_part_amount_first and self.get_time() - self.tp_order[3] > 60 * 15:
self.message_log("Update TP order", color=Style.B_WHITE)
self.place_profit_order()
if ADAPTIVE_TRADE_CONDITION and self.stable_state() \
and self.tp_order_id and not self.tp_part_amount_first and self.get_time() - self.tp_order[3] > 60 * 15:
self.message_log("Update TP order", color=Style.B_WHITE)
self.place_profit_order()

def event_grid_only_release(self):
if self.grid_only_restart and START_ON_BUY and AMOUNT_FIRST:
Expand Down
4 changes: 2 additions & 2 deletions martin_binance/lib.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.1"
__version__ = "3.0.2"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down Expand Up @@ -234,7 +234,7 @@ def __init__(self, _trade: {}) -> None:
self.amount = Decimal(_trade["qty"])
self.buy = _trade.get('isBuyer', False)
self.is_maker = _trade.get('isMaker', False)
self.id = _trade["id"]
self.id = int(_trade["id"])
self.order_id = int(_trade["orderId"])
self.price = Decimal(_trade["price"])
self.commission = Decimal(_trade.get('commission', "0"))
Expand Down
52 changes: 26 additions & 26 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.1"
__version__ = "3.0.2"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand All @@ -15,15 +15,14 @@
import queue
import os
import random
import shutil
import sqlite3
import time
import traceback
from abc import abstractmethod
from datetime import datetime, timedelta, timezone
from decimal import Decimal
from pathlib import Path
from shutil import rmtree, copy
from shutil import rmtree, copy, make_archive
from typing import Dict, List

import jsonpickle
Expand Down Expand Up @@ -338,31 +337,32 @@ async def backtest_control(self):
except Exception as err:
self.message_log(f"Backtest control: {err}", log_level=logging.ERROR)
self.message_log(f"Exception traceback: {traceback.format_exc()}", log_level=logging.DEBUG)
else:
storage_name.replace(storage_name.with_name('study.db'))
if prm_best:
_prm_best = dict(prm_best)
self.message_log(
f"Updating parameters from backtest,"
f" predicted value {prm_best.pop('_value')} -> {prm_best.pop('new_value')}",
color=Style.B_WHITE,
tlg=True
)
for key, value in prm_best.items():
self.message_log(f"{key}: {getattr(prm, key)} -> {value}")
setattr(
prm, key,
value if isinstance(value, int) or key in PARAMS_FLOAT else Decimal(f"{value}")
)
l_m = str(
datetime.now(timezone.utc).replace(tzinfo=None) - _ts + timedelta(seconds=prm.SAVE_PERIOD)
).rsplit('.')[0]
break
#
storage_name.replace(storage_name.with_name('study.db'))
if prm_best:
_prm_best = dict(prm_best)
self.message_log(
f"Strategy parameters are optimal now. Optimization cycle duration {l_m}",
f"Updating parameters from backtest,"
f" predicted value {prm_best.pop('_value')} -> {prm_best.pop('new_value')}",
color=Style.B_WHITE,
tlg=True
)
restart = True
for key, value in prm_best.items():
self.message_log(f"{key}: {getattr(prm, key)} -> {value}")
setattr(
prm, key,
value if isinstance(value, int) or key in PARAMS_FLOAT else Decimal(f"{value}")
)
l_m = str(
datetime.now(timezone.utc).replace(tzinfo=None) - _ts + timedelta(seconds=prm.SAVE_PERIOD)
).rsplit('.')[0]
self.message_log(
f"Strategy parameters are optimal now. Optimization cycle duration {l_m}",
color=Style.B_WHITE,
tlg=True
)
restart = True
else:
break

Expand Down Expand Up @@ -442,7 +442,7 @@ def session_data_handler(self):
df_grid_buy.index = pd.to_datetime(df_grid_buy.index, unit='ms')
df_grid_buy.to_pickle(Path(session_data, "buy.pkl"))

shutil.make_archive(str(Path(self.session_root, "raw_bak")), 'zip', self.session_root, 'raw')
make_archive(str(Path(self.session_root, "raw_bak")), 'zip', self.session_root, 'raw')
self.message_log(f"Stream data for backtesting saved to {self.session_root}")

def parquet_declare(self, raw_path):
Expand Down Expand Up @@ -1704,7 +1704,7 @@ def get_sum_profit(self):
raise NotImplementedError

@abstractmethod
def get_free_assets(self, **kwargs):
def get_free_assets(self, *args, **kwargs):
raise NotImplementedError

@abstractmethod
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dynamic = ["version", "description"]
requires-python = ">=3.9"

dependencies = [
"exchanges-wrapper==2.1.6",
"exchanges-wrapper==2.1.7",
"jsonpickle==3.0.2",
"psutil==5.9.6",
"requests==2.31.0",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
exchanges-wrapper==2.1.6
exchanges-wrapper==2.1.7
jsonpickle==3.0.2
psutil==5.9.6
requests==2.31.0
Expand Down

0 comments on commit 42e1267

Please sign in to comment.