def strategy(self, action, 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) logger.info("lagging log") self.exchange.plot('val_open', val_open[-1], 'b') self.exchange.plot('val_close', val_close[-1], 'r') 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, action, 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, action, open, close, high, low, volume): # this is your strategy function # use action argument for mutli timeframe implementation, since a timeframe string will be passed as `action` # get lot or set your own value which will be used to size orders # don't forget to round properly # careful default lot is about 20x your account size !!! lot = round(self.exchange.get_lot() / 20, 3) # Example of a callback function, which we can utilize for order execution etc. 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 you are using minute granularity or multiple timeframes its important to use `action` as its going pass a timeframe string # this way you can separate functionality and use proper ohlcv timeframe data that get passed each time if action == '1m': #if you use minute_granularity you can make use of 1m timeframe for various operations pass if action == '15m': # 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, callback=entry_callback) # 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, callback=entry_callback) # 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.isLongEntry.append(long_entry_condition) self.isShortEntry.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]}")