def test_policy(symbol='AAPL', sd=dt.datetime(2010, 1, 1), ed=dt.datetime(2012, 12, 31), st=100000, shares_contraint=1000, look_back_period=14): df_trades = create_trades_df(start_date=sd, end_date=ed) df_trades.set_index('Date', inplace=True) df_trades['Symbol'] = symbol df_trades['Order'] = 'NOTHING' df_prices_sym = get_data([symbol], pd.date_range(sd, ed), False) df_prices_idx = get_data(['SPY'], pd.date_range(sd, ed), False, dropNonTradingSPY=False) df_price_filter_sym = df_prices_sym.dropna(subset=[symbol]) df_price_filter_idx = df_prices_idx.dropna(subset=['SPY']) iterator = more_itertools.peekable(df_price_filter_sym.iloc[look_back_period:].iterrows()) ltd_shares = 0.0 prev_sym_price_over_sma = indicator.get_price_over_sma(df_price_filter_sym.iloc[:look_back_period]) for index, row in iterator: # get current price to determine when we should close the position. df_prices_historical_sym = df_price_filter_sym.loc[:index][-look_back_period:] # Todo: Can we do this in one shot? df_prices_historical_idx = df_price_filter_idx.loc[:index][-look_back_period:] sym_price_over_sma = indicator.get_price_over_sma(df_prices_historical_sym) sym_bollinger_band_percent = indicator.get_bollinger_band_percent(df_prices_historical_sym) sym_rsi = indicator.get_rsi(df_prices_historical_sym, look_back_period) idx_price_over_sma = indicator.get_price_over_sma(df_prices_historical_idx) idx_bollinger_band_percent = indicator.get_bollinger_band_percent(df_prices_historical_idx) idx_rsi = indicator.get_rsi(df_prices_historical_idx, look_back_period) signal = get_signal(sym_price_over_sma, sym_bollinger_band_percent, sym_rsi, idx_price_over_sma, idx_bollinger_band_percent, idx_rsi, prev_sym_price_over_sma) print(signal) process_signal(df_trades, index, signal, ltd_shares, shares_contraint) ltd_shares = update_life_to_date_shares(ltd_shares, df_trades, index, shares_contraint) prev_sym_price_over_sma = sym_price_over_sma return df_trades.reset_index()
def get_signal(self, price, ohlc, window=20, ga_train=False): symbol = price.dtypes.index[0] # Find Candlestick patterns and generate signals patterns_signal = pd.DataFrame(0, index=price.index, columns=[symbol]) found_patterns = cdsd.pattern_signals(ohlc, ['Abandoned Baby', 'Morning Star', 'Evening Star', 'Harami Cross']) for pattern in found_patterns: patterns_signal.loc[pattern[0]] = pattern[1] # Find trendlines and iterlines points and generate signals trends, points_signal = ind.get_trendlines(price, charts=False) #Get SMA and generate signals sma = ind.get_price_sma(price, window=30) sma_signal = 1 * (sma < 0.0) + -1 * (sma > 0.0) #Get RSI and generate signals rsi = ind.get_rsi(price, window=14) rsi_signal = 1 * (rsi < 30.0) + -1 * (rsi > 70.0) #Get MACD and generate signals macd, macdsign, macddiff = ind.get_macd(price, fast_window=12, slow_window=26) macd_signal = 1 * (macd>macdsign) + -1 * (macd<macdsign) #Get Bollinger Bands and generate signals bb_values = ind.get_bollinger_band_values(price, window=30) bb_signal = 1 * (bb_values < -1) + -1 * (bb_values > 1) pdb.set_trace()
def get_df_with_indicators_single_currency(self, currency_dir): logger.log_info( "Calculating technical indicators for data from {}.".format( currency_dir)) df_result = self.get_tf_resampled_single_currency_raw_data_with_base( currency_dir) for period in config.MA_PERIODS: df_result = indicators.get_ma(df_result, "close", period) for period in config.RSI_PERIODS: df_result = indicators.get_rsi(df_result, "close", period) return df_result
def buildIndicators(self, df_prices, symbol="IBM"): """ Build (panda Series) indicators from the prices dataframe @params df_prices: the prices dataframe @params symbol: the asset's symbol 5,10,20,30 """ # rolling bollinger band self.bband = idc.get_bbands(pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]), self.window_size, symbol=symbol).dropna() # fixing treshold for consistencies before normalization self.bband[self.bband < -1] = -1 self.bband[self.bband > 1] = 1 self.discretize_bband = self.normalizeIndicators(self.bband) # rolling momentum abs self.momentum = idc.get_momentum(pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]), self.window_size, symbol=symbol).dropna() self.momentum[self.momentum < -0.3] = -0.3 self.momentum[self.momentum > 0.3] = 0.3 self.discretize_momentum = self.normalizeIndicators(self.momentum) # rolling standard deviation self.rstd = pd.Series(pd.rolling_std(df_prices, window=2), name='rstd').dropna() self.rstd[self.rstd < 0.5] = 0.5 self.rstd[self.rstd > 4] = 4 self.discretize_rstd = self.normalizeIndicators(self.rstd) # rolling rsi self.rsi = idc.get_rsi(df_prices, self.window_size).dropna() self.rsi[self.rsi < 40] = 40 self.rsi[self.rsi > 70] = 70 self.discretize_rsi = self.normalizeIndicators(self.rsi) self.discretize_holding = {0: 0, -1000: 1, 1000: 2} self.n_states = int(3 * 10**4)
def trade_strategy(self, price, ohlc, ga_train=False): """ Create a dataframe of order signals that maximizes portfolio return Signals: buy = 1 hold = 0 sell = -1 """ symbol = price.dtypes.index[0] # Find Candlestick patterns and generate signals patterns_signal = pd.DataFrame(0, index=price.index, columns=[symbol]) found_patterns = cdsd.pattern_signals(ohlc, ['Abandoned Baby', 'Morning Star', 'Evening Star', 'Harami Cross']) for pattern in found_patterns: patterns_signal.loc[pattern[0]] = pattern[1] # Find trendlines and iterlines points and generate signals trends, points_signal = ind.get_trendlines(price, charts=False) #Get SMA and generate signals sma = ind.get_price_sma(price, window=30) sma_signal = 1 * (sma < 0.0) + -1 * (sma > 0.0) #Get RSI and generate signals rsi = ind.get_rsi(price, window=14) rsi_signal = 1 * (rsi < 30.0) + -1 * (rsi > 70.0) #Get MACD and generate signals macd, macdsign, macddiff = ind.get_macd(price, fast_window=12, slow_window=26) macd_signal = 1 * (macd>macdsign) + -1 * (macd<macdsign) #Get Bollinger Bands and generate signals bb_values = ind.get_bollinger_band_values(price, window=30) bb_signal = 1 * (bb_values < -1) + -1 * (bb_values > 1) #pdb.set_trace() #Combine signals if type(ga_train)==bool: signal = 1 * ( ((patterns_signal==1)*0.2 + (macd_signal==1)*0.2 + (sma_signal==1)*0.2 + (rsi_signal==1)*0.2 + (bb_signal==1)*0.2) + (points_signal==1)*0.4 >= 0.8) + -1 * ( ((patterns_signal==-1)*0.2 + (macd_signal==-1)*0.2 + (sma_signal==-1)*0.2 + (rsi_signal==-1)*0.2 + (bb_signal==-1)*0.2) + (points_signal==-1)*0.4 >= 0.8) else: signal = 1 * ( ((patterns_signal==1)*ga_train[0] + (macd_signal==1)*ga_train[1] + (sma_signal==1)*ga_train[2] + (rsi_signal==1)*ga_train[3] + (bb_signal==1)*ga_train[4]) + (points_signal==1)*ga_train[5] >= ga_train[6]) + -1 * ( ((patterns_signal==-1)*ga_train[0] + (macd_signal==-1)*ga_train[1] + (sma_signal==-1)*ga_train[2] + (rsi_signal==-1)*ga_train[3] + (bb_signal==-1)*ga_train[4]) + (points_signal==-1)*ga_train[5] >= ga_train[6]) # Create an order series with 0 as default values self.df_order_signals = signal * 0 # Keep track of net signals which are constrained to -1, 0, and 1 net_signals = 0 for date in self.df_order_signals.index: net_signals = self.df_order_signals.loc[:date].sum() # If net_signals is not long and signal is to buy if (net_signals<1).values[0] and (signal.loc[date]==1).values[0]: self.df_order_signals.loc[date]=1 # If net_signals is not short and signal is to sell elif (net_signals > -1).values[0] and (signal.loc[date]==-1).values[0]: self.df_order_signals.loc[date]=-1 if trends != None: trades = self.df_order_signals[self.df_order_signals[symbol]!=0] for i in range(len(trades)): date = trades.index[i] signal = trades.ix[i][0] #closest_trend, slope = ind.get_closest_trendline([date, price.loc[date][0]], trends, max_sep=0.3) closest_trend, slope = ind.get_closest_trendline([date, price.loc[date][0]], trends) if closest_trend != None: if closest_trend == "Resistance": #pdb.set_trace() if signal==1 and slope>0: self.df_order_signals.loc[date] = 0 elif closest_trend == "Support": if signal==-1 and slope<0: self.df_order_signals.loc[date] = 0 #pdb.set_trace() # On the last day, close any open positions if self.df_order_signals.values.sum() == -1: # Found short position self.df_order_signals.ix[-1] = 1 if self.df_order_signals.values.sum() == 1: # Found held position self.df_order_signals.ix[-1]=-1 # Alternative close positions open_pos = self.df_order_signals.values.sum() if open_pos != 0: self.df_order_signals.ix[-1] = -1 * open_pos #pdb.set_trace() return self.df_order_signals
def testPolicyMixed(n_days_bb=20, n_days_mtum=20, n_days_std=20, n_days_rsi=20, tresh_bb=1, tresh_mmtum=0.2, tresh_std_low=1, tresh_std_high=1, symbol="JPM", sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31), sv=100000): df_prices_all = get_data([symbol], pd.date_range(sd, ed)) df_prices = df_prices_all[symbol] df_trades = pd.DataFrame(data=np.zeros(len(df_prices)), index=df_prices.index, columns=['trades']) #rstd = idc.get_rolling_stdev(pd.DataFrame(df_prices, index = df_prices.index, columns = [symbol]), n_days_std) rstd = pd.rolling_std(df_prices, window=n_days_std) bband = idc.get_bbands( pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]), n_days_bb) momentum = idc.get_momentum( pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]), n_days_mtum) abs_momentum = momentum.abs() rsi = idc.get_rsi(df_prices, n_days_rsi) # use rsi to generat sell & buy signal: # > 70 : overbought : should sell # < 30 : oversold : should buy #use volatility as a filter: # if std to low, time to buy, std will increase soon, # maybe make a cross over on the rmean of std ? # if std to high, means the growth was strong but will back to the mean # use momentum to confirm sell & buy signal: # confirmed if small enough momentum # (changes in prices is slowing - time to take action) for t in range(1, len(df_prices) - 1): df_net_holdings = df_trades.cumsum(axis=0) net_holdings = df_net_holdings.values[t] if (net_holdings > 1000) | (net_holdings < -1000): print("ERROR") # buy signal if ((bband[t - 1] <= -tresh_bb) & (bband[t] > -tresh_bb)) | (rsi.iloc[t] < 30): if (abs_momentum[t] <= tresh_mmtum): if rstd[t] <= tresh_std_low: if (net_holdings == 0): df_trades.iloc[t] = 1000 elif (net_holdings == -1000): df_trades.iloc[t] = 2000 # sell signal if ((bband[t - 1] >= tresh_bb) & (bband[t] < tresh_bb)) | (rsi.iloc[t] > 70): if (abs_momentum[t] <= tresh_mmtum): if rstd[t] >= tresh_std_high: # could be remove since thresh = 0 if (net_holdings == 0): df_trades.iloc[t] = -1000 elif (net_holdings == 1000): df_trades.iloc[t] = -2000 return df_trades, rstd