Skip to content

Commit

Permalink
1.2.6-16
Browse files Browse the repository at this point in the history
fixed #28
changed initial checks to work with a small depo
  • Loading branch information
DogsTailFarmer committed Sep 12, 2022
1 parent e2e654d commit f4693ab
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 103 deletions.
2 changes: 1 addition & 1 deletion margin_req.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ unicodedata2==14.0.0
unittest2==1.1.0
wheel==0.31.1
wmi==1.5.1
martin-binance==1.2.6
martin-binance==1.2.6
2 changes: 1 addition & 1 deletion martin_binance/__init__.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__ = "1.2.6-15"
__version__ = "1.2.6-16"
__maintainer__ = "Jerry Fedorenko"
__contact__ = "https://github.com/DogsTailFarmer"

Expand Down
179 changes: 80 additions & 99 deletions martin_binance/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ class Strategy(StrategyBase):
all_order_exist = StrategyBase.all_order_exist

##############################################################
# strategy logic methods
# strategy control methods
##############################################################
def __init__(self):
super().__init__()
Expand Down Expand Up @@ -779,76 +779,34 @@ def init(self, check_funds: bool = True) -> None: # skipcq: PYL-W0221
if last_price:
print('Last ticker price: ', last_price)
self.avg_rate = f2d(last_price)
df = self.get_buffered_funds().get(self.f_currency, 0)
df = df.available if df else 0
if USE_ALL_FIRST_FUND and df and self.cycle_buy:
self.message_log('Check USE_ALL_FIRST_FUND parameter. You may have loss on Reverse cycle',
color=Style.B_WHITE)
if self.cycle_buy:
ds = self.get_buffered_funds().get(self.s_currency, 0)
ds = ds.available if ds else 0
if check_funds and self.deposit_second > f2d(ds):
self.message_log('Not enough second coin for Buy cycle!', color=Style.B_RED)
if STANDALONE:
raise SystemExit(1)
first_order_vlm = self.deposit_second * 1 * (1 - self.martin) / (1 - self.martin**ORDER_Q)
first_order_vlm /= self.avg_rate
amount_min = tcm.get_min_buy_amount(last_price)
else:
if USE_ALL_FIRST_FUND:
self.deposit_first = f2d(df)
else:
if check_funds and self.deposit_first > f2d(df):
self.message_log('Not enough first coin for Sell cycle!', color=Style.B_RED)
if STANDALONE:
raise SystemExit(1)
first_order_vlm = self.deposit_first * 1 * (1 - self.martin) / (1 - pow(self.martin, ORDER_Q))
amount_min = tcm.get_min_sell_amount(last_price)
if not GRID_ONLY and PROFIT_MAX < 100:
# Calculate the recommended size of the first grid order depending on the step_size
step_size = tcm.get_minimal_amount_change(amount_min)
k_m = 1 - float(PROFIT_MAX) / 100
amount_first_grid = (step_size * last_price / ((1 / k_m) - 1))
# For Bitfinex test accounts correction
if (amount_first_grid >= float(self.deposit_second) if self.cycle_buy else float(self.deposit_first) or
amount_first_grid >= tcm.get_max_sell_amount(0)):
amount_first_grid /= ORDER_Q
#
if self.first_run and check_funds:
df = self.get_buffered_funds().get(self.f_currency, 0)
df = df.available if df else 0
if USE_ALL_FIRST_FUND and df and self.cycle_buy:
self.message_log('Check USE_ALL_FIRST_FUND parameter. You may have loss on Reverse cycle',
color=Style.B_WHITE)
if self.cycle_buy:
if amount_first_grid > 80 * self.deposit_second / 100:
self.message_log(f"Recommended size of the first grid order {amount_first_grid:f} too large for"
f" a small deposit {self.deposit_second}", log_level=LogLevel.ERROR)
if STANDALONE and self.first_run:
ds = self.get_buffered_funds().get(self.s_currency, 0)
ds = ds.available if ds else 0
if self.deposit_second > f2d(ds):
self.message_log('Not enough second coin for Buy cycle!', color=Style.B_RED)
if STANDALONE:
raise SystemExit(1)
elif amount_first_grid > 20 * self.deposit_second / 100:
self.message_log(f"Recommended size of the first grid order {amount_first_grid:f} it is rather"
f" big for a small deposit {self.deposit_second}", log_level=LogLevel.WARNING)
depo = self.deposit_second
else:
amount_first_grid /= last_price
if amount_first_grid > 80 * self.deposit_first / 100:
self.message_log(f"Recommended size of the first grid order {amount_first_grid:f} too large for"
f" a small deposit {self.deposit_first}", log_level=LogLevel.ERROR)
if STANDALONE and self.first_run:
raise SystemExit(1)
elif amount_first_grid > 20 * self.deposit_first / 100:
self.message_log(f"Recommended size of the first grid order {amount_first_grid:f} it is rather"
f" big for a small deposit {self.deposit_first}", log_level=LogLevel.WARNING)
#
if self.cycle_buy and first_order_vlm < tcm.get_min_buy_amount(last_price):
self.message_log(f"Total deposit {AMOUNT_SECOND}{self.s_currency}"
f" not enough for min amount for {ORDER_Q} orders.", color=Style.B_RED)
if STANDALONE and self.first_run:
raise SystemExit(1)
elif not self.cycle_buy and first_order_vlm < tcm.get_min_sell_amount(last_price):
self.message_log(f"Total deposit {self.deposit_first}{self.f_currency}"
f" not enough for min amount for {ORDER_Q} orders.", color=Style.B_RED)
if STANDALONE and self.first_run:
raise SystemExit(1)
buy_amount = tcm.get_min_buy_amount(last_price)
sell_amount = tcm.get_min_sell_amount(last_price)
print(f"buy_amount: {buy_amount}, sell_amount: {sell_amount}")
if USE_ALL_FIRST_FUND:
self.deposit_first = f2d(df)
else:
if self.deposit_first > f2d(df):
self.message_log('Not enough first coin for Sell cycle!', color=Style.B_RED)
if STANDALONE:
raise SystemExit(1)
depo = self.deposit_first
self.place_grid(self.cycle_buy, depo, self.reverse_target_amount, init_calc_only=True)
else:
print('Actual price not received, initialization checks skipped')
print("Can't get actual price, initialization checks stopped")
if STANDALONE:
raise SystemExit(1)
# self.message_log('End Init section')

@staticmethod
Expand Down Expand Up @@ -1504,6 +1462,39 @@ def unsuspend(self) -> None:
print('Unsuspend')
self.start_process()

def init_warning(self, _amount_first_grid: Decimal):
if self.cycle_buy:
depo = self.deposit_second
else:
depo = self.deposit_first
if ADAPTIVE_TRADE_CONDITION:
if self.first_run and self.order_q < 3:
self.message_log(f"Depo amount {depo} not enough to set the grid with 3 or more orders",
log_level=LogLevel.ERROR)
if STANDALONE:
raise SystemExit(1)

_amount_first_grid = _amount_first_grid if self.cycle_buy else (_amount_first_grid / self.avg_rate)

if _amount_first_grid > 80 * depo / 100:
self.message_log(f"Recommended size of the first grid order {_amount_first_grid:f} too large for"
f" a small deposit {self.deposit_second}", log_level=LogLevel.ERROR)
if STANDALONE and self.first_run:
raise SystemExit(1)
elif _amount_first_grid > 20 * depo / 100:
self.message_log(f"Recommended size of the first grid order {_amount_first_grid:f} it is rather"
f" big for a small deposit {self.deposit_second}", log_level=LogLevel.WARNING)
else:
first_order_vlm = depo * 1 * (1 - self.martin) / (1 - self.martin ** ORDER_Q)

first_order_vlm = (first_order_vlm / self.avg_rate) if self.cycle_buy else first_order_vlm

if first_order_vlm < _amount_first_grid:
self.message_log(f"Depo amount {depo}{self.s_currency} not enough for {ORDER_Q} orders",
color=Style.B_RED)
if STANDALONE and self.first_run:
raise SystemExit(1)

##############################################################
# strategy function
##############################################################
Expand All @@ -1514,12 +1505,14 @@ def place_grid(self,
reverse_target_amount: Decimal,
allow_grid_shift: bool = True,
additional_grid: bool = False,
grid_update: bool = False) -> None:
self.message_log(f"place_grid: buy_side: {buy_side}, depo: {depo},"
f" reverse_target_amount: {reverse_target_amount},"
f" allow_grid_shift: {allow_grid_shift},"
f" additional_grid: {additional_grid},"
f" grid_update: {grid_update}", log_level=LogLevel.DEBUG)
grid_update: bool = False,
init_calc_only: bool = False) -> None:
if not init_calc_only:
self.message_log(f"place_grid: buy_side: {buy_side}, depo: {depo},"
f" reverse_target_amount: {reverse_target_amount},"
f" allow_grid_shift: {allow_grid_shift},"
f" additional_grid: {additional_grid},"
f" grid_update: {grid_update}", log_level=LogLevel.DEBUG)
self.grid_hold.clear()
self.last_shift_time = None
funds = self.get_buffered_funds()
Expand Down Expand Up @@ -1565,11 +1558,17 @@ def place_grid(self,
amount_first_grid = amount_min_dec
if self.order_q > 1:
self.message_log(f"For{' Reverse' if self.reverse else ''} {'Buy' if buy_side else 'Sell'}"
f" cycle set {self.order_q} orders for {self.over_price:.4f}% over price", tlg=False)
f" cycle{' will be' if init_calc_only else ''} set {self.order_q} orders"
f" for {self.over_price:.4f}% over price", tlg=False)
else:
self.message_log(f"For{' Reverse' if self.reverse else ''} {'Buy' if buy_side else 'Sell'}"
f" cycle set 1 order{' for additional grid' if additional_grid else ''}",
tlg=False)
#
if init_calc_only:
self.init_warning(amount_first_grid)
return
#
if self.order_q > 1:
delta_price = self.over_price * base_price_dec / (100 * (self.order_q - 1))
else:
Expand Down Expand Up @@ -1903,16 +1902,6 @@ def set_trade_conditions(self,
self.message_log(f"set_trade_conditions: buy_side: {buy_side}, depo: {float(depo):f}, base_price: {base_price},"
f" reverse_target_amount: {reverse_target_amount}, amount_min: {amount_min},"
f" step_size: {step_size}, delta_min: {delta_min}", LogLevel.DEBUG)
if additional_grid or grid_update:
grid_min = 1
else:
if FEE_FTX and not self.reverse:
grid_min = GRID_MAX_COUNT
else:
grid_min = ORDER_Q
over_price_min = 100 * delta_min * (grid_min + 1) / base_price
self.message_log(f"set_trade_conditions.grid_min: {grid_min}, over_price_min: {float(over_price_min):f}",
LogLevel.DEBUG)
depo_c = (depo / base_price) if buy_side else depo
if not additional_grid and not grid_update and not GRID_ONLY and PROFIT_MAX < 100:
k_m = 1 - PROFIT_MAX / 100
Expand All @@ -1939,7 +1928,7 @@ def set_trade_conditions(self,
else:
tbb = bb.get('tbb')
over_price = 100 * (f2d(tbb) - base_price) / base_price
self.over_price = max(over_price, over_price_min)
self.over_price = max(over_price, OVER_PRICE)
# Adapt grid orders quantity for current over price
order_q = int(self.over_price * ORDER_Q / OVER_PRICE)
depo_c = (depo / base_price) if buy_side else depo
Expand All @@ -1948,8 +1937,7 @@ def set_trade_conditions(self,
self.message_log(f"set_trade_conditions: depo: {float(depo):f}, order_q: {order_q},"
f" amount_first_grid: {amount_first_grid:f}, amount_2: {amnt_2:f},"
f" q_max: {q_max}, coarse overprice: {float(self.over_price):f}", LogLevel.DEBUG)
q_max = max(q_max, grid_min)
while q_max > grid_min:
while q_max > 3:
delta_price = self.over_price * base_price / (100 * (q_max - 1))
if LINEAR_GRID_K >= 0:
price_k = f2d(1 - math.log(q_max - 1, q_max + LINEAR_GRID_K))
Expand All @@ -1960,13 +1948,7 @@ def set_trade_conditions(self,
break
q_max -= 1
#
if order_q > q_max:
self.order_q = q_max
else:
if order_q >= grid_min:
self.order_q = order_q
else:
self.order_q = grid_min
self.order_q = q_max if order_q > q_max else order_q
# Correction over_price after change quantity of orders
if self.reverse and self.order_q > 1:
over_price = self.calc_over_price(buy_side,
Expand All @@ -1976,7 +1958,7 @@ def set_trade_conditions(self,
delta_min,
amount_first_grid,
amount_min)
self.over_price = max(over_price, over_price_min)
self.over_price = max(over_price, OVER_PRICE)
return amount_first_grid

def set_profit(self) -> Decimal:
Expand Down Expand Up @@ -2787,6 +2769,9 @@ def on_new_ticker(self, ticker: Ticker) -> None:
def on_new_order_book(self, order_book: OrderBook) -> None:
# print(f"on_new_order_book: max_bids: {order_book.bids[0].price}, min_asks: {order_book.asks[0].price}")
pass
##############################################################
# private update methods
##############################################################

def on_new_funds(self, funds: Dict[str, FundsEntry]) -> None:
# print(f"on_new_funds.funds: {funds}")
Expand Down Expand Up @@ -2824,10 +2809,6 @@ def on_new_funds(self, funds: Dict[str, FundsEntry]) -> None:
self.grid_hold['additional_grid'],
self.grid_hold['grid_update'])

##############################################################
# private update methods
##############################################################

def on_order_update(self, update: OrderUpdate) -> None:
# self.message_log(f"Order {update.original_order.id}: {update.status}", log_level=LogLevel.DEBUG)
if update.status in [OrderUpdate.ADAPTED,
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.8"

dependencies = [
"exchanges-wrapper>=1.2.4-5",
"exchanges-wrapper>=1.2.4-15",
"margin-strategy-sdk==0.0.11",
"aiohttp>=3.8.1",
"grpcio>=1.47.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>=1.2.4-5
exchanges-wrapper>=1.2.4-15
margin-strategy-sdk==0.0.11
aiohttp>=3.8.1
grpcio>=1.47.0
Expand Down

0 comments on commit f4693ab

Please sign in to comment.