def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() variant_type = self.input(defval=5, title="variant_type", type=int) basis_len = self.input(defval=19, title="basis_len", type=int) resolution = self.input(defval=2, title="resolution", type=int) sma_len = self.input(defval=9, title="sma_len", type=int) div_threshold = self.input(defval=3.0, title="div_threshold", type=float) source = self.exchange.security(str(resolution) + 'm') if self.eval_time is not None and \ self.eval_time == source.iloc[-1].name: return series_open = source['open'].values series_close = source['close'].values variant = self.variants[variant_type] val_open = variant(series_open, basis_len) val_close = variant(series_close, basis_len) if val_open[-1] > val_close[-1]: high_val = val_open[-1] low_val = val_close[-1] else: high_val = val_close[-1] low_val = val_open[-1] sma_val = sma(close, sma_len) self.exchange.plot('val_open', val_open[-1], 'b') self.exchange.plot('val_close', val_close[-1], 'r') logger.info("occ:sma_val[-1]:" + str(sma_val[-1])) logger.info("occ:low_val:" + str(low_val)) logger.info("occ:high_val:" + str(high_val)) logger.info("lot:" + str(lot)) logger.info("------------") self.exchange.entry("Long", True, lot, stop=math.floor(low_val), when=(sma_val[-1] < low_val)) self.exchange.entry("Short", False, lot, stop=math.ceil(high_val), when=(sma_val[-1] > high_val)) open_close_div = sma(numpy.abs(val_open - val_close), sma_len) if open_close_div[-1] > div_threshold and \ open_close_div[-2] > div_threshold < open_close_div[-2]: self.exchange.close_all() self.eval_time = source.iloc[-1].name
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() fast_len = self.input('fast_len', int, 9) slow_len = self.input('slow_len', int, 16) fast_sma = sma(close, fast_len) slow_sma = sma(close, slow_len) golden_cross = crossover(fast_sma, slow_sma) dead_cross = crossunder(fast_sma, slow_sma) if golden_cross: self.exchange.entry("Long", True, lot) if dead_cross: self.exchange.entry("Short", False, lot)
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() fast_len = self.input('fast_len', int, 9) slow_len = self.input('slow_len', int, 16) fast_sma = sma(close, fast_len) slow_sma = sma(close, slow_len) golden_cross = crossover(fast_sma, slow_sma) dead_cross = crossunder(fast_sma, slow_sma) def entry_callback(avg_price=close[-1]): long = True if self.exchange.get_position_size() > 0 else False logger.info( f"{'Long' if long else 'Short'} Entry Order Successful") if golden_cross: self.exchange.entry("Long", True, lot, \ round_decimals=3, callback=entry_callback) if dead_cross: self.exchange.entry("Short", False, lot, \ round_decimals=3, callback=entry_callback)
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() # for test lot lot = int(round(lot / 50)) bitmex = BitMex(threading=False) price = bitmex.get_market_price() # variants settings rsi2_len = self.input('length', int, 2) rsi50_len = self.input('length', int, 50) rsi2 = rsi(close, rsi2_len) rsi50 = rsi(close, rsi50_len) factor = self.input('factor', int, 20) period = self.input('period', int, 7) resolution = self.input(defval=1, title="resolution", type=int) # defval 변경, 예) 5분 --> 5 source = self.exchange.security(str(resolution) + 'm') # def __init__ 비교 supertrenddf = supertrend(source, factor, period) fast_len = self.input('fast_len', int, 5) half_len = self.input('half_len', int, 5) slow_len = self.input('slow_len', int, 200) fast_sma = sma(close, fast_len) half_sma = sma(close, half_len) slow_sma = sma(close, slow_len) # conditions sma_long = over(fast_sma[-1], slow_sma[-1]) sma_short = under(fast_sma[-1], slow_sma[-1]) super_long = over(close[-1], supertrenddf['TSL'][-1]) super_short = under(close[-1], supertrenddf['TSL'][-1]) super_stoploss = supertrenddf['TSL'][-1] supertrendtrend = supertrenddf['Trend'][-1] rsi2_overbought = over(rsi2[-1], 95) rsi2_oversold = under(rsi2[-1], 5) rsi50_over = over(rsi50[-1], 50) rsi50_under = under(rsi50[-1], 50) price_under = under(price, half_sma[-1]) price_over = over(price, half_sma[-1]) half_before = over(close[-1], half_sma[-1]) half_after = under(close[-1], half_sma[-1]) # show infomations logger.info('price: %s' % price) logger.info('fast_sma[-1]: %s' % fast_sma[-1]) logger.info('slow_sma[-1]: %s' % slow_sma[-1]) logger.info('sma_long: %s' % sma_long) logger.info('sma_short: %s' % sma_short) logger.info('super_long: %s' % super_long) logger.info('super_short: %s' % super_short) logger.info('super_stoploss: %s' % super_stoploss) logger.info('sma_trend: %s' % supertrendtrend) logger.info('rsi2[-1 ]%s' % rsi2[-1]) logger.info('rsi50[-1 ]%s' % rsi50[-1]) logger.info('rsi2_oversold: %s' % rsi2_oversold) logger.info('rsi2_overbought: %s' % rsi2_overbought) logger.info('price_under: %s' % price_under) logger.info('price_over: %s' % price_over) logger.info('half_before: %s' % half_before) logger.info('half_after: %s' % half_after) logger.info('get_whichpositon(): %s' % bitmex.get_whichpositon()) logger.info('position_size(): %s' % bitmex.get_position_size()) # entry if super_long: #long trend logger.info( '+ + + + + LONG + + + + + LONG + + + + + LONG + + + + + ') if bitmex.get_whichpositon() is None: if sma_long and rsi2_oversold or price_under: logger.info( 'postion condition > None > and all short condition order' ) self.exchange.entry("Long", True, lot, limit=price - 0.5, post_only=True) else: logger.info( 'postion condition > None > default long order') self.exchange.entry("Long", True, lot, limit=math.ceil(super_stoploss), post_only=True) elif bitmex.get_whichpositon() == 'LONG': logger.info('postion condition > LONG') if price_over: # closing logger.info('postion condition > LONG > Closing') self.exchange.order("Long", False, abs(bitmex.get_position_size()), limit=price + 1.5, post_only=True) elif rsi2_overbought: # add more entry logger.info( 'postion condition > LONG > Rsi2 overbougt add more entry' ) self.exchange.entry("LongAdd", True, lot, limit=price - 0.5, post_only=True) elif super_short: # stop loss logger.info( 'postion condition > LONG > super_short(stop loss)') self.exchange.entry("Long", True, lot) self.exchange.entry("LongAdd", True, lot) elif bitmex.get_whichpositon() == 'SHORT': logger.info('cancel SHORT on long trend') # self.exchange.cancel_all() self.exchange.close_all() else: # self.exchange.cancel_all() logger.info('Super Long --> Else') if super_short: # short trend logger.info( '- - - - - SHORT - - - - - SHORT - - - - - SHORT - - - - - ') if bitmex.get_whichpositon() is None: if sma_short and rsi2_overbought or price_over: logger.info( 'postion condition > None > and all short condition order' ) self.exchange.entry("Short", False, lot, limit=price + 0.5, post_only=True) else: logger.info( 'postion condition > None > default short order') self.exchange.entry("Short", False, lot, limit=math.floor(super_stoploss), post_only=True) elif bitmex.get_whichpositon() == 'SHORT': logger.info('postion condition > SHORT') if price_under: # closing logger.info( 'postion condition > SHORT > price_under(closing)') self.exchange.order("Short", True, abs(bitmex.get_position_size()), limit=price - 1.5, post_only=True) elif rsi2_oversold: # add more entry logger.info( 'postion condition > SHORT > rsi2_oversold(add more entry)' ) self.exchange.entry("ShortAdd", False, lot, limit=price - 0.5, post_only=True) elif super_long: # stop loss logger.info( 'postion condition > SHORT > super_short(stop loss)') self.exchange.entry("Short", True, lot) self.exchange.entry("ShortAdd", True, lot) elif bitmex.get_whichpositon() == 'LONG': logger.info('cancel LONG on short trend') self.exchange.close_all() else: logger.info('Super Shot --> Else') self.dealcount += 1 diff = (abs(bitmex.get_balance() - abs(self.prebalance))) realised_pnl = bitmex.get_margin()['realisedPnl'] logger.info('dealcount:%s' % self.dealcount) logger.info('prebalance():%s' % self.prebalance) logger.info('bitmex.get_balance():%s' % bitmex.get_balance()) logger.info('diff:%s' % diff) logger.info('realised_pnl:%s' % realised_pnl) logger.info('--------------------------------------------------')
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() # for test lot lot = int(round(lot / 50)) bitmex = BitMex(threading=False) price = bitmex.get_market_price() position_avg_price = bitmex.get_position_avg_price() # variants settings rsi2_len = self.input('length', int, 2) rsi50_len = self.input('length50', int, 50) rsi2 = rsi(close, rsi2_len) rsi50 = rsi(close, rsi50_len) factor = self.input('factor', int, 3) period = self.input('period', int, 7) factor2 = self.input('factor2', int, 20) period2 = self.input('period2', int, 7) resolution = self.input(defval=1, title="resolution", type=int) # defval 변경, 예) 5분 --> 5 source = self.exchange.security(str(resolution) + 'm') # def __init__ 비교 supertrenddf = supertrend(source, factor, period) supertrenddf2 = supertrend(source, factor2, period2) print('supertrenddf:%s' % supertrenddf) print('supertrenddf2:%s' % supertrenddf2) fast_len = self.input('fast_len', int, 5) half_len = self.input('half_len', int, 50) slow_len = self.input('slow_len', int, 200) fast_sma = sma(close, fast_len) half_sma = sma(close, half_len) slow_sma = sma(close, slow_len) # conditions sma_long = over(fast_sma[-1], slow_sma[-1]) sma_short = under(fast_sma[-1], slow_sma[-1]) super_long = over(close[-1], supertrenddf['SuperTrend'][-1]) super_short = under(close[-1], supertrenddf['SuperTrend'][-1]) supertrendtrend = supertrenddf['Trend'][-1] super2_long = over(close[-1], supertrenddf2['SuperTrend'][-1]) super2_short = under(close[-1], supertrenddf2['SuperTrend'][-1]) supertrendtrend2 = supertrenddf2['Trend'][-1] super_centerline = (supertrenddf['SuperTrend'][-1] + supertrenddf2['SuperTrend'][-1]) / 2 rsi2_overbought = over(rsi2[-1], 95) rsi2_oversold = under(rsi2[-1], 5) rsi50_over = over(rsi50[-1], 50) rsi50_under = under(rsi50[-1], 50) price_under = under(price, half_sma[-1]) price_over = over(price, half_sma[-1]) half_before = over(close[-1], half_sma[-1]) half_after = under(close[-1], half_sma[-1]) # show infomations logger.info('price: %s' % price) logger.info('fast_sma[-1]: %s' % fast_sma[-1]) logger.info('slow_sma[-1]: %s' % slow_sma[-1]) logger.info('sma_long: %s' % sma_long) logger.info('sma_short: %s' % sma_short) logger.info('super_long: %s' % super_long) logger.info('super_short: %s' % super_short) logger.info('sma_trend: %s\n' % supertrendtrend) logger.info('supertrend value:%s' % supertrenddf['SuperTrend'][-1]) logger.info('supertrend Upper Band:%s' % supertrenddf['Upper Band'][-1]) logger.info('supertrend Lower Band:%s' % supertrenddf['Lower Band'][-1]) logger.info('supertrenddf[Trend][-1]:%s' % supertrenddf['Trend'][-1]) logger.info('supertrenddf[TSL][-1]:%s' % supertrenddf['TSL'][-1]) logger.info('supertrenddf[ATR][-1]:%s\n' % supertrenddf['ATR'][-1]) logger.info('supertrend2 value:%s' % supertrenddf2['SuperTrend'][-1]) logger.info('supertrend2 Upper Band:%s' % supertrenddf2['Upper Band'][-1]) logger.info('supertrend2 Lower Band:%s' % supertrenddf2['Lower Band'][-1]) logger.info('supertrenddf2[Trend][-1]:%s' % supertrenddf2['Trend'][-1]) logger.info('supertrenddf2[TSL][-1]:%s' % supertrenddf2['TSL'][-1]) logger.info('supertrenddf2[ATR][-1]:%s\n' % supertrenddf2['ATR'][-1]) logger.info( 'supertrenddf[SuperTrend][-1]:%s + supertrenddf2[SuperTrend][-1]:%s ' % (supertrenddf['SuperTrend'][-1], supertrenddf2['SuperTrend'][-1])) logger.info('super_centerline: %s' % super_centerline) logger.info('rsi2[-1 ]%s' % rsi2[-1]) logger.info('rsi50[-1 ]%s' % rsi50[-1]) logger.info('rsi2_oversold: %s' % rsi2_oversold) logger.info('rsi2_overbought: %s' % rsi2_overbought) logger.info('price_under: %s' % price_under) logger.info('price_over: %s' % price_over) logger.info('half_before: %s' % half_before) logger.info('half_after: %s' % half_after) logger.info('get_whichpositon(): %s' % bitmex.get_whichpositon()) logger.info('position_size(): %s' % bitmex.get_position_size()) # entry if super2_long: logger.info( '+ + + + + LONG + + + + + LONG + + + + + LONG + + + + + ') if bitmex.get_whichpositon( ) is None: # and (not supertrendtrend and supertrendtrend2) and rsi2_overbought: logger.info('postion condition > None') if bitmex.get_open_order('Short'): self.exchange.cancel('Short') self.exchange.entry("Long", True, lot, limit=math.ceil(super_centerline), post_only=True) elif bitmex.get_whichpositon() == 'LONG': logger.info('postion condition > LONG') if supertrendtrend and supertrendtrend2 and rsi2_oversold: # closing logger.info('postion condition > LONG > Closing') self.exchange.order("Long", False, abs(bitmex.get_position_size()), limit=price + 2.5, post_only=True) elif rsi2_overbought: # add more entry logger.info('postion condition > LONG > Rsi2 overbout') self.exchange.entry("LongAdd", True, lot, limit=price - 0.5, post_only=True) elif super_short: # stop loss logger.info( 'postion condition > LONG > super_short(stop loss)') self.exchange.entry("Long", True, lot) self.exchange.entry("LongAdd", True, lot) else: logger.info('postion condition > LONG > else') self.exchange.order("Long", False, abs(bitmex.get_position_size()), limit=price + 10, post_only=True) elif bitmex.get_whichpositon() == 'SHORT': logger.info('cancel SHORT on long trend') # self.exchange.cancel_all() self.exchange.close_all() self.exchange.close_all() else: logger.info('Super Shot --> Else') if super2_short: logger.info( '- - - - - SHORT - - - - - SHORT - - - - - SHORT - - - - - ') if bitmex.get_whichpositon( ) is None: #and rsi2_overbought and price_over: logger.info('postion condition > None') if bitmex.get_open_order('Long'): self.exchange.cancel('Long') self.exchange.entry("Short", False, lot, limit=math.floor(super_centerline), post_only=True) elif bitmex.get_whichpositon() == 'SHORT': logger.info('postion condition > SHORT') if price_under: # closing logger.info( 'postion condition > SHORT > price_under(closing)') self.exchange.order("Short", True, abs(bitmex.get_position_size()), limit=price - 2.5, when=price_under, post_only=True) elif rsi2_oversold: # add more entry logger.info( 'postion condition > SHORT > rsi2_oversold(add more entry)' ) self.exchange.entry("ShortAdd", False, lot, limit=price - 0.5, post_only=True) elif super_long: # stop loss logger.info( 'postion condition > SHORT > super_short(stop loss)') self.exchange.entry("Short", True, lot) self.exchange.entry("ShortAdd", True, lot) else: logger.info('postion condition > SHORT > else') self.exchange.order("Short", True, abs(bitmex.get_position_size()), limit=price - 10, post_only=True) elif bitmex.get_whichpositon() == 'LONG': logger.info('cancel LONG on short trend') self.exchange.close_all() else: logger.info('Super Shot --> Else') self.dealcount += 1 diff = (abs(bitmex.get_balance() - abs(self.prebalance))) realised_pnl = bitmex.get_margin()['realisedPnl'] logger.info('dealcount:%s' % self.dealcount) logger.info('prebalance():%s' % self.prebalance) logger.info('bitmex.get_balance():%s' % bitmex.get_balance()) logger.info('diff:%s' % diff) logger.info('realised_pnl:%s' % realised_pnl) logger.info('--------------------------------------------------')
def strategy(self, open, close, high, low, volume): # get lot or set your own value which will be used to size orders # careful default lot is about 20x your account size !!! lot = self.exchange.get_lot() # indicator lengths fast_len = self.input('fast_len', int, 6) slow_len = self.input('slow_len', int, 18) # setting indicators, they usually take source and length as arguments sma1 = sma(close, fast_len) sma2 = sma(close, slow_len) # entry conditions long_entry_condition = crossover(sma1, sma2) short_entry_condition = crossunder(sma1, sma2) # setting a simple stop loss and profit target in % using built-in simple profit take and stop loss implementation # which is placing the sl and tp automatically after entering a position self.exchange.sltp(profit_long=1.25, profit_short=1.25, stop_long=1, stop_short=1.1, round_decimals=0) # example of calculation of stop loss price 0.8% round on 2 decimals hardcoded inside this class # sl_long = round(close[-1] - close[-1]*0.8/100, 2) # sl_short = round(close[-1] - close[-1]*0.8/100, 2) # order execution logic if long_entry_condition: # entry - True means long for every other order other than entry use self.exchange.order() function self.exchange.entry("Long", True, lot / 20) # stop loss hardcoded inside this class #self.exchange.order("SLLong", False, lot/20, stop=sl_long, reduce_only=True, when=False) if short_entry_condition: # entry - False means short for every other order other than entry use self.exchange.order() function self.exchange.entry("Short", False, lot / 20) # stop loss hardcoded inside this class # self.exchange.order("SLShort", True, lot/20, stop=sl_short, reduce_only=True, when=False) # storing history for entry signals, you can store any variable this way to keep historical values self.long_entry_signal_history.append(long_entry_condition) self.short_entry_signal_history.append(short_entry_condition) # OHLCV and indicator data, you can access history using list index # log indicator values logger.info(f"sma1: {sma1[-1]}") logger.info(f"second last sma2: {sma2[-2]}") # log last candle OHLCV values logger.info(f"open: {open[-1]}") logger.info(f"high: {high[-1]}") logger.info(f"low: {low[-1]}") logger.info(f"close: {close[-1]}") logger.info(f"volume: {volume[-1]}") #second last candle OHLCV values logger.info(f"second last open: {open[-2]}") logger.info(f"second last high: {high[-2]}") logger.info(f"second last low: {low[-2]}") logger.info(f"second last close: {close[-2]}") logger.info(f"second last volume: {volume[-2]}") # log history entry signals logger.info(f"long_entry_hist: {self.long_entry_signal_history}") logger.info(f"short_entry_hist: {self.short_entry_signal_history}")
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() lot = int(round(lot / 6, self.decimal_num)) price = self.exchange.get_market_price() pos_size = self.exchange.get_position_size() fast_len = self.input("fast_len", int, int(os.environ.get("BOT_FAST_LEN", 5))) slow_len = self.input("slow_len", int, int(os.environ.get("BOT_SLOW_LEN", 18))) trend_len = self.input("trend_len", int, int(os.environ.get("BOT_TREND_LEN", 1200))) fast_sma = sma(close, fast_len) slow_sma = sma(close, slow_len) trend_sma = sma(close, trend_len) uptrend = True if trend_sma[-1] > trend_sma[-3] or trend_sma[ -1] > trend_sma[-10] else False downtrend = True if trend_sma[-1] < trend_sma[-3] or trend_sma[ -1] < trend_sma[-10] else False golden_cross = crossover(fast_sma, slow_sma) dead_cross = crossunder(fast_sma, slow_sma) nc = "golden" if round(fast_sma[-1] - slow_sma[-1], self.price_decimal_num) < 0 else "dead" ct = "sideways" if downtrend and uptrend else ( "down" if downtrend else "up") np = "short" if nc == "golden" and ( pos_size > 0 or (pos_size >= 0 and downtrend)) else "long" nt = "golden" if (nc == "golden" and np == "short") else ( "dead" if nc == "dead" and np == "long" else not nc) logger.info(f"--------------------------------------") logger.info(f"trend: {ct}") logger.info( f'next trade @ {nt} cross > {np} {lot} @ {calc_entry_price(price, False, self.price_decimal_num) if np == "short" else calc_entry_price(price, True, self.price_decimal_num)}' ) if trend_sma[-1] != trend_sma[-1] or trend_sma[-3] != trend_sma[ -3] or trend_sma[-10] != trend_sma[-10]: logger.info(f"--------------------------------------") logger.info(f"Bot status: NEEDS RESTART") # logger.info(f'--------------------------------------') # logger.info(f'{abs(pos_size)}') if not eval(os.environ.get("BOT_TEST", "False")): if dead_cross and uptrend: # self.exchange.cancel_orders_by_side('BUY') self.exchange.order( "Long", True, lot, limit=calc_entry_price(price, True, self.price_decimal_num), when=True, post_only=True, ) logger.info("in dead_cross and uptrend for long") if float(self.exchange.get_position()["notional"]) > 0.0: self.exchange.order( "Long", False, lot, limit=calc_entry_price(price, False, self.price_decimal_num), when=golden_cross, post_only=True, ) if golden_cross and downtrend: # self.exchange.cancel_orders_by_side('SELL') self.exchange.entry( "Short", False, lot, limit=calc_entry_price(price, False, self.price_decimal_num), when=True, post_only=True, ) logger.info("in golden_cross and downtrend for short") if float(self.exchange.get_position()["notional"]) < 0.0: self.exchange.order( "Short", True, lot, limit=calc_entry_price(price, True, self.price_decimal_num), stop=(calc_entry_price(price, True, self.price_decimal_num)), when=dead_cross, post_only=True, )
def strategy(self, open, close, high, low, volume): lot = self.exchange.get_lot() lot = get_calc_lot(lot=lot, decimal_num=self.decimal_num, leverage=20.0, actual_leverage=3.0) fast_len = self.input("fast_len", int, int(os.environ.get("BOT_FAST_LEN", 5))) slow_len = self.input("slow_len", int, int(os.environ.get("BOT_SLOW_LEN", 18))) trend_len = self.input("trend_len", int, 90) logger.info(f"fast_len: {fast_len}") logger.info(f"slow_len: {slow_len}") logger.info(f"trend_len: {trend_len}") fast_sma = sma(close, fast_len) slow_sma = sma(close, slow_len) trend_sma = sma(close, trend_len) uptrend = True if trend_sma[-1] > trend_sma[-3] or trend_sma[ -1] > trend_sma[-10] else False downtrend = True if trend_sma[-1] < trend_sma[-3] or trend_sma[ -1] < trend_sma[-10] else False golden_cross = crossover(fast_sma, slow_sma) dead_cross = crossunder(fast_sma, slow_sma) # inc_trend = fast_sma[-1] > slow_sma[-1] # dec_trend = fast_sma[-1] < slow_sma[-1] reward = self.risk * self.rr_ratio self.exchange.sltp( profit_long=reward, profit_short=reward, stop_long=self.risk, stop_short=self.risk, round_decimals=self.price_decimal_num, ) # if float(self.exchange.get_position()['notional']) == 0.0: if self.exchange.get_position_size() == 0.0: self.exchange.cancel_all() if golden_cross: print("inc_trend detected") while True: # check if in long position if float(self.exchange.get_position() ["notional"]) > 0.0 or downtrend: print("long position opened") break print("trying to open long position...") self.exchange.entry("Long", True, lot) if dead_cross: print("dec_trend detected") while True: # check if in short position if float(self.exchange.get_position() ["notional"]) < 0.0 or uptrend: print("short position opened") break print("trying to open short position...") self.exchange.entry("Short", False, lot) # OHLCV and indicator data, you can access history using list index # log indicator values print() logger.info(f"fast_sma: {fast_sma[-1]}") logger.info(f"slow_sma: {slow_sma[-1]}") logger.info(f"trend_sma: {trend_sma[-1]}") logger.info(f"uptrend: {uptrend}") logger.info(f"downtrend: {downtrend}") logger.info(f"golden_cross: {golden_cross}") logger.info(f"dead_cross: {dead_cross}") # log last candle OHLCV values logger.info(f"open: {open[-1]}") logger.info(f"high: {high[-1]}") logger.info(f"low: {low[-1]}") logger.info(f"close: {close[-1]}") logger.info(f"volume: {volume[-1]}")