Skip to content

Commit

Permalink
3.0.0rc19
Browse files Browse the repository at this point in the history
  • Loading branch information
DogsTailFarmer committed Mar 11, 2024
1 parent 8b82de9 commit 0b66bcc
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 83 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.0rc19 - 2024-03-11
### Update
* Replaced checking price when calculating TP vs updating price based on order book if error occurred
* Don't unload assets on *`test`* accounts for avoid overload limited `coinmarketcap` API
* Startup sequence optimization
* Up requirements for exchanges-wrapper==2.0.1

## 3.0.0rc18 - 2024-03-10
### Update
* Added price check when calculating TP in relation to the average filling price of the last grid order.
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.0rc18"
__version__ = "3.0.0rc19"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down
2 changes: 2 additions & 0 deletions martin_binance/backtest/exchange_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

# TODO Add part filling event

from decimal import Decimal
import pandas as pd

Expand Down
10 changes: 8 additions & 2 deletions martin_binance/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import asyncio
import random
import logging

import grpclib.exceptions
import shortuuid

from exchanges_wrapper import martin as mr, Channel, Status, GRPCError
Expand Down Expand Up @@ -86,7 +88,9 @@ async def send_request(self, _request, _request_type, **kwargs):
try:
res = await _request(_request_type(**kwargs))
except asyncio.CancelledError:
pass # Task cancellation should not be logged as an error.
pass # Task cancellation should not be logged as an error
except grpclib.exceptions.StreamTerminatedError:
logger.warning("Have not connection to gRPC server")
except GRPCError as ex:
status_code = ex.status
if (
Expand Down Expand Up @@ -120,7 +124,9 @@ async def for_request(self, _request, _request_type, **kwargs):
async for res in _request(_request_type(**kwargs)):
yield res
except asyncio.CancelledError:
pass # Task cancellation should not be logged as an error.
pass # Task cancellation should not be logged as an error
except grpclib.exceptions.StreamTerminatedError:
logger.warning("WSS connection to gRPC server was terminated")
except GRPCError as ex:
status_code = ex.status
logger.warning(f"Exception on WSS loop: {status_code.name}, {ex.message}")
Expand Down
33 changes: 12 additions & 21 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.0rc18"
__version__ = "3.0.0rc19"
__maintainer__ = "Jerry Fedorenko"
__contact__ = 'https://github.com/DogsTailFarmer'

Expand Down Expand Up @@ -53,7 +53,6 @@ def __init__(self):
self.tp_order_id = None # + Take profit order id
self.tp_wait_id = None # -
self.tp_order = () # - (id, buy, amount, price, local_time()) Placed take profit order
self.tp_error = False # Flag when can't place tp
self.tp_order_hold = {} # - Save unreleased take profit order
self.tp_hold = False # - Flag for replace take profit order
self.tp_cancel = False # - Wanted cancel tp order after successes place and Start()
Expand All @@ -77,7 +76,7 @@ def __init__(self):
self.shift_grid_threshold = None # - Price level of shift grid threshold for current cycle
self.f_currency = '' # - First currency name
self.s_currency = '' # - Second currency name
self.last_shift_time = None # +
self.last_shift_time = None # -
self.avg_rate = O_DEC # - Flow average rate for trading pair
#
self.grid_hold = {} # - Save for later create grid orders
Expand Down Expand Up @@ -383,9 +382,6 @@ def save_strategy_state(self, return_only=False) -> Dict[str, str]:
self.queue_to_db.put(data_to_db)
if self.wait_refunding_for_start or self.tp_order_hold or self.grid_hold:
self.get_buffered_funds()
if self.tp_error:
self.tp_error = False
self.place_profit_order(after_error=True)
if self.reverse_hold:
if self.start_reverse_time:
if self.get_time() - self.start_reverse_time > 2 * SHIFT_GRID_DELAY:
Expand Down Expand Up @@ -418,7 +414,6 @@ def save_strategy_state(self, return_only=False) -> Dict[str, str]:
'cycle_time_reverse': json.dumps(self.cycle_time_reverse, default=str),
'deposit_first': json.dumps(self.deposit_first),
'deposit_second': json.dumps(self.deposit_second),
'last_shift_time': json.dumps(self.last_shift_time),
'martin': json.dumps(self.martin),
'order_q': json.dumps(self.order_q),
'orders': json.dumps(self.orders_grid.get()),
Expand Down Expand Up @@ -476,7 +471,6 @@ def restore_strategy_state(self, strategy_state: Dict[str, str] = None, restore=
)
self.deposit_first = f2d(json.loads(strategy_state.get('deposit_first')))
self.deposit_second = f2d(json.loads(strategy_state.get('deposit_second')))
self.last_shift_time = json.loads(strategy_state.get('last_shift_time')) or self.get_time()
self.martin = f2d(json.loads(strategy_state.get('martin')))
self.order_q = json.loads(strategy_state.get('order_q'))
self.orders_grid.restore(json.loads(strategy_state.get('orders')))
Expand Down Expand Up @@ -524,6 +518,7 @@ def restore_strategy_state(self, strategy_state: Dict[str, str] = None, restore=
self.message_log("Restore, strategy stopped. Need manual action", tlg=True)
return
self.start_after_shift = False
self.last_shift_time = self.get_time()
self.avg_rate = self.get_buffered_ticker().last_price
#
open_orders = self.get_buffered_open_orders()
Expand Down Expand Up @@ -944,11 +939,12 @@ def debug_output(self):
self.message_log(f"\n"
f"! =======================================\n"
f"! debug output: ver: {self.client.srv_version}: {HEAD_VERSION}+{__version__}+{msb_ver}\n"
f"! sum_amount_first: {self.sum_amount_first}, sum_amount_second: {self.sum_amount_second}\n"
f"! part_amount: {self.part_amount}\n"
f"! deposit_first: {self.deposit_first}, deposit_second: {self.deposit_second}\n"
f"! initial_first: {self.initial_first}, initial_second: {self.initial_second}\n"
f"! initial_reverse_first: {self.initial_reverse_first},"
f" initial_reverse_second: {self.initial_reverse_second}\n"
f"! sum_amount_first: {self.sum_amount_first}, sum_amount_second: {self.sum_amount_second}\n"
f"! part_amount: {self.part_amount}\n"
f"! reverse_init_amount: {self.reverse_init_amount}\n"
f"! reverse_target_amount: {self.reverse_target_amount}\n"
f"! tp_order: {self.tp_order}\n"
Expand All @@ -957,7 +953,6 @@ def debug_output(self):
f"! profit_first: {self.profit_first}, profit_second: {self.profit_second}\n"
f"! part_profit_first: {self.part_profit_first},"
f" part_profit_second: {self.part_profit_second}\n"
f"! deposit_first: {self.deposit_first}, deposit_second: {self.deposit_second}\n"
f"! command: {self.command}\n"
f"! reverse: {self.reverse}\n"
f"! Profit: {self.get_sum_profit()}\n"
Expand Down Expand Up @@ -1342,7 +1337,6 @@ def place_profit_order(self, by_market=False, after_error=False) -> None:
self.message_log('Hold take profit order, replace existing', color=Style.B_WHITE)
else:
buy_side = not self.cycle_buy
# Calculate take profit order
tp = self.calc_profit_order(buy_side, by_market=by_market)
price = tp.get('price')
amount = tp.get('amount')
Expand All @@ -1357,23 +1351,20 @@ def place_profit_order(self, by_market=False, after_error=False) -> None:
fund = funds.get(self.f_currency, O_DEC)
fund = fund.available if fund else O_DEC
if buy_side and amount * price > fund:
# Save take profit order and wait update balance
self.tp_order_hold = {'buy_side': buy_side,
'amount': amount * price,
'by_market': by_market,
'timestamp': self.get_time()}
self.message_log(f"Hold TP order for Buy {amount} {self.f_currency} by {price},"
f" wait {amount * price} {self.s_currency}, exist: {any2str(fund)}")
elif not buy_side and amount > fund:
# Save take profit order and wait update balance
self.tp_order_hold = {'buy_side': buy_side,
'amount': amount,
'by_market': by_market,
'timestamp': self.get_time()}
self.message_log(f"Hold TP order for Sell {amount} {self.f_currency}"
f" by {price}, exist {any2str(fund)}")
else:
# Create take profit order
self.message_log(f"Create {'Buy' if buy_side else 'Sell'} take profit order,"
f" vlm: {amount}, price: {price}, profit (incl.fee): {profit}%")
self.tp_target = target
Expand Down Expand Up @@ -1508,7 +1499,7 @@ def calc_profit_order(self, buy_side: bool, by_market=False, log_output=True) ->
amount = target = target_amount_first
# Calculate depo amount in second
amount_s = self.round_truncate(self.sum_amount_second, base=False, _rounding=ROUND_HALF_DOWN)
price = tcm.round_price(min(amount_s / target_amount_first, self.avg_rate), ROUND_FLOOR)
price = tcm.round_price(amount_s / target_amount_first, ROUND_FLOOR)
else:
step_size_s = self.round_truncate((step_size_f * self.avg_rate), base=False, _rounding=ROUND_CEILING)
# Calculate target amount for second
Expand All @@ -1520,7 +1511,7 @@ def calc_profit_order(self, buy_side: bool, by_market=False, log_output=True) ->
target_amount_second = self.round_truncate(target_amount_second, base=False, _rounding=ROUND_CEILING)
# Calculate depo amount in first
amount = self.round_truncate(self.sum_amount_first, base=True, _rounding=ROUND_FLOOR)
price = tcm.round_price(max(target_amount_second / amount, self.avg_rate), ROUND_HALF_UP)
price = tcm.round_price(target_amount_second / amount, ROUND_HALF_UP)
target = amount * price
# Calc real margin for TP
profit = (100 * (target - tp_amount) / tp_amount).quantize(Decimal("1.0123"), rounding=ROUND_FLOOR)
Expand Down Expand Up @@ -2341,9 +2332,9 @@ def on_order_update_ex(self, update: OrderUpdate) -> None:
self.message_log(f"Executed amount: First: {any2str(amount_first)}, Second: {any2str(amount_second)},"
f" price: {any2str(self.avg_rate)}")
if update.status in (OrderUpdate.FILLED, OrderUpdate.ADAPTED_AND_FILLED):
if not GRID_ONLY:
self.shift_grid_threshold = None
if self.orders_grid.exist(update.original_order.id):
if not GRID_ONLY:
self.shift_grid_threshold = None
self.ts_grid_update = self.get_time()
self.orders_grid.remove(update.original_order.id)
if self.orders_save:
Expand Down Expand Up @@ -2511,7 +2502,7 @@ def on_place_order_error(self, place_order_id: int, error: str) -> None:
self.cancel_grid()
elif place_order_id == self.tp_wait_id:
self.tp_wait_id = None
self.tp_error = True
self.place_profit_order(after_error=True)

if 'FAILED_PRECONDITION' in error:
self.command = 'stopped'
Expand Down Expand Up @@ -2591,7 +2582,7 @@ def restore_state_before_backtesting_ex(self, saved_state):
self.reverse = json.loads(saved_state.get('reverse'))
self.deposit_first = f2d(json.loads(saved_state.get('deposit_first')))
self.deposit_second = f2d(json.loads(saved_state.get('deposit_second')))
self.last_shift_time = json.loads(saved_state.get('last_shift_time')) or self.get_time()
self.last_shift_time = self.get_time()
self.order_q = json.loads(saved_state.get('order_q'))
self.orders_grid.restore(json.loads(saved_state.get('orders')))
self.orders_hold.restore(json.loads(saved_state.get('orders_hold')))
Expand Down
Loading

0 comments on commit 0b66bcc

Please sign in to comment.