def get_features(self, prices): """ Compute the technical features of a position and feed that into the Q-Learning process TODO: Try different parameters to see if you can improve the portfolio Try out different window sizes (right now set to 10 trading days) prices: Adjusted close prices of the given symbol df_features: A pandas dataframe of the technical indicators """ rolling_mean = prices.rolling(window=self.window_size).mean() rolling_std = prices.rolling(window=self.window_size).std() momentum = get_momentum(prices, self.window_size) sma_indicator = get_sma_indicator(prices, rolling_mean) bollinger_val = compute_bollinger_value(prices, rolling_mean, rolling_std) df_features = pd.concat([momentum, sma_indicator], axis=1) df_features = pd.concat([df_features, bollinger_val], axis=1) df_features.columns = ["ind{}".format(i) for i in range(len(df_features.columns))] # Perhaps you can come up with a different feature? # Try it! df_features.dropna(inplace=True) return df_features
def get_features(self, prices): """Compute technical indicators and use them as features to be fed into a Q-learner. Parameters: prices: Adjusted close prices of the given symbol Returns: df_features: A pandas dataframe of the technical indicators """ window = 10 # Compute rolling mean rolling_mean = prices.rolling(window=window).mean() # Compute_rolling_std rolling_std = prices.rolling(window=window).std() # Compute momentum momentum = get_momentum(prices, window) # Compute SMA indicator sma_indicator = get_sma_indicator(prices, rolling_mean) # Compute Bollinger value bollinger_val = compute_bollinger_value(prices, rolling_mean, rolling_std) # Create a dataframe with three features df_features = pd.concat([momentum, sma_indicator], axis=1) df_features = pd.concat([df_features, bollinger_val], axis=1) df_features.columns = ["ind{}".format(i) for i in range(len(df_features.columns))] df_features.dropna(inplace=True) return df_features
def trading_strategy(self, sym_price): """Create a dataframe of order signals that maximizes portfolio's return. This function has been optimized for the symbol and training period in the main function Parameters: sym_price: The price series of a stock symbol of interest Returns: df_order_signals: A series that contains 1 for buy, 0 for hold and -1 for sell """ # Get momentum indicator and generate signals momentum = get_momentum(sym_price, 40) mom_signal = -1 * (momentum < -0.07) + 1 * (momentum > 0.14) # Get RSI indicator and generate signals rsi_indicator = get_RSI(sym_price) rsi_signal = 1 * (rsi_indicator < 50) + -1 * (rsi_indicator > 50) # Get SMA indicator and generate signals sma_indicator = get_sma_indicator(sym_price, sym_price.rolling(window=30).mean()) sma_signal = 1 * (sma_indicator < 0.0) + -1 * (sma_indicator > 0.0) # Combine individual signals signal = 1 * ((sma_signal == 1) & (rsi_signal == 1) & (mom_signal == 1)) \ + -1 * ((sma_signal == -1) & (rsi_signal == -1) & (mom_signal == -1)) # 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) and (signal.loc[date] == 1): self.df_order_signals.loc[date] = 1 # If net_signals is not short and signal is to sell elif (net_signals > -1) and (signal.loc[date] == -1): self.df_order_signals.loc[date] = -1 # On the last day, close any open positions if self.df_order_signals.sum() == -1: self.df_order_signals[-1] = 1 elif self.df_order_signals.sum() == 1: self.df_order_signals[-1] = -1 return self.df_order_signals
def get_features1(self, prices, symbol, print=False): ''' Compute technical indicators and use them as features to be fed into a Q-learner. :param: prices: Adj Close prices dataframe :param: Whether adding data for printing to dataframe or not :return: Normalize Features dataframe ''' # Fill NAN values if any prices.fillna(method="ffill", inplace=True) prices.fillna(method="bfill", inplace=True) prices.fillna(1.0, inplace=True) # Price adj_close = prices[symbol] # Compute Momentum mom = get_momentum(adj_close, window=10) # Compute RSI rsi = get_RSI(adj_close) # Compute rolling mean rm = get_rolling_mean(adj_close, window=10) # Compute rolling standard deviation rstd = get_rolling_std(adj_close, window=10) # Compute upper and lower bands upper_band, lower_band = get_bollinger_bands(rm, rstd) # Compute SMA sma = get_sma_indicator(adj_close, rm) df = prices.copy() df['Momentum'] = mom df['Adj. Close/SMA'] = adj_close/sma df['middle_band'] = rm # Delete 'Adj Close' column del df[symbol] if set(['cash']).issubset(df.columns): del df['cash'] # Normalize dataframe df_norm = normalize_data(df) # Add Adj Close, Bollinrt Bands and RSY if printing if print: df_norm['Adj Close'] = prices[symbol] df_norm['upper_band'] = upper_band df_norm['lower_band'] = lower_band df_norm['middle_band'] = rm df_norm['RSI'] = rsi # Drop NaN df_norm.dropna(inplace=True) return df_norm