def calculate_signals(self, event): """ Generates a new set of signals based on the MAC SMA with the short window crossing the long window meaning a long entry and vice versa for a short entry. Parameters event - A MarketEvent object. """ if event.type == 'MARKET': for symbol in self.symbol_list: bars = self.bars.get_latest_bars_values(symbol, "close", N=self.long_window) if bars is not None and bars != []: short_sma = np.mean(bars[-self.short_window:]) long_sma = np.mean(bars[-self.long_window:]) dt = self.bars.get_latest_bar_datetime(symbol) sig_dir = "" strength = 1.0 strategy_id = 1 if short_sma > long_sma and self.bought[symbol] == "OUT": sig_dir = 'LONG' signal = SignalEvent(strategy_id, symbol, dt, sig_dir, strength) self.events.put(signal) self.bought[symbol] = 'LONG' elif short_sma < long_sma and self.bought[symbol] == "LONG": sig_dir = 'EXIT' signal = SignalEvent(strategy_id, symbol, dt, sig_dir, strength) self.events.put(signal) self.bought[symbol] = 'OUT'
def calculate_signals(self, event): """ Generates a new set of signals based on the MAC SMA with the short window crossing the long window meaning a long entry and vice versa for a short entry. Parameters event - A MarketEvent object. """ if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars_values(s, "close", N=self.long_window) bar_date = self.bars.get_latest_bar_datetime(s) if bars is not None and bars.size > 0: short_sma = np.mean(bars[-self.short_window:]) long_sma = np.mean(bars[-self.long_window:]) symbol = s cur_date = dt.utcnow() sig_dir = "" if short_sma > long_sma and self.bought[s] == "OUT": print("LONG: %s" % bar_date) sig_dir = 'LONG' signal = SignalEvent(1, symbol, cur_date, sig_dir, 10000) self.events.put(signal) self.bought[s] = 'LONG' elif short_sma < long_sma and self.bought[s] == "LONG": print("SHORT: %s" % bar_date) sig_dir = 'EXIT' signal = SignalEvent(1, symbol, cur_date, sig_dir, 10000) self.events.put(signal) self.bought[s] = 'OUT'
def calculate_signals(self, event): if event.type == 'TICK': pair = event.instrument price = event.bid pd = self.pairs_dict[pair] if pd["ticks"] == 0: pd["short_sma"] = price pd["long_sma"] = price else: pd["short_sma"] = self.calc_rolling_sma( pd["short_sma"], self.short_window, price) pd["long_sma"] = self.calc_rolling_sma(pd["long_sma"], self.long_window, price) # Only start the strategy when we have created an accurate short window if pd["ticks"] > self.short_window: if pd["short_sma"] > pd["long_sma"] and not pd["invested"]: signal = SignalEvent(pair, "market", "buy", event.time) self.events.put(signal) pd["invested"] = True if pd["short_sma"] < pd["long_sma"] and pd["invested"]: signal = SignalEvent(pair, "market", "sell", event.time) self.events.put(signal) pd["invested"] = False pd["ticks"] += 1
def calculate_signals(self, event, periods=12): """ params: event: periods: parameter of RSI, number of periods """ if event.type == "MARKET": for s in self.symbol_list: bars = self.bars.get_latest_bars(s, periods + 1) # Wait until at least "periods"+1 time periods market data is available if len(bars) == periods + 1: # Calculate RSI close_price = [x[5] for x in bars ] # close price for "periods"+1 periods close_price_diff = [ close_price[i] - close_price[i - 1] for i in range(1, periods + 1) ] ups_ = [x for x in close_price_diff if x > 0] drops_ = [x for x in close_price_diff if x < 0] ups_total = sum(ups_) drops_total = sum(drops_) if drops_total == 0 and ups_total == 0: # close prices for the last "periods" + 1 periods # haven't changed at all. Do not send signal, wait RSI = 50 elif drops_total == 0 and ups_total != 0: RSI = 100 else: RS = ups_total / drops_total RSI = 100 * RS / (1 + RS) # This is the RSI # Calculate the direction and strenght of the signal if RSI >= 70 and RSI < 80: signal = SignalEvent(bars[0][0], bars[0][1], 'SHORT', "weak") elif RSI >= 80 and RSI < 90: signal = SignalEvent(bars[0][0], bars[0][1], 'SHORT', "mild") elif RSI >= 90: signal = SignalEvent(bars[0][0], bars[0][1], 'SHORT', "strong") elif RSI <= 30 and RSI > 20: signal = SignalEvent(bars[0][0], bars[0][1], 'LONG', "weak") elif RSI <= 20 and RSI > 10: signal = SignalEvent(bars[0][0], bars[0][1], 'LONG', "mild") elif RSI <= 10: signal = SignalEvent(bars[0][0], bars[0][1], 'LONG', "strong") # Only when RSI is less than or equal to 30, or greater than or equal to # 70, a trading signal will be triggered if RSI <= 30 or RSI >= 70: self.events.put(signal)
def calculate_signals(self, event): if event.type == 'TICK': # Firstly dont do any thing until after 8am if 2 < int(event.time.hour) < 20: if self.grid is None: # Set up a grid self.grid = Grid(self.instrument) self.grid.start_grid(event.mid) else: self.work_grid(event) if event.time.hour >= 20: if self.grid is not None and self.grid.level_triggered != 0: signal = SignalEvent(event.instrument, "market", "close_all", time.time()) self.events.put(signal)
def calculate_signals(self, event): if event.type == 'TICK': pair = event.instrument price = event.bid pd = self.pairs_dict[pair] if pd["ticks"] == 0: pd["short_sma"] = price pd["long_sma"] = price else: pd["short_sma"] = self.calc_rolling_sma( pd["short_sma"], self.short_window, price) pd["long_sma"] = self.calc_rolling_sma(pd["long_sma"], self.long_window, price) # Si avvia la strategia solamente dopo aver creato una accurata finestra di breve periodo if pd["ticks"] > self.short_window: if pd["short_sma"] > pd["long_sma"] and not pd["invested"]: signal = SignalEvent(pair, "market", "buy", event.time) self.events.put(signal) pd["invested"] = True if pd["short_sma"] < pd["long_sma"] and pd["invested"]: signal = SignalEvent(pair, "market", "sell", event.time) self.events.put(signal) pd["invested"] = False pd["ticks"] += 1
def calculate_signals(self,event): if event.type == 'MARKET': for symbol in self.symbol_list: bars = self.bars.get_latest_bars_values(symbol,'close',N=self.long_window) if bars is not None and bars != []: short_sma = np.mean(bars[-self.short_window:]) long_sma = np.mean(bars[-self.long_window:]) dt = self.bars.get_latest_bar_datetime(symbol) sig_dir = '' strength = 1.0 strategy_id = 1 if short_sma > long_sma and self.bought[symbol] == 'OUT': sig_dir = 'LONG' signal = SignalEvent(strategy_id,symbol,dt,sig_dir,strength) self.events.put(signal) self.bought[symbol] = 'LONG' elif short_sma < long_sma and self.bought[symbol] == 'LONG': sig_dir = 'EXIT' signal = SignalEvent( strategy_id,symbol,dt,sig_dir,strength) self.events.put(signal) self.bought[symbol] = 'OUT'
def calculate_signals( self, event ): if isinstance(event, MarketEvent): for symbol in self.symbol_list: data = self.data.get_latest_data(symbol)[0] if data is not None and len(data) > 0: signal = SignalEvent( symbol, data[1], 'LONG' ) self.event_queue.put(signal) self.bought[symbol] = True
def calculate_signals(self, event): """ For "Buy and Hold" we generate a single signal per symbol and then no additional signals. This means we are constantly long the market from the date of strategy initialisation. Parameters event - A MarketEvent object. """ if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, n=50) # get last close price, calculate the H,(date,days,stock_data) last_n_data = pd.DataFrame( [bars[-i][5] for i in range(len(bars))]) isMmt = calH.H_calc(bars[0], 50, last_n_data) avr10 = sum(last_n_data[-5:]) if bars is not None and bars != []: # if there is no position yet if self.bought[s] == False and isMmt > 0.75: print(isMmt) # bars[-1] is the latest price info [5] is close, bars[0] is n=5 days ago if bars[-1][5] >= avr10: direction = 'LONG' strength = 5 self.bought[s] = True else: direction = 'SHORT' strength = 0 self.bought[s] = True # if there is position else: direction = 'EXIT' strength = 5 self.bought[s] = False # (Symbol, Datetime, Type = LONG, SHORT or EXIT,and the strength of the signal) signal = SignalEvent(bars[-1][0], bars[-1][1], direction, strength) self.events.put(signal) if len(bars) > 1: if bars[-1][1].month != bars[-2][ 1].month and s == self.symbol_list[0]: print(bars[-1][1])
def calculate_xy_signals(self, zscore_last): """ Calculates the actual x, y signal pairings to be sent to the signal generator. Parameters zscore_last - The current zscore to test against """ y_signal = None x_signal = None sid = self.strategy_id p0 = self.pair[0] p1 = self.pair[1] dt = self.datetime hr = abs(self.hedge_ratio) # If we're long the market and below the # negative of the high zscore threshold if zscore_last <= -self.zscore_high and not self.long_market: self.long_market = True y_signal = SignalEvent(sid, p0, dt, 'LONG', 1.0) x_signal = SignalEvent(sid, p1, dt, 'SHORT', hr) # If we're long the market and between the # absolute value of the low zscore threshold if abs(zscore_last) <= self.zscore_low and self.long_market: self.long_market = False y_signal = SignalEvent(sid, p0, dt, 'EXIT', 1.0) x_signal = SignalEvent(sid, p1, dt, 'EXIT', 1.0) # If we're short the market and above # the high zscore threshold if zscore_last >= self.zscore_high and not self.short_market: self.short_market = True y_signal = SignalEvent(sid, p0, dt, 'SHORT', 1.0) x_signal = SignalEvent(sid, p1, dt, 'LONG', hr) # If we're short the market and between the # absolute value of the low zscore threshold if abs(zscore_last) <= self.zscore_low and self.short_market: self.short_market = False y_signal = SignalEvent(sid, p0, dt, 'EXIT', 1.0) x_signal = SignalEvent(sid, p1, dt, 'EXIT', 1.0) return y_signal, x_signal
def calculate_signals(self, event): """ for "Buy and Hold" we generate a singal per symbol and then no additional signal.This means wa are constantly long the market from the date of strategy initialisation. :param event:A MarketEvent object. :return: event.type == "MARKET" 说明有新的市场数据加入,只是在最开始的时候 为每个股票 产出买入的信号,之后就不做任何事情 """ if event.type == "MARKET": for s in self.symbol_list: # 对每一个股票都产生一个买入的信号 bars = self.bars.get_latest_bars(s, N=1) if bars is not None and bars != []: if self.bought[s] == False: signal = SignalEvent(bars[0][0], bars[0][1], 'LONG') # (Symbol, Datetime, Type = LONG, SHORT or EXIT) self.events.put(signal) self.bought[s] = True
def calculate_xy_signals(self, zscore_last): """ Calcola le effettive coppie di segnali x, y da inviare al generatore di segnali. Parametri zscore_last - Il punteggio dello z-score su cui eseguire il test """ y_signal = None x_signal = None p0 = self.pair[0] p1 = self.pair[1] dt = self.datetime hr = abs(self.hedge_ratio) # Se siamo long sul mercato e al di sotto del # negativo della soglia alta dello zscore if zscore_last <= -self.zscore_high and not self.long_market: self.long_market = True y_signal = SignalEvent(1, p0, dt, 'LONG', 1.0) x_signal = SignalEvent(1, p1, dt, 'SHORT', hr) # Se siamo long sul mercato e tra il # valore assoluto della soglia bassa dello zscore if abs(zscore_last) <= self.zscore_low and self.long_market: self.long_market = False y_signal = SignalEvent(1, p0, dt, 'EXIT', 1.0) x_signal = SignalEvent(1, p1, dt, 'EXIT', 1.0) # Se siamo short sul mercato e oltre # la soglia alta dello z-score if zscore_last >= self.zscore_high and not self.short_market: self.short_market = True y_signal = SignalEvent(1, p0, dt, 'SHORT', 1.0) x_signal = SignalEvent(1, p1, dt, 'LONG', hr) # Se siamo short sul mercato e tra il # valore assoluto della soglia bassa dello z-score if abs(zscore_last) <= self.zscore_low and self.short_market: self.short_market = False y_signal = SignalEvent(1, p0, dt, 'EXIT', 1.0) x_signal = SignalEvent(1, p1, dt, 'EXIT', 1.0) return y_signal, x_signal
def calculate_signals(self, event): if event.type == 'TICK': # Firstly dont do any thing until after 8am if 2 < int(event.time.hour) < 20: if self.grid is None: # Set up a grid self.grid = Grid(self.instrument) self.grid.start_grid(event.mid, self.mode) else: if self.mode == 'AR': self.ar_grid(event) elif self.mode == 'TREND': self.trend_grid(event) if event.time.hour > 20: if self.grid is not None: signal = SignalEvent(event.instrument, "market", "close_all", time.time()) self.events.put(signal) self.grid = None
def caculate_signals(self, event): """ For "Buy and Hold" we generate a single signal per symbol and then no additional signals. This is implemented by constantly adding long signal to the market in the queue data-structure since the date of strategy initialisation :param event: A MarketEvent object. :return: """ if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) if bars is not None and bars != []: if self.bought[s] == False: # (Symbol, Datetime, Type = LONG, SHORT or EXIT) signal = SignalEvent(bars[0][0], bars[0][1], 'LONG') self.events.put(signal) self.bought[s] = False
def calculate_signals(self, event): """ For "Buy and Hold" we generate a single signal per symbol and then no additional signals. This means we are constantly long the market from the date of strategy initialisation. Parameters event - A BarArrive object. """ if event.type == 'BarArrive': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) if bars is not None and bars != []: if not self.bought[s]: # strategy ID, symbol, datetime, signal_type, strength signal = SignalEvent(1, s, bars[0][0], 'LONG', 1.0) self.events.put(signal) self.bought[s] = True
def test_update_signal(self): events_queue = queue.Queue(100) bars = HistoricCSVDataHandler(events_queue, './tests/datasets/', ['BTC_ETC'], ['open', 'high', 'low', 'close']) p = NaivePortfolio(bars, events_queue, datetime(2017, 4, 1, 0, 0, 0), 1000.0) bars.update_bars() signal = SignalEvent('BUY_AND_HOLD', 'BTC_ETC', datetime.utcnow(), 'LONG', 1.0) p.update_signal(signal) events_queue.get(False) # MARKET event = events_queue.get(False) # ORDER self.assertEqual(event.type, 'ORDER') self.assertEqual(event.order_type, 'MKT') self.assertEqual(event.direction, 'BUY') self.assertEqual(event.quantity, 1)
def calculate_signals(self, event): """ For "Buy and Hold" we generate a single signal per symbol and then no additional signals. This means we are constantly long the market from the date of strategy initialisation. Parameters event - A MarketEvent object. """ if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) if bars is not None and bars != []: if self.bought[s] == False: # (Symbol, Datetime, Type = LONG, SHORT or EXIT) signal = SignalEvent(bars[0][0], bars[0][1], 'LONG') self.events.put(signal) self.bought[s] = True
def monitor(self): size = '10' losers = market_infor_api.NewLosers() signals = [] for loser in losers: if float(loser.size) < 10: continue # 1:开多2:开空3:平多4:平空 if loser.otype == 4: #如果是多头空仓 就开空仓 price = str(loser.price * 0.99) otype = '2' elif loser.otype == 3: price = str(loser.price * 1.01) otype = '1' signals.append(SignalEvent('TAKE_ORDER', price, size, otype)) del losers return signals
def monitor(self): signals = [] positions = self.account.get_positions() for position in positions: if abs(position.ratio) > 8 and position.size > 0: "如果收益超过+-10%" # 1:开多2:开空3:平多4:平空 size = position.size if position.otype == 1: price = position.best_ask - 0.001 otype = '3' elif position.otype == 2: "空头平仓 获取最优买价" price = position.best_bid + 0.001 otype = '4' else: raise TypeError signals.append(SignalEvent('TAKE_ORDER', price, size, otype)) del positions return signals
def calculate_signal(self): interested_bar_vals = self.data.get_bar_values(self.symbol, "adj_close", N=2) bar_date = self.data.get_latest_bar_datetime(self.symbol) if len(interested_bar_vals) > 0: current_val = interested_bar_vals[-1] previous_val = interested_bar_vals[-2] if current_val > previous_val: signal = "BUY" elif current_val < previous_val: signal = "SELL" else: signal = "NONE" else: signal = "NONE" new_event = SignalEvent(self.symbol, bar_date, signal, 1) self.events.put(new_event)
def calculate_signals(self, event): if event.type == 'MARKET': s0 = 'BTC_ETC' s1 = 'BTC_LTC' if len(self.bars.latest_symbol_data[s0]) >= self.LOOK_BACK and len( self.bars.latest_symbol_data[s1]) > self.LOOK_BACK: X = self.bars.get_latest_bars(s0, self.LOOK_BACK) Y = self.bars.get_latest_bars(s1, self.LOOK_BACK) X = pd.DataFrame(X) X.set_index('datetime', inplace=True) Y = pd.DataFrame(Y) Y.set_index('datetime', inplace=True) print(X) ols = rolling_beta(X['close'], Y['close'], X.index, window=self.LOOK_BACK) pairs = pd.DataFrame( X['close'], Y['close'], columns=['{}_close'.format(s0), '{}_close'.format(s1)]) pairs['hedge_ratio'] = ols['beta'] pairs['hedge_ratio'] = [v for v in pairs['hedge_ratio'].values] pairs['spread'] = pairs['{}_close'.format( s0)] - pairs['hedge_ratio'] * pairs['{}_close'.format(s1)] pairs['zscore'] = (pairs['spread'] - np.mean( pairs['spread'])) / np.std(pairs['spread']) if pairs['zscore', -1] <= -self.Z_ENTRY_THRESHOLD: signal = SignalEvent(s0, X['close', -1], 'LONG', 1.0) self.queue.put(signal) signal = SignalEvent(s1, Y['close', -1], 'SHORT', 1.0) self.queue.put(signal) elif pairs['zscore', -1] >= self.Z_ENTRY_THRESHOLD: signal = SignalEvent(s0, X['close', -1], 'SHORT', 1.0) self.queue.put(signal) signal = SignalEvent(s1, Y['close', -1], 'LONG', 1.0) self.queue.put(signal) elif pairs['zscore', -1] <= self.Z_EXIT_THRESHOLD: signal = SignalEvent(s0, X['close', -1], 'EXIT', 1.0) self.queue.put(signal) signal = SignalEvent(s1, Y['close', -1], 'EXIT', 1.0) self.queue.put(signal)
def calculate_signals(self, event): ''' Reacts to a MarketEvent object and for each symbol obtains the latest N bar closing prices where N is the larger lookback period. Then it calculates the simple moving averages. If the short SMA exceeds the long SMA, go long. If the long SMA exceeds the short SMA, exit the position. It does this by generating a SignalEvent object if there is a moving average cross and updating the "bought" attribute of the symbol to be 'LONG' or 'OUT' Parameters: event - a MarketEvent object ''' if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars_values(s, 'adj_close_price', N=self.long_window) bar_date = self.bars.get_latest_bar_datetime(s) if bars is not None and bars != []: short_sma = np.mean(bars[-self.short_window:]) long_sma = np.mean(bars[-self.long_window:]) symbol = s dt = datetime.datetime.utcnow() sig_dir = '' if short_sma > long_sma and self.bought[s] == 'OUT': print('LONG: %s' % bar_date) sig_dir = 'LONG' signal = SignalEvent(strategy_id=1, symbol=symbol, datetime=dt, signal_type=sig_dir, strength=1.0) self.events.put(signal) self.bought[s] = 'LONG'
def calculate_signals(self, marketevent) -> list: listOfEvent = [] if marketevent.type == 'MARKET' or marketevent.type == 'POLL': for secObj in self.sec_pool: if len(secObj.histBars) > 0: prev_price = libs.toPrec( secObj.histBars.tail(1)['close'].values[0], 2) else: prev_price = secObj.cursorBar['open'].values[0] # for test only listOfEvent.append( SignalEvent(datetime=marketevent.datetime, secObj=secObj, position=self.position, signal_type='LONG:{}@{}'.format(1, 1), signal_src=self.name)) return listOfEvent if secObj.cursorBar['vol'].values[0] != 0: '''-----conditions for LONG-----''' if secObj.cursorBar['open'].values[0] < prev_price: price = libs.toPrec(secObj.cursorBar['open'].values[0], 2) # 开盘价买入 assert self.position[0]['sec_obj'].ts_code == 'cash' cash_available = self.position[0]['available'] mkt_quantity = cash_available / ( price * (1 + secObj.commission) ) if cash_available > 0 else 0 mkt_quantity = libs.toPrec(mkt_quantity, secObj.tradeunit, 'd') if mkt_quantity > 0: listOfEvent.append( SignalEvent(datetime=marketevent.datetime, secObj=secObj, position=self.position, signal_type='LONG:{}@{}'.format( mkt_quantity, price), signal_src=self.name)) print( 'signal generated by {} to LONG:{}@{}'.format( self.name, mkt_quantity, price)) '''-----conditions for SHORT-----''' if secObj.cursorBar['close'].values[0] > prev_price: price = libs.toPrec( secObj.cursorBar['close'].values[0], 2) sec_available = 0 for holding in self.position: if holding['sec_obj'].ts_code == secObj.ts_code: sec_available = holding['available'] if sec_available > 0: listOfEvent.append( SignalEvent(datetime=marketevent.datetime, secObj=secObj, position=self.position, signal_type='SHORT:{}@{}'.format( sec_available, price), signal_src=self.name)) print( 'signal generated by {} to SHORT:{}@{}'.format( self.name, sec_available, price)) # to remember strategy-specific variables here # ... break # only react on the 1st sec in the sec pool if the pool has more than 1 else: print('{} skipped reaction on {} as non trade date:{}'. format(self.name, secObj.sec_name, marketevent.datetime)) return listOfEvent
def calculate_signals(self, marketevent) -> list: listOfEvent = [] # supporting conditions if self.sec_pool[0]._heartbeat.freq != '1d': print(f'{self.name} works only with freq=1d, skipping...') return listOfEvent if marketevent.type == 'MARKET' or marketevent.type == 'POLL': camparedate = self.sec_pool[0]._dataagent.int_findOffsetDate( self.sec_pool[0].cursorTick['unit_intdate'], self.period, self.sec_pool[0]._heartbeat._df_unitAxis) if camparedate is None: print( f'not on trade on {camparedate} from {self.period} trade days ago' ) return listOfEvent for secObj in self.sec_pool: # 如果无n日前的数据 if not self.dict_comparegrowth: break if secObj.cursorBar['vol'].values[ 0] == 0: # if the sec is not on trade today # input(f'!!!!!!! {secObj.ts_code} is not on trade today, press enter to skip signal generation...') print( f'!!!!!!! {secObj.ts_code} is not on trade today, press enter to skip signal generation...' ) continue '''-----conditions for SHORT-----''' if self.dict_comparegrowth[ secObj.ts_code][1] != 1 and self.dict_comparegrowth[ secObj.ts_code][0] < self.neg_threshold: price = libs.toPrec(secObj.cursorBar['open'].values[0], 2) # 开盘价 sec_available = 0 for holding in self.position: if holding['sec_obj'].ts_code == secObj.ts_code: sec_available = holding['available'] if sec_available > 0: listOfEvent.append( SignalEvent(datetime=marketevent.datetime, secObj=secObj, position=self.position, signal_type='SHORT:{}@{}'.format( sec_available, price), signal_src=self.name)) print('signal generated by {} to SHORT:{}@{}'.format( self.name, sec_available, price)) '''-----conditions for LONG-----''' if self.dict_comparegrowth[ secObj.ts_code][1] == 1 and self.dict_comparegrowth[ secObj.ts_code][0] > self.pos_threshold: price = libs.toPrec(secObj.cursorBar['open'].values[0], 2) # 开盘价买入 if price == 0: # means the ETF product still not available yet despite of the existence of anchoring index print( 'cannot LONG {} because the ETF does not exist yet...' .format(secObj.ts_code)) continue assert self.position[0]['sec_obj'].ts_code == 'cash' cash_available = self.position[0]['available'] mkt_quantity = cash_available / ( price * (1 + secObj.commission)) if cash_available > 0 else 0 mkt_quantity = libs.toPrec(mkt_quantity, secObj.tradeunit, 'd') if mkt_quantity > 0: listOfEvent.append( SignalEvent(datetime=marketevent.datetime, secObj=secObj, position=self.position, signal_type='LONG:{}@{}'.format( mkt_quantity, price), signal_src=self.name)) print('signal generated by {} to LONG:{}@{}'.format( self.name, mkt_quantity, price)) # if Poll event, no need to update dict_comparegrowth as it is meant to be used in next trade dau if marketevent.type != 'POLL': valuelist = [] self.dict_comparegrowth = None for secObj in self.sec_pool: if secObj.anchorObj is None: secObj.anchorObj = secObj print( f'no achoring intrument found for sec {secObj.sec_name}, using itself to simulate...' ) currentprice = secObj.anchorObj.cursorBar['close'].values[ 0] compareprice = secObj.anchorObj.allBars.loc[ secObj.anchorObj.allBars['unit_intdate'] == camparedate]['close'].values[0] if compareprice == 0: # if any of the n-days-ago prices is 0, means the index did not existed hence the whole strategy is invalid print( 'anchor sec {} did not exist on {}, 28Turn strategy skipped reaction' .format(secObj.anchorObj.sec_name, camparedate)) break else: growth_rate = (currentprice - compareprice) / compareprice valuelist.append([secObj.ts_code, growth_rate]) else: valuelist.sort(key=lambda x: x[1], reverse=True) rank = 1 valuelist[0].append(1) for i in range(1, len(valuelist)): if valuelist[i][1] != valuelist[i - 1][1]: rank += 1 valuelist[i].append(rank) self.dict_comparegrowth = {x[0]: x[1:] for x in valuelist} print(f'{self.name} calculated ranking is:', self.dict_comparegrowth) return listOfEvent
def trend_grid(self, event): # If the mid has crossed the first buy, then generate a signal if self.grid.level_triggered == 0 and event.mid > self.grid.buy_level_one: signal = SignalEvent(event.instrument, "market", "buy", time.time()) print "Opening position level 1 TREND, mid %s" % event.mid self.events.put(signal) self.grid.shift_grid_trend(1) elif self.grid.level_triggered == 1 and event.mid > self.grid.buy_level_two: signal = SignalEvent(event.instrument, "market", "buy", time.time(), units_multiplier=0.5) self.events.put(signal) print "Opening position level 2 TREND, mid %s" % event.mid self.grid.shift_grid_trend(1) elif self.grid.level_triggered == 2 and event.mid > self.grid.buy_level_three: signal = SignalEvent(event.instrument, "market", "buy", time.time(), units_multiplier=0.25) self.events.put(signal) print "Opening position level 3 TREND, mid %s" % event.mid self.grid.shift_grid_trend(1) elif self.grid.level_triggered >= 3 and event.mid > self.grid.buy_next_marker: print "Shifting new marker, mid %s" % event.mid self.grid.shift_grid_trend(1, True) elif self.grid.level_triggered > 0 and event.mid < self.grid.stop_loss_buy: signal = SignalEvent(event.instrument, "market", "close_all", time.time()) self.events.put(signal) if self.mode_changer == 0: self.mode = 'AR' self.mode_changer = 0 else: self.mode_changer += 1 print "Closing all buys at stop loss, mid %s" % event.mid self.grid = None # Done with this grid. # If the mid has crossed the first sell, then generate a signal elif self.grid.level_triggered == 0 and event.mid < self.grid.sell_level_one: signal = SignalEvent(event.instrument, "market", "sell", time.time()) self.events.put(signal) print "Opening position level -1 TREND, mid %s" % event.mid self.grid.shift_grid_trend(-1) elif self.grid.level_triggered == -1 and event.mid < self.grid.sell_level_two: signal = SignalEvent(event.instrument, "market", "sell", time.time(), units_multiplier=0.5) self.events.put(signal) print "Opening position level -2 TREND, mid %s" % event.mid self.grid.shift_grid_trend(-1) elif self.grid.level_triggered == -2 and event.mid < self.grid.sell_level_three: signal = SignalEvent(event.instrument, "market", "sell", time.time(), units_multiplier=0.25) self.events.put(signal) print "Opening position level -3 TREND, mid %s" % event.mid self.grid.shift_grid_trend(-1) elif self.grid.level_triggered <= -3 and event.mid < self.grid.sell_next_marker: print "Shifting grid, mid %s" % event.mid self.grid.shift_grid_trend(-1, True) elif self.grid.level_triggered < 0 and event.mid > self.grid.stop_loss_sell: signal = SignalEvent(event.instrument, "market", "close_all", time.time()) self.events.put(signal) if self.mode_changer == 0: self.mode = 'AR' self.mode_changer = 0 else: self.mode_changer += 1 print "Closing all sells stop loss, mid %s" % event.mid self.grid = None # Done with this grid. if time.time() - self.start_time > 2: print self.grid self.start_time = time.time()
def calculate_signals(self, event): if event.type == 'TICK': if self.start_time == 0: self.start_time = event.time x = { 'Instrument': [event.instrument], 'Time': [event.time], 'Bid': [float(event.bid)], 'Ask': [float(event.ask)], 'Mid': [float(event.mid)] } tick_df = pd.DataFrame(x) tick_df = tick_df.set_index(pd.DatetimeIndex(tick_df['Time'])) del tick_df['Time'] self.recent_ticks = self.recent_ticks.append(tick_df) if (event.time - self.start_time).total_seconds() > 60: bar = ticks_to_candle(self.recent_ticks, "1M", type="Mid") self.recent_ticks = pd.DataFrame() self.start_time = event.time future_return = self.perform_prediction(bar)[0] if future_return >= 2: print "Entering LONG position" signal = SignalEvent(event.instrument, "market", "buy", time.time()) self.events.put(signal) open_signal = OpenSignal(signal.instrument, signal.order_type, signal.side, signal.time) x = True for s in self.open_signals: if s.side == 'sell': print "Already have an short pos, so closing it" self.open_signals.remove(s) x = False continue if x: self.open_signals.append(open_signal) if future_return <= -2: print "Entering SHORT position" signal = SignalEvent(event.instrument, "market", "sell", time.time()) self.events.put(signal) open_signal = OpenSignal(signal.instrument, signal.order_type, signal.side, signal.time) x = True for s in self.open_signals: if s.side == 'buy': print "Already have an open pos, so closing it" self.open_signals.remove(s) x = False continue if x: self.open_signals.append(open_signal) # close any positions that have been open for 5 mins for signal in self.open_signals: if signal.open_time == 5: if signal.side == 'buy': new_signal = SignalEvent(signal.instrument, 'market', 'sell', time.time()) self.events.put(new_signal) self.open_signals.remove(signal) print "Closing long pos after 5mins" else: new_signal = SignalEvent(signal.instrument, 'market', 'buy', time.time()) self.events.put(new_signal) self.open_signals.remove(signal) print "Closing short pos after 5mins" else: signal.open_time += 1
def calculate_signals(self, event): if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) #if s == 'GBPEUR': self.close = np.append(self.close, bars[0][5]) self.high = np.append(self.high, bars[0][3]) self.low = np.append(self.low, bars[0][4]) # atr_22=np.around(talib.ATR(self.high,self.low,self.close,timeperiod=22),decimals=4) # min_22=np.around(talib.MIN(self.low,timeperiod = 22),decimals=4) # max_22=np.around(talib.MAX(self.high,timeperiod = 22),decimals=4) # ts_long = max_22 - atr_22*3.5 # ts_short = min_22+atr_22*3.5 self.days.append(bars[0][1].dayofweek) if all(day == bars[0][1].dayofweek for day in self.days): self.previous_high.append(self.high[-1]) self.previous_low.append(self.low[-1]) self.previous_close.append(self.close[-1]) else: self.max_previous_high, self.min_previous_low = max( self.previous_high), min(self.previous_low) self.last_close = self.previous_close[-1] self.days = [] self.previous_high = [] self.previous_low = [] self.previous_high.append(self.high[-1]) self.previous_low.append(self.low[-1]) # print bars[0][1],(self.max_previous_high+self.min_previous_low+self.last_close)/3 # print self.max_previous_high,self.min_previous_low,self.last_close #---------------INDICATORS ------------------------- daily_pivot_point = (self.max_previous_high + self.min_previous_low + self.last_close) / 3 self.pivot_points = np.append(self.pivot_points, daily_pivot_point) R1 = daily_pivot_point * 2 - self.min_previous_low R2 = daily_pivot_point + self.max_previous_high - self.min_previous_low R3 = self.max_previous_high + 2 * (daily_pivot_point - self.min_previous_low) S1 = daily_pivot_point * 2 - self.max_previous_high S2 = daily_pivot_point - self.max_previous_high + self.min_previous_low S3 = self.min_previous_low - 2 * (self.max_previous_high - daily_pivot_point) hourly_pivot_point = (self.close[-1] + self.high[-1] + self.low[-1]) / 3 self.hourly_pivot_points = np.append(self.hourly_pivot_points, hourly_pivot_point) MA_hourly_pivot_point_3 = np.around(talib.SMA(np.array( self.hourly_pivot_points), timeperiod=3), decimals=4) MA_hourly_pivot_point_5 = np.around(talib.SMA(np.array( self.close), timeperiod=5), decimals=4) if bars is not None and bars != []: if self.position.direction == 'EXIT': if ((R1 - 0.0010) <= self.high[-1] <= R1) or ( (R2 - 0.0010) <= self.high[-1] <= R2) or ( (R3 - 0.0010) <= self.high[-1] <= R3): if (MA_hourly_pivot_point_3[-1] < MA_hourly_pivot_point_5[-1] and MA_hourly_pivot_point_3[-2] >= MA_hourly_pivot_point_5[-2] ) or ( MA_hourly_pivot_point_3[-1] < MA_hourly_pivot_point_5[-1] and MA_hourly_pivot_point_3[-3] >= MA_hourly_pivot_point_5[-3] ) and self.close[-1] < MA_hourly_pivot_point_3[ -1] and self.close[ -1] < MA_hourly_pivot_point_3[ -1] and self.bought[s] == False: self.short_close_enter_price = self.close[-1] self.events.put( SignalEvent(bars[0][0], bars[0][1], 'SHORT')) #print self.i,' ENTER SHORT-->',bars[0][1],'close enter','-->',self.close[-1] self.position.direction = 'SHORT' self.bought[s] = True self.temp_close.append(self.close[-1]) #print self.temp_close,self.close return elif ((S1 + 0.001) > self.low[-1] > S1) or ( (S2 + 0.001) > self.low[-1] > S2) or ( (S3 + 0.001) > self.low[-1] > S3): if ( MA_hourly_pivot_point_3[-1] < MA_hourly_pivot_point_5[-1] and MA_hourly_pivot_point_3[-2] >= MA_hourly_pivot_point_5[-2] ) or ( MA_hourly_pivot_point_3[-1] < MA_hourly_pivot_point_5[-1] and MA_hourly_pivot_point_3[-3] >= MA_hourly_pivot_point_5[-3] ) and self.close[-1] > MA_hourly_pivot_point_3[-1]: self.long_close_enter_price = self.close[-1] #self.bought[s] = True self.events.put( SignalEvent(bars[0][0], bars[0][1], 'LONG')) self.position.direction = 'LONG' #print self.i,"ENTER LONG-->",bars[0][1], 'close enter','-->',self.close[-1] self.bought[s] = True self.temp_close.append(self.close[-1]) return elif self.position.direction == 'SHORT': if self.close[-1] >= self.temp_close[ 0] + 0.0035 or self.close[ -1] <= self.temp_close[0] - 0.007: #print self.close[-1], self.temp_close[0], min(self.temp_close) ,min(self.temp_close)+(0.0040/(1.2+((self.temp_close[0]-(min(self.temp_close)))*100))) self.position.direction = 'EXIT' #print self.i,'EXIT SHORT',bars[0][1],'close enter','-->',self.close[-1] self.bought[s] = False self.events.put( SignalEvent(bars[0][0], bars[0][1], 'EXIT')) self.temp_close = [] return elif self.position.direction == 'LONG': if self.close[-1] <= self.temp_close[ 0] - 0.0035 or self.close[ -1] >= self.temp_close[0] + 0.007: #if self.long_close_enter_price - self.close[-1] >=0.0020: #assert(self.long_close_enter_price-self.close[-1]>=0.0020) self.position.direction = 'EXIT' self.long_close_enter_price = 0 self.bought[s] = False self.events.put( SignalEvent(bars[0][0], bars[0][1], 'EXIT')) self.temp_close = [] return if self.plot: self.time_stamp.append(bars[0][1]) self.close_plotting.append(bars[0][5]) #print bars[0][1],bars[0][1].dayofweek self.pivot_points_plotting.append(daily_pivot_point) self.r1_plotting.append(R1) self.s1_plotting.append(S1) if len(self.time_stamp) > 250: del self.time_stamp[0] del self.close_plotting[0] del self.pivot_points_plotting[0] del self.r1_plotting[0] del self.s1_plotting[0] xmin, xmax, ymin, ymax = [ min(self.time_stamp), max(self.time_stamp), .82, 1 ] self.line1.set_xdata(self.time_stamp) self.line1.set_ydata(self.close_plotting) self.line2.set_xdata(self.time_stamp) self.line2.set_ydata(self.pivot_points_plotting) self.line3.set_xdata(self.time_stamp) self.line3.set_ydata(self.r1_plotting) self.line4.set_xdata(self.time_stamp) self.line4.set_ydata(self.s1_plotting) plt.axis([xmin, xmax, ymin, ymax]) self.fig.canvas.restore_region( self.background) # restore background self.ax1.draw_artist(self.line1) # redraw just the points self.fig.canvas.blit(self.ax1.bbox) if self.position.direction == 'SHORT' or self.position.direction == 'LONG': self.temp_close.append(self.close[-1]) elif self.position.direction == 'EXIT': self.temp_close = []
def calculate_signals(self, event): """ For "Buy and Hold" we generate a single signal per symbol and then no additional signals. This means we are constantly long the market from the date of strategy initialisation. Parameters event - A MarketEvent object. """ #---------- WORKING ---------- #plt.xlabel("Dates") # fig=plt.figure(figsize=(14,10),dpi=80,facecolor='w',edgecolor='k') # ax1=fig.add_subplot(1,1,1) # ax1.cla() # plt.ion() # plt.show(False) # ax1.hold(True) # ema_short,ema_middle,ema_fast,close,time_stamp=[],[],[],[],[] # line1, = ax1.plot(time_stamp,close,alpha=0.8,color='blue',markerfacecolor='red') # line2, = ax1.plot(time_stamp,ema_short,alpha=0.8,color='green') # fig.show() # fig.canvas.draw() # background=fig.canvas.copy_from_bbox(ax1.bbox) if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) #if s == 'GBPEUR': self.close = np.append(self.close, bars[0][5]) self.high = np.append(self.high, bars[0][3]) self.low = np.append(self.low, bars[0][4]) # print bars[0][1], type(bars[0][1]) # exit() ema_10 = np.around(talib.EMA(self.close, timeperiod=10), decimals=4) ema_25 = np.around(talib.EMA(self.close, timeperiod=25), decimals=4) ema_50 = np.around(talib.EMA(self.close, timeperiod=50), decimals=4) atr_22 = np.around(talib.ATR(self.high, self.low, self.close, timeperiod=22), decimals=4) min_22 = np.around(talib.MIN(self.low, timeperiod=22), decimals=4) max_22 = np.around(talib.MAX(self.high, timeperiod=22), decimals=4) ts_long = max_22 - atr_22 * 3.5 ts_short = min_22 + atr_22 * 3.5 #--------PLOTTING---------------- #if bars[0][1].dayofweek<4: self.time_stamp.append(bars[0][1]) self.close_plotting.append(bars[0][5]) #print bars[0][1],bars[0][1].dayofweek self.ema_short.append(ema_10[-1]) if len(self.time_stamp) > 250: del self.time_stamp[0] del self.close_plotting[0] del self.ema_short[0] xmin, xmax, ymin, ymax = [ min(self.time_stamp), max(self.time_stamp), .82, 1 ] self.line1.set_xdata(self.time_stamp) self.line1.set_ydata(self.close_plotting) self.line2.set_xdata(self.time_stamp) self.line2.set_ydata(self.ema_short) plt.axis([xmin, xmax, ymin, ymax]) self.fig.canvas.restore_region( self.background) # restore background self.ax1.draw_artist(self.line1) # redraw just the points self.fig.canvas.blit(self.ax1.bbox) #candlestick(self.ax1,bars) #x=mdates.datestr2num(bars[0][1]) #plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y%m%d %H:%M:%S')) #plt.gca().xaxis.set_major_locator(mdates.SecondLocator()) #print x #ax1.autofmt_xdate() # ax1.fmt_xdata =bars[0][1] #mdates.DateFormatter(bars[0][1]) # day = mdates.DayLocator() # daysFmt=mdates.DateFormatter('%Y%m%d %H:%M:%S') # ax1.xaxis.set_major_locator(day) # # # plt.gcf().autofmt_xdate() #rotates labels # #ax1.plot(bars[0][1]) # plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y%m%d')) #plt.plot(atr_22,'g--') # plt.draw() y_min = 0 y_max = 0 # #plt.plot(atr_22,"#DDA0A0",label='ATR_22') #plt.plot(min_22,"#DDA0A0",label='ATR_22') #assert(len(self.a) == sma) if bars is not None and bars != []: if self.position.direction == 'EXIT': if self.close[-1] < ema_50[-1]: if ema_10[-1] < ema_50[-1] and pd.Series( ema_50).shift( ).values[-1] <= pd.Series(ema_10).shift( ).values[-1] and self.bought[s] == False: self.short_close_enter_price = self.close[-1] self.events.put( SignalEvent(bars[0][0], bars[0][1], 'SHORT')) #print self.i,' ENTER SHORT-->',bars[0][1],'close enter','-->',self.close[-1] self.position.direction = 'SHORT' self.bought[s] = True self.temp_close.append(self.close[-1]) #print self.temp_close,self.close #y_min=bars[0][1] self.start_short_span = self.time_stamp[-1] # p=plt.axvspan(self.start_span,self.time_stamp[-1]) #self.s.append(self.time_stamp[-1]) return elif self.close[-1] > ema_50[-1]: if ema_10[-1] > ema_50[-1] and pd.Series( ema_50).shift().values[-1] >= pd.Series( ema_10).shift().values[-1]: self.long_close_enter_price = self.close[-1] #self.bought[s] = True self.events.put( SignalEvent(bars[0][0], bars[0][1], 'LONG')) self.position.direction = 'LONG' #print self.i,"ENTER LONG-->",bars[0][1], 'close enter','-->',self.close[-1] self.bought[s] = True self.temp_close.append(self.close[-1]) self.start_long_span = self.time_stamp[-1] return elif self.position.direction == 'SHORT': if self.close[-1] >= min( self.temp_close) + (0.0035 / (1.1 + ( (self.temp_close[0] - (min(self.temp_close))) * 100))): #print self.close[-1], self.temp_close[0], min(self.temp_close) ,min(self.temp_close)+(0.0040/(1.2+((self.temp_close[0]-(min(self.temp_close)))*100))) self.position.direction = 'EXIT' #print self.i,'EXIT SHORT',bars[0][1],'close enter','-->',self.close[-1] self.bought[s] = False self.events.put( SignalEvent(bars[0][0], bars[0][1], 'EXIT')) self.temp_close = [] #y_max=bars[0][1] #plt.axvspan(y_min,y_max,facecolor='g') #plt.draw() self.end_short_span = self.time_stamp[-1] p = plt.axvspan(self.start_short_span, self.end_short_span, facecolor='r', alpha=.3) return elif self.position.direction == 'LONG': if self.close[-1] <= max(self.temp_close) - ( 0.0035 / (1.1 + (((max(self.temp_close) - self.temp_close[0])) * 100))): #if self.long_close_enter_price - self.close[-1] >=0.0020: #assert(self.long_close_enter_price-self.close[-1]>=0.0020) self.position.direction = 'EXIT' self.long_close_enter_price = 0 self.bought[s] = False self.events.put( SignalEvent(bars[0][0], bars[0][1], 'EXIT')) self.end_long_span = self.time_stamp[-1] p = plt.axvspan(self.start_long_span, self.end_long_span, facecolor='g', alpha=.3) #print self.i,'EXIT LONG', bars[0][1],'close exit','-->',self.close[-1] self.temp_close = [] return self.i += 1 if self.position.direction == 'SHORT' or self.position.direction == 'LONG': self.temp_close.append(self.close[-1]) elif self.position.direction == 'EXIT': self.temp_close = []
def calculate_signals(self, event): if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) print bars[0] ## if prev is initial then obtain the first value if s not in self.prev_bars: ##may need to do this only if the calculation for zero gives issues self.prev_bars[s] = self.bars.update_bars() ##self.prev_bars[s] = self.bars.get_first_bar(s, N=0) ##print self.prev_bars[s] ##converting from tuple from original data etc means lets set prev initially to zero as the closing value prev = 0 else: self.prev_bars[s] = self.bars.update_bars() print(self.prev_bars[s]) if (self.prev_bars[s] is not None): prev = self.prev_bars[s][5] prev = 0 ##current curr = bars[0][5] ##delta value delta = curr - prev ## per change if prev == 0: percent_change = 0 else: percent_change = delta / prev if bars is not None and bars != []: if self.bought[s] == True: # (Symbol, Datetime, Type = LONG, SHORT, EXIT) if percent_change > self.g_sell_gain_thresh: signal = SignalEvent(bars[0][0], bars[0][1], 'EXIT') self.events.put(signal) time.sleep(0.01) self.bought[s] = False self.prev_bars[s][5] = curr ##Add code to reset g_sell_gain_thresh/ or set it outside of block for each symbol elif percent_change < self.g_sell_loss_thresh: signal = SignalEvent(bars[0][0], bars[0][1], 'EXIT') self.prev_bars[s][5] = curr self.bought[s] = False ##Add code to reset g_sell_loss_thresh/ or set it outside of block for each symbol else: pass else: if percent_change < self.g_buy_thresh or percent_change > self.g_buy_again_thresh: signal = SignalEvent(bars[0][0], bars[0][1], 'LONG') self.events.put(signal) time.sleep(0.01) self.prev_bars[s][5] = curr self.bought[s] = True ##Add code to reset g_buy_thresh and g_buy_again_thresh/ or set it outside of block for each symbol else: pass
def run(self, op_data: dict, req_data: list, timeframe: str, symbol: str, exchange): """ Run the model with the given data. Args: None: Returns: SignalEvent if signal is produced, otherwise None. Raises: None. """ self.logger.debug( "Running " + str(timeframe) + " " + self.get_name() + ".") if timeframe in self.operating_timeframes: features = list(zip( op_data[timeframe].index, op_data[timeframe]['open'], op_data[timeframe].EMA10, op_data[timeframe].EMA20)) longs = {'price': [], 'time': []} shorts = {'price': [], 'time': []} # Check for EMA crosses. for i in range(len(op_data[timeframe].index)): fast = features[i][2] slow = features[i][3] fast_minus_1 = features[i - 1][2] slow_minus_1 = features[i - 1][3] fast_minus_2 = features[i - 2][2] slow_minus_2 = features[i - 2][3] if fast is not None and slow is not None: # Short cross if slow > fast: if slow_minus_1 < fast_minus_1 and slow_minus_2 < fast_minus_2: shorts['price'].append(features[i][1]) shorts['time'].append(features[i][0]) # Long cross elif slow < fast: if slow_minus_1 > fast_minus_1 and slow_minus_2 > fast_minus_2: longs['price'].append(features[i][1]) longs['time'].append(features[i][0]) if longs or shorts: signal = False # Generate trade signal if current bar has an entry. if features[-1][0] == longs['time'][-1]: direction = "long" entry_price = longs['price'][-1] entry_ts = longs['time'][-1] signal = True elif features[-1][0] == shorts['time'][-1]: direction = "short" entry_price = shorts['price'][-1] entry_ts = shorts['time'][-1] signal = True if signal: # Plot the signal. chart = go.Figure( data=[ # Bars. go.Ohlc( x=op_data[timeframe].index, open=op_data[timeframe]['open'], high=op_data[timeframe]['high'], low=op_data[timeframe]['low'], close=op_data[timeframe]['close'], name="Bars", increasing_line_color='black', decreasing_line_color='black'), # EMA10. go.Scatter( x=op_data[timeframe].index, y=op_data[timeframe].EMA10, line=dict(color='gray', width=1), name="EMA10"), # EMA20. go.Scatter( x=op_data[timeframe].index, y=op_data[timeframe].EMA20, line=dict(color='black', width=1), name="EMA20"), # Longs. go.Scatter( x=longs['time'], y=longs['price'], mode='markers', name="Long", marker_color="green", marker_size=10), # Shorts. go.Scatter( x=shorts['time'], y=shorts['price'], mode='markers', name="Short", marker_color="red", marker_size=10)]) title = str( timeframe + " " + self.get_name() + " " + symbol + " " + exchange.get_name()) chart.update_layout( title_text=title, title={ 'y': 0.9, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top'}, xaxis_rangeslider_visible=False, xaxis_title="Time", yaxis_title="Price (USD)", paper_bgcolor='white', plot_bgcolor='white', xaxis_showgrid=True, yaxis_showgrid=True) chart.show() return SignalEvent(symbol, entry_ts, direction, timeframe, self.name, exchange, entry_price, "Market", None, None, None, " ") else: return None