ready2live test
This commit is contained in:
@ -33,10 +33,12 @@ Do budoucna vice ridit nakupy pri klesani - napr. vyložení jen 2-3 pozic a dal
|
|||||||
#
|
#
|
||||||
"""
|
"""
|
||||||
stratvars = AttributeDict(maxpozic = 400,
|
stratvars = AttributeDict(maxpozic = 400,
|
||||||
|
def_mode_from = 200,
|
||||||
chunk = 10,
|
chunk = 10,
|
||||||
MA = 2,
|
MA = 2,
|
||||||
Trend = 2,
|
Trend = 2,
|
||||||
profit = 0.02,
|
profit = 0.02,
|
||||||
|
def_profit = 0.01,
|
||||||
lastbuyindex=-6,
|
lastbuyindex=-6,
|
||||||
pendingbuys={},
|
pendingbuys={},
|
||||||
limitka = None,
|
limitka = None,
|
||||||
@ -93,6 +95,27 @@ def next(data, state: StrategyState):
|
|||||||
#ic(state.vars)
|
#ic(state.vars)
|
||||||
#ic(data)
|
#ic(data)
|
||||||
|
|
||||||
|
#
|
||||||
|
def is_defensive_mode():
|
||||||
|
akt_pozic = int(state.positions)
|
||||||
|
max_pozic = int(state.vars.maxpozic)
|
||||||
|
def_mode_from = safe_get(state.vars, "def_mode_from")
|
||||||
|
if def_mode_from == None: def_mode_from = max_pozic/2
|
||||||
|
if akt_pozic >= int(def_mode_from):
|
||||||
|
state.ilog(e=f"DEFENSIVE mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_limitka_price():
|
||||||
|
def_profit = safe_get(state.vars, "def_profit")
|
||||||
|
if def_profit == None: def_profit = state.vars.profit
|
||||||
|
if is_defensive_mode():
|
||||||
|
return price2dec(float(state.avgp)+float(def_profit))
|
||||||
|
else:
|
||||||
|
return price2dec(float(state.avgp)+float(state.vars.profit))
|
||||||
|
|
||||||
#mozna presunout o level vys
|
#mozna presunout o level vys
|
||||||
def vyloz():
|
def vyloz():
|
||||||
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
||||||
@ -104,25 +127,22 @@ def next(data, state: StrategyState):
|
|||||||
vykladka = state.vars.vykladka
|
vykladka = state.vars.vykladka
|
||||||
#kolik muzu max vylozit
|
#kolik muzu max vylozit
|
||||||
kolikmuzu = int((int(state.vars.maxpozic) - int(state.positions))/int(state.vars.chunk))
|
kolikmuzu = int((int(state.vars.maxpozic) - int(state.positions))/int(state.vars.chunk))
|
||||||
akt_pozic = int((int(state.positions))/int(state.vars.chunk)) #20
|
akt_pozic = int(state.positions)
|
||||||
max_pozic = int((int(state.vars.maxpozic))/int(state.vars.chunk)) #40
|
max_pozic = int(state.vars.maxpozic)
|
||||||
|
|
||||||
#mame polovinu a vic vylozeno, pouzivame defenzicni krivku
|
#mame polovinu a vic vylozeno, pouzivame defenzicni krivku
|
||||||
if (akt_pozic >= max_pozic/2):
|
if is_defensive_mode():
|
||||||
state.ilog(e="DEF: Mame pul a vic vylozeno, pouzivame defenzivni krivku", akt_pozic=akt_pozic, max_pozic=max_pozic, curve_def=curve_def)
|
state.ilog(e="DEF: Pouzivame defenzivni krivku", akt_pozic=akt_pozic, max_pozic=max_pozic, curve_def=curve_def)
|
||||||
curve = curve_def
|
curve = curve_def
|
||||||
#zaroven docasne menime ticks2reset na defenzivni 0.06
|
#zaroven docasne menime ticks2reset na defenzivni 0.06
|
||||||
state.vars.ticks2reset = 0.06
|
state.vars.ticks2reset = 0.06
|
||||||
state.ilog(e="DEF: Menime tick2reset na 0.06", ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
state.ilog(e="DEF: Menime tick2reset na 0.06", ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
||||||
defense = True
|
|
||||||
else:
|
else:
|
||||||
defense = False
|
|
||||||
#vracime zpet, pokud bylo zmeneno
|
#vracime zpet, pokud bylo zmeneno
|
||||||
if state.vars.ticks2reset != state.vars.ticks2reset_backup:
|
if state.vars.ticks2reset != state.vars.ticks2reset_backup:
|
||||||
state.vars.ticks2reset = state.vars.ticks2reset_backup
|
state.vars.ticks2reset = state.vars.ticks2reset_backup
|
||||||
state.ilog(e="DEF: Menime tick2reset zpet na"+str(state.vars.ticks2reset), ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
state.ilog(e="DEF: Menime tick2reset zpet na"+str(state.vars.ticks2reset), ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
||||||
|
|
||||||
|
|
||||||
if kolikmuzu < vykladka: vykladka = kolikmuzu
|
if kolikmuzu < vykladka: vykladka = kolikmuzu
|
||||||
|
|
||||||
if len(curve) < vykladka:
|
if len(curve) < vykladka:
|
||||||
@ -137,9 +157,11 @@ def next(data, state: StrategyState):
|
|||||||
##VAR - na zaklade conf. muzeme jako prvni posilat MARKET order
|
##VAR - na zaklade conf. muzeme jako prvni posilat MARKET order
|
||||||
if safe_get(state.vars, "first_buy_market") == True:
|
if safe_get(state.vars, "first_buy_market") == True:
|
||||||
#pri defenzivnim rezimu pouzivame vzdy LIMIT order
|
#pri defenzivnim rezimu pouzivame vzdy LIMIT order
|
||||||
if defense:
|
if is_defensive_mode():
|
||||||
|
state.ilog(e="DEF mode on, odesilame jako prvni limitku")
|
||||||
state.buy_l(price=price, size=qty)
|
state.buy_l(price=price, size=qty)
|
||||||
else:
|
else:
|
||||||
|
state.ilog(e="Posilame jako prvni MARKET order")
|
||||||
state.buy(size=qty)
|
state.buy(size=qty)
|
||||||
else:
|
else:
|
||||||
state.buy_l(price=price, size=qty)
|
state.buy_l(price=price, size=qty)
|
||||||
@ -277,7 +299,7 @@ def next(data, state: StrategyState):
|
|||||||
#neni limitka, ale mela by byt - vytváříme ji
|
#neni limitka, ale mela by byt - vytváříme ji
|
||||||
if int(state.positions) > 0 and state.vars.limitka is None:
|
if int(state.positions) > 0 and state.vars.limitka is None:
|
||||||
state.ilog(e="Limitka neni, ale mela by být.", msg=f"{state.positions=}")
|
state.ilog(e="Limitka neni, ale mela by být.", msg=f"{state.positions=}")
|
||||||
price=price2dec(float(state.avgp)+state.vars.profit)
|
price=get_limitka_price()
|
||||||
state.vars.limitka = asyncio.run(state.interface.sell_l(price=price, size=int(state.positions)))
|
state.vars.limitka = asyncio.run(state.interface.sell_l(price=price, size=int(state.positions)))
|
||||||
state.vars.limitka_price = price
|
state.vars.limitka_price = price
|
||||||
if state.vars.limitka == -1:
|
if state.vars.limitka == -1:
|
||||||
@ -287,12 +309,13 @@ def next(data, state: StrategyState):
|
|||||||
else:
|
else:
|
||||||
state.ilog(e="Vytvořena nová limitka", limitka=str(state.vars.limitka), limtka_price=state.vars.limitka_price, qty=state.positions)
|
state.ilog(e="Vytvořena nová limitka", limitka=str(state.vars.limitka), limtka_price=state.vars.limitka_price, qty=state.positions)
|
||||||
|
|
||||||
elif state.vars.limitka is not None and int(state.positions) > 0 and (int(state.positions) != int(limitka_qty)):
|
#existuje a nesedi mnozstvi nebo cena
|
||||||
|
elif state.vars.limitka is not None and int(state.positions) > 0 and ((int(state.positions) != int(limitka_qty)) or float(state.vars.limitka_price) != float(get_limitka_price())):
|
||||||
#limitka existuje, ale spatne mnostvi - updatujeme
|
#limitka existuje, ale spatne mnostvi - updatujeme
|
||||||
state.ilog(e=f"Limitka existuje, ale spatne mnozstvi - updatujeme", msg=f"{state.positions=} {limitka_qty=}", pos=state.positions, limitka_qty=limitka_qty)
|
state.ilog(e=f"Limitka existuje, ale spatne mnozstvi nebo CENA - updatujeme", msg=f"{state.positions=} {limitka_qty=} {state.vars.limitka_price=}", nastavenacena=state.vars.limitka_price, spravna_cena=get_limitka_price(), pos=state.positions, limitka_qty=limitka_qty)
|
||||||
#snad to nespadne, kdyztak pridat exception handling
|
#snad to nespadne, kdyztak pridat exception handling
|
||||||
puvodni = state.vars.limitka
|
puvodni = state.vars.limitka
|
||||||
state.vars.limitka = asyncio.run(state.interface.repl(price=state.vars.limitka_price, orderid=state.vars.limitka, size=int(state.positions)))
|
state.vars.limitka = asyncio.run(state.interface.repl(price=get_limitka_price(), orderid=state.vars.limitka, size=int(state.positions)))
|
||||||
|
|
||||||
if state.vars.limitka == -1:
|
if state.vars.limitka == -1:
|
||||||
state.ilog(e="Replace limitky neprobehl, vracime puvodni", msg=f"{state.vars.limitka=}", puvodni=puvodni)
|
state.ilog(e="Replace limitky neprobehl, vracime puvodni", msg=f"{state.vars.limitka=}", puvodni=puvodni)
|
||||||
@ -334,7 +357,7 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
|
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
|
||||||
lp = state.interface.get_last_price(symbol=state.symbol)
|
lp = state.interface.get_last_price(symbol=state.symbol)
|
||||||
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),2)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)}", last_price=lp, stratvars=state.vars)
|
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),2)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, stratvars=state.vars)
|
||||||
|
|
||||||
#maxSlopeMA = -0.03
|
#maxSlopeMA = -0.03
|
||||||
#SLOPE ANGLE PROTECTIONs
|
#SLOPE ANGLE PROTECTIONs
|
||||||
@ -362,10 +385,11 @@ def next(data, state: StrategyState):
|
|||||||
if state.vars.jevylozeno == 0:
|
if state.vars.jevylozeno == 0:
|
||||||
print("Neni vylozeno, muzeme testovat nakup")
|
print("Neni vylozeno, muzeme testovat nakup")
|
||||||
|
|
||||||
|
#pokud je defenziva, buy triggeruje defenzivni def_trend
|
||||||
|
#TBD
|
||||||
|
|
||||||
|
|
||||||
if isfalling(state.indicators.ema,state.vars.Trend) and slope > minimum_slope:
|
if isfalling(state.indicators.ema,state.vars.Trend) and slope > minimum_slope:
|
||||||
print("BUY MARKET")
|
|
||||||
#zatim vykladame full
|
|
||||||
#positions = int(int(state.vars.maxpozic)/int(state.vars.chunk))
|
|
||||||
vyloz()
|
vyloz()
|
||||||
|
|
||||||
## testuje aktualni cenu od nejvyssi visici limitky
|
## testuje aktualni cenu od nejvyssi visici limitky
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -251,7 +251,11 @@ class Backtester:
|
|||||||
#(1679081919.381649, 27.88)
|
#(1679081919.381649, 27.88)
|
||||||
#ic(i)
|
#ic(i)
|
||||||
fill_time = i[0]
|
fill_time = i[0]
|
||||||
fill_price = i[1]
|
|
||||||
|
#v BT nikdy nekoupime za lepsi cenu nez LIMIT price (TBD mozna zmenit na parametr)
|
||||||
|
fill_price = o.limit_price
|
||||||
|
#fill_price = i[1]
|
||||||
|
|
||||||
print("FILL LIMIT BUY at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
print("FILL LIMIT BUY at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
||||||
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
||||||
#TODO loguru
|
#TODO loguru
|
||||||
@ -281,7 +285,13 @@ class Backtester:
|
|||||||
#(1679081919.381649, 27.88)
|
#(1679081919.381649, 27.88)
|
||||||
#ic(i)
|
#ic(i)
|
||||||
fill_time = i[0]
|
fill_time = i[0]
|
||||||
fill_price = i[1]
|
|
||||||
|
#support pomaleho plneni
|
||||||
|
#v BT nikdy neprodame za lepsi cenu nez LIMIT price (TBD mozna zmenit na parametr)
|
||||||
|
fill_price = o.limit_price
|
||||||
|
|
||||||
|
|
||||||
|
#fill_price = i[1]
|
||||||
print("FILL LIMIT SELL at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
print("FILL LIMIT SELL at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
||||||
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
||||||
#TODO loguru
|
#TODO loguru
|
||||||
@ -572,6 +582,7 @@ class Backtester:
|
|||||||
res.append(o)
|
res.append(o)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
##toto bude predelano na display_results(ve variantach) umozni zobrazit result jak BT tak LIVE
|
||||||
def display_backtest_result(self, state):
|
def display_backtest_result(self, state):
|
||||||
"""
|
"""
|
||||||
Displays backtest results chart, trades and orders with option to save the result as static HTML.
|
Displays backtest results chart, trades and orders with option to save the result as static HTML.
|
||||||
@ -755,6 +766,13 @@ class Backtester:
|
|||||||
Open orders:''' + str(len(self.open_orders)))
|
Open orders:''' + str(len(self.open_orders)))
|
||||||
textik7 = html.Div('''
|
textik7 = html.Div('''
|
||||||
Trades:''' + str(len(self.trades)))
|
Trades:''' + str(len(self.trades)))
|
||||||
|
textik8 = html.Div('''
|
||||||
|
Profit:''' + str(state.profit))
|
||||||
|
textik9 = html.Div(f"{BT_FILL_CONS_TRADES_REQUIRED=}")
|
||||||
|
textik10 = html.Div(f"{BT_FILL_LOG_SURROUNDING_TRADES=}")
|
||||||
|
textik11 = html.Div(f"{BT_FILL_CONDITION_BUY_LIMIT=}")
|
||||||
|
textik12 = html.Div(f"{BT_FILL_CONDITION_SELL_LIMIT=}")
|
||||||
|
|
||||||
orders_title = dcc.Markdown('## Open orders')
|
orders_title = dcc.Markdown('## Open orders')
|
||||||
trades_title = dcc.Markdown('## Trades')
|
trades_title = dcc.Markdown('## Trades')
|
||||||
## Define the graph
|
## Define the graph
|
||||||
@ -867,7 +885,7 @@ class Backtester:
|
|||||||
return 'saved'
|
return 'saved'
|
||||||
|
|
||||||
## Customize your layout
|
## Customize your layout
|
||||||
app.layout = dbc.Container([mytitle,button,saved, textik1, textik2, textik3, textik35, textik4, textik5, textik55, textik6,textik7, mygraph, trades_title, trades_table, orders_title, open_orders_table])
|
app.layout = dbc.Container([mytitle,button,saved, textik1, textik2, textik3, textik35, textik4, textik5, textik55, textik6,textik7, textik8, textik9, textik10, textik11, textik12, mygraph, trades_title, trades_table, orders_title, open_orders_table])
|
||||||
|
|
||||||
port = 9050
|
port = 9050
|
||||||
print("Backtest FINSIHED"+str(self.backtest_end-self.backtest_start))
|
print("Backtest FINSIHED"+str(self.backtest_end-self.backtest_start))
|
||||||
|
|||||||
@ -9,14 +9,14 @@ QUIET_MODE = False
|
|||||||
#N - N consecutive trades required
|
#N - N consecutive trades required
|
||||||
#not impl.yet
|
#not impl.yet
|
||||||
#minimum is 1, na alpace live to vetsinou vychazi 7-8 u BAC, je to hodne podobne tomu, nez je cena překonaná pul centu. tzn. 7-8 a nebo FillCondition.SLOW
|
#minimum is 1, na alpace live to vetsinou vychazi 7-8 u BAC, je to hodne podobne tomu, nez je cena překonaná pul centu. tzn. 7-8 a nebo FillCondition.SLOW
|
||||||
BT_FILL_CONS_TRADES_REQUIRED = 3
|
BT_FILL_CONS_TRADES_REQUIRED = 2
|
||||||
#during bt trade execution logs X-surrounding trades of the one that triggers the fill
|
#during bt trade execution logs X-surrounding trades of the one that triggers the fill
|
||||||
BT_FILL_LOG_SURROUNDING_TRADES = 10
|
BT_FILL_LOG_SURROUNDING_TRADES = 10
|
||||||
#fill condition for limit order in bt
|
#fill condition for limit order in bt
|
||||||
# fast - price has to be equal or bigger <=
|
# fast - price has to be equal or bigger <=
|
||||||
# slow - price has to be bigger <
|
# slow - price has to be bigger <
|
||||||
BT_FILL_CONDITION_BUY_LIMIT = FillCondition.FAST
|
BT_FILL_CONDITION_BUY_LIMIT = FillCondition.SLOW
|
||||||
BT_FILL_CONDITION_SELL_LIMIT = FillCondition.FAST
|
BT_FILL_CONDITION_SELL_LIMIT = FillCondition.SLOW
|
||||||
#backend counter of api requests
|
#backend counter of api requests
|
||||||
COUNT_API_REQUESTS = False
|
COUNT_API_REQUESTS = False
|
||||||
#stratvars that cannot be changed in gui
|
#stratvars that cannot be changed in gui
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from v2realbot.strategy.base import Strategy
|
from v2realbot.strategy.base import Strategy
|
||||||
from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial
|
from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial, safe_get
|
||||||
from v2realbot.utils.tlog import tlog, tlog_exception
|
from v2realbot.utils.tlog import tlog, tlog_exception
|
||||||
from v2realbot.enums.enums import Mode, Order, Account
|
from v2realbot.enums.enums import Mode, Order, Account
|
||||||
from alpaca.trading.models import TradeUpdate
|
from alpaca.trading.models import TradeUpdate
|
||||||
@ -37,7 +37,8 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
self.state.positions = data.position_qty
|
self.state.positions = data.position_qty
|
||||||
if self.state.vars.limitka is None:
|
if self.state.vars.limitka is None:
|
||||||
self.state.avgp = float(data.price)
|
self.state.avgp = float(data.price)
|
||||||
price=price2dec(float(o.filled_avg_price)+self.state.vars.profit)
|
#price=price2dec(float(o.filled_avg_price)+self.state.vars.profit)
|
||||||
|
price = await self.get_limitka_price()
|
||||||
self.state.vars.limitka = await self.interface.sell_l(price=price, size=o.filled_qty)
|
self.state.vars.limitka = await self.interface.sell_l(price=price, size=o.filled_qty)
|
||||||
#obcas live vrati "held for orders", odchytime chybu a limitku nevytvarime - spravi to dalsi notifikace nebo konzolidace
|
#obcas live vrati "held for orders", odchytime chybu a limitku nevytvarime - spravi to dalsi notifikace nebo konzolidace
|
||||||
if self.state.vars.limitka == -1:
|
if self.state.vars.limitka == -1:
|
||||||
@ -49,7 +50,8 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
else:
|
else:
|
||||||
#avgp, pos
|
#avgp, pos
|
||||||
self.state.avgp, self.state.positions = self.state.interface.pos()
|
self.state.avgp, self.state.positions = self.state.interface.pos()
|
||||||
cena = price2dec(float(self.state.avgp) + float(self.state.vars.profit))
|
#cena = price2dec(float(self.state.avgp) + float(self.state.vars.profit))
|
||||||
|
cena = await self.get_limitka_price()
|
||||||
try:
|
try:
|
||||||
puvodni = self.state.vars.limitka
|
puvodni = self.state.vars.limitka
|
||||||
self.state.vars.limitka = await self.interface.repl(price=cena,orderid=self.state.vars.limitka,size=int(self.state.positions))
|
self.state.vars.limitka = await self.interface.repl(price=cena,orderid=self.state.vars.limitka,size=int(self.state.positions))
|
||||||
@ -175,3 +177,24 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
self.state.vars.jevylozeno = 0
|
self.state.vars.jevylozeno = 0
|
||||||
print("cancel pending buys end")
|
print("cancel pending buys end")
|
||||||
self.state.ilog(e="Dokončeno zruseni vsech pb", pb=self.state.vars.pendingbuys)
|
self.state.ilog(e="Dokončeno zruseni vsech pb", pb=self.state.vars.pendingbuys)
|
||||||
|
|
||||||
|
#kopie funkci co jsou v next jen async, nejak vymyslet, aby byly jen jedny
|
||||||
|
async def is_defensive_mode(self):
|
||||||
|
akt_pozic = int(self.state.positions)
|
||||||
|
max_pozic = int(self.state.vars.maxpozic)
|
||||||
|
def_mode_from = safe_get(self.state.vars, "def_mode_from")
|
||||||
|
if def_mode_from == None: def_mode_from = max_pozic/2
|
||||||
|
if akt_pozic >= int(def_mode_from):
|
||||||
|
self.state.ilog(e=f"DEFENSIVE MODE active {self.state.vars.def_mode_from=}", msg=self.state.positions)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self.state.ilog(e=f"STANDARD MODE active {self.state.vars.def_mode_from=}", msg=self.state.positions)
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def get_limitka_price(self):
|
||||||
|
def_profit = safe_get(self.state.vars, "def_profit")
|
||||||
|
if def_profit == None: def_profit = self.state.vars.profit
|
||||||
|
if await self.is_defensive_mode():
|
||||||
|
return price2dec(float(self.state.avgp)+float(def_profit))
|
||||||
|
else:
|
||||||
|
return price2dec(float(self.state.avgp)+float(self.state.vars.profit))
|
||||||
Binary file not shown.
Reference in New Issue
Block a user