def calculate_signals(self, event): if (event.type == EventType.BAR and event.ticker == self.ticker): # Add latest adjusted closing price to the # short and long window bars self.lw_bars.append(event.adj_close_price) if self.bars > self.long_window - self.short_window: self.sw_bars.append(event.adj_close_price) # Enough bars are present for trading if self.bars > self.long_window: # Calculate the simple moving averages short_sma = np.mean(self.sw_bars) long_sma = np.mean(self.lw_bars) # Trading signals based on moving average cross if short_sma > long_sma and not self.invested: print("LONG %s: %s" % (self.ticker, event.time)) signal = SignalEvent(self.ticker, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested = True elif short_sma < long_sma and self.invested: print("SHORT %s: %s" % (self.ticker, event.time)) signal = SignalEvent(self.ticker, "SLD", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested = False self.bars += 1
def calculate_signals(self, event): if (event.type in [EventType.BAR, EventType.TICK] and event.ticker == self.ticker and self._end_of_month_trading_calendar(event.time)): ticker = event.ticker if self.invested: liquidate_signal = SignalEvent(ticker, "EXIT") self.events_queue.put(liquidate_signal) long_signal = SignalEvent(ticker, "BOT") self.events_queue.put(long_signal) self.invested = True
def calculate_signals(self, event): """ For a particular received BarEvent, determine whether it is the end of the month (for that bar)/ quarter / year and generate a liquidation signal, as well as a purchase signal, for each ticker. """ if (event.type in [EventType.BAR, EventType.TICK] and self._end_of_quarter(event.time)): ticker = event.ticker if self.tickers_invested[ticker]: liquidate_signal = SignalEvent(ticker, "EXIT") self.events_queue.put(liquidate_signal) long_signal = SignalEvent(ticker, "BOT") self.events_queue.put(long_signal) self.tickers_invested[ticker] = True
def calculate_signals(self, event): if (event.type == EventType.BAR and event.ticker == self.ticker): # print("what type of price is in the event", event.adj_close_price, type(event.adj_close_price)) # print("Our dataframe looks like this ", self.prices_df) self.prices_df = self.prices_df.append( {event.ticker: event.adj_close_price}, ignore_index=True) # self.prices_df[self.bars] = event.adj_close_price if self.bars == 0: print(self.prices_df) # if we have enough bars for the third window if self.bars > self.third_window + 1: if self.bars % self.trade_freq == 0: # print(self.prices_df.tail(5)) # calculate the 1 month, 3 month, 6 month returns # current_price = self.prices_df.iloc[-1][ticker] current_price = self.prices_df.iloc[-1] one_month = (current_price - self.prices_df.iloc[-1 - self.first_window] ) / current_price three_month = (current_price - self.prices_df.iloc[-1 - self.second_window] ) / current_price six_month = (current_price - self.prices_df.iloc[-1 - self.third_window] ) / current_price accelerating_momo = np.mean( [one_month, three_month, six_month]) if accelerating_momo > 0 and not self.invested: print("LONG %s: %s " % (self.ticker, event.time)) signal = SignalEvent( self.ticker, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested = True elif accelerating_momo < 0 and self.invested: print("SELLING %s: %s" % (self.ticker, event.time)) signal = SignalEvent( self.ticker, "SLD", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested = False self.bars += 1
def calculate_signals(self, event): if (event.type in [EventType.BAR, EventType.TICK] and event.ticker == self.ticker): if not self.invested and self.bars == 0: signal = SignalEvent(self.ticker, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested = True self.bars += 1
def calculate_signals(self, event): if (event.type == EventType.BAR and event.ticker in self.tickers): # print("what type of price is in the event", event.adj_close_price, type(event.adj_close_price)) # print("Our dataframe looks like this ", self.prices_df) self.prices_df = self.prices_df.append( {event.ticker: event.adj_close_price}, ignore_index=True) # self.prices_df[self.bars] = event.adj_close_price if self.bars == 0: print(self.prices_df) print("printeing the invested dictionary") for key, value in self.invested.items(): print(key, value) # if we have enough bars for the third window if self.bars > self.third_window + 1: # We only interested in monthly trading if self.bars % self.trade_freq == 0: # print(self.prices_df.tail(5)) # calculate the 1 month, 3 month, 6 month returns # current_price = self.prices_df.iloc[-1][ticker] returns_dict = {} for ticker in tickers: # now we don't want to calculate returns for the risk free asset if ticker not in [self.risk_free]: current_price = self.prices_df[ticker].iloc[-1] one_month = ( current_price - self.prices_df[ticker].iloc[ -1 - self.first_window]) / current_price three_month = ( current_price - self.prices_df[ticker].iloc[ -1 - self.second_window]) / current_price six_month = ( current_price - self.prices_df[ticker].iloc[ -1 - self.third_window]) / current_price returns_dict[ticker] = np.mean( [one_month, three_month, six_month]) # logic now: buy the asset with the max momo score when we are not invested best_perfomer = max(returns_dict, key=returns_dict.get) # print(best_perfomer) if returns_dict[best_perfomer] > 0 and not self.invested[ best_perfomer]: for investment in getKeysByValue(self.invested, True): # sell everything that we own print("SELLING %s: %s" % (investment, event.time)) signal = SignalEvent( investment, "SLD", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested[investment] = False print("LONG %s: %s " % (best_perfomer, event.time)) signal = SignalEvent( best_perfomer, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested[best_perfomer] = True # Othrewise buy bonds if we dont own them already else: if self.invested[self.risk_free] == False: for investment in getKeysByValue( self.invested, True): # sell everything that we own print("SELLING %s: %s" % (investment, event.time)) signal = SignalEvent( investment, "SLD", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested[investment] = False print("LONG %s: %s " % (self.risk_free, event.time)) signal = SignalEvent( self.risk_free, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(signal) self.invested[self.risk_free] = True self.bars += 1
def calculate_signals(self, event): if (event.type in [EventType.BAR, EventType.TICK] and event.ticker in self.tickers # and self._end_of_month_trading_calendar(event.time) ): self.bars += 1 self._set_correct_time_and_price(event) # IF IT IS THE INDEX, THEN WE ONLY USE TO CALCULATE THE 200DAY MOVING AVERAGE if event.ticker == self.index_ticker: self.index_prices.append(event.adj_close_price) if len(self.index_prices) == self.index_dma_window: # close = self.index_prices[-1] # are_we_above = self.index_prices[-1] > np.mean(self.index_prices) self.index_dma = self.index_prices[-1] > np.mean( self.index_prices) # ticker = event.ticker # add closing prices to prices queue self.ticker_bars[event.ticker].append(event.adj_close_price) self.ticker_bars_unadj[event.ticker].append(event.close_price) # add todays prices prices and yesterdays prices # first we move the old price # self.high_lows[event.ticker]['yes_high'] = self.high_lows[event.ticker]['today_high'] # self.high_lows[event.ticker]['yes_close'] = self.high_lows[event.ticker]['today_low'] # today_high = event.high_price # today_high = self.high_lows[event.ticker]['today_high'] = int( event.high_price * event.adj_close_price / event.close_price) self.high_lows[event.ticker]['today_low'] = int( event.low_price * event.adj_close_price / event.close_price) todays_high = self.high_lows[event.ticker]['today_high'] todays_low = self.high_lows[event.ticker]['today_low'] if len(self.ticker_bars_unadj[event.ticker]) > 1: yesterdays_close = self.ticker_bars[event.ticker][-2] true_range = np.max([todays_high, yesterdays_close]) - np.min( [todays_low, yesterdays_close]) self.true_range[event.ticker].append(true_range) if len(self.true_range[event.ticker]) >= 20: queue_of_tr = pd.Series(self.true_range[event.ticker]) atr_series = queue_of_tr.ewm( span=20, min_periods=self.atr_period).mean() self.atr[event.ticker] = atr_series # can only trade if all tickers have more than 90 days enough_days = True valid_tickers_for_day = self.valid_tickers(self.time) # todo here is where we check the burn in. Logic needs changing otherwise count_incomplete_tickers = 0 for ticker in valid_tickers_for_day: if len(self.ticker_bars[ticker]) < self.window or len( self.ticker_bars[ticker]) < self.sma_days_for_stocks: count_incomplete_tickers += 1 enough_days = False # if not enough_days: # break print("we do not have full window data and sma days for: ", count_incomplete_tickers, "tickers") if enough_days: number_of_stocks_prices_seen = np.sum( self.latest_prices > -1.0) # todo threshold only needs to be calculated once per day # todo the entire valid tickers could be calculated outside the strategy # todo it could be calculated in run and therefore speed it all up. threshold = self.number_of_valid_ticks_on_day(self.time) if enough_days and event.time.weekday( ) == 2 and number_of_stocks_prices_seen >= threshold: """calculate momentums""" # momentums = pd.DataFrame(self.tickers) momenta = {} for ticker in valid_tickers_for_day: # closing_prices = list(self.ticker_bars[ticker]) closing_prices = list( itertools.islice( self.ticker_bars[ticker], self.sma_days_for_stocks - self.window, self.sma_days_for_stocks)) momenta[ticker] = self.expo_momentum(closing_prices) # momenta_df = pd.DataFrame(list(momenta.items), columns=['Asset', 'Momentum']) # momenta_df = momenta_df.sort_values(by = 'Momentum') # remove the index ticker from the table as we won't buy that momenta.pop(self.index_ticker, None) # interested in top fifth best performing assets n = int((len(valid_tickers_for_day) - 1) / 5) top_n = { key: momenta[key] for key in sorted(momenta, key=momenta.get, reverse=True) [:n] } top_assets = list(top_n.keys()) """ Do any stocks we own need to be sold? """ for stock in self.tickers_invested: if self.tickers_invested[stock]: """ check if we need to sell this """ """ if stock not in top assets ---> SELL if stock is below 100DMA --> SELL if gap over 15% --> SELL we need to update the tables every wednesday. Either we keep the table as part of a class. Or for every tick coming in we calculate and then trade. """ if stock not in top_assets: liquidate_signal = SignalEvent(stock, "EXIT") self.events_queue.put(liquidate_signal) self.tickers_invested[stock] = False elif self.below_100_dma(self.ticker_bars[stock][-1], stock): liquidate_signal = SignalEvent(stock, "EXIT") self.events_queue.put(liquidate_signal) self.tickers_invested[stock] = False elif self.move_greater_than_15(stock): liquidate_signal = SignalEvent(stock, "EXIT") self.events_queue.put(liquidate_signal) self.tickers_invested[stock] = False """ can we buy any stocks only if the index is above the 200DMA and if the stock is above 100DMA and no move larger than 15% go through the top momentum list. if we do not own buy until we run out of cash """ if self.index_dma: for ticker in top_assets: if not self.below_100_dma(self.ticker_bars[ticker][-1], ticker) \ and not self.move_greater_than_15(ticker) \ and not self.tickers_invested[ticker]: size = int(self.atr[ticker].iloc[-1]) long_signal = SignalEvent(ticker, "BOT", size) self.events_queue.put(long_signal) self.tickers_invested[ticker] = True """ rebalance if its a second wednesday what is the target size and what is the currents size of the position. if the difference is too much rebalance go through all the assets with booleans. And then place orders to buy. The position sizer will see its a rebalance then """ if self.is_second_wed(event.time): for stock in self.tickers_invested: if self.tickers_invested[stock]: size = int(self.atr[stock].iloc[-1]) long_signal = SignalEvent(stock, "BOT", size) self.events_queue.put(long_signal)
def calculate_signals(self, event): if (event.type in [EventType.BAR, EventType.TICK] and event.ticker in self.tickers): no_invested = 0 for key in self.tickers_invested: if self.tickers_invested[key]: no_invested += 1 if no_invested > 1: print("**************") print("INVESTED IN", no_invested, "ASSETS") print("**************") elif no_invested == 0 and self.bars > self.third_window: print("**************") print("EMPTY PORTFOLIO") print("**************") # if self.tickers_invested # append the price to the momo queue this might be WRONG!!! self.ticker_bars[event.ticker].append(event.adj_close_price) # this assumes an equal amount of bars in each input # if self.bars > (len(self.tickers) * self.third_window) + 1: can_trade = True for ticker in self.ticker_bars: if len(self.ticker_bars[ticker]) < self.third_window: can_trade = False # now we have six months of prices in our bars # we create a dictionary with the mean returns over lookback periods # if can_trade: rank_assets = {} # risky_assets = for ticker in self.tickers: if ticker != self.safe_asset: current_price = self.ticker_bars[ticker][-1] one_month = (current_price - self.ticker_bars[ticker][ -1 - self.first_window]) / current_price three__month = (current_price - self.ticker_bars[ ticker][-1 - self.second_window]) / current_price six_month = (current_price - self.ticker_bars[ticker][ -1 - self.third_window + 1]) / current_price accel_momo = np.mean( [one_month, three__month, six_month]) rank_assets[ticker] = accel_momo # NOW WE KNOW WHICH ASSET TO BUY DO WE BUY IT ON THE NEXT DAY?? # action at end of the month if self._end_of_month(event.time): if self.asset_to_invest_in[ 0] is None or self.asset_to_invest_in[ 0].month != event.time.month: asset_to_trade = self.which_asset_to_invest( rank_assets) print(asset_to_trade, "IS THE ASSET TO OWN", event.time) self.asset_to_invest_in = (event.time, asset_to_trade) ticker = event.ticker # and we are not invested if ticker == self.asset_to_invest_in[ 1] and not self.tickers_invested[ticker]: print("LONG %s: %s" % (ticker, event.time)) long_signal = SignalEvent( ticker, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(long_signal) self.tickers_invested[ticker] = True elif ticker != self.asset_to_invest_in[ 1] and self.tickers_invested[ticker]: print("EXIT %s: %s" % (ticker, event.time)) liquidate_signal = SignalEvent(ticker, "EXIT") self.events_queue.put(liquidate_signal) self.tickers_invested[ticker] = False # else if there is an asset we should be in. elif self.asset_to_invest_in[1] is not None: for key in self.tickers_invested: if self.tickers_invested[ key] and key != self.asset_to_invest_in[ 1] and key == event.ticker: print("We should not be invested EXITING", key, "NOT equal to", self.asset_to_invest_in[1]) print("EXIT %s: %s" % (event.ticker, event.time)) liquidate_signal = SignalEvent(event.ticker, "EXIT") self.events_queue.put(liquidate_signal) self.tickers_invested[event.ticker] = False elif not self.tickers_invested[ key] and key == self.asset_to_invest_in[ 1] and key == event.ticker: print("LONG %s: %s" % (ticker, event.time)) long_signal = SignalEvent( ticker, "BOT", suggested_quantity=self.base_quantity) self.events_queue.put(long_signal) self.tickers_invested[ticker] = True self.bars += 1 """