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) # Get RSI indicator rsi_indicator = get_RSI(prices, window) # 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, rsi_indicator], 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 addEvidence(self, symbol="AAPL", sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31), sv=100000): syms = [symbol] dates = pd.date_range(sd, ed) total_prices = ut.get_data(syms, dates) prices = total_prices[syms] psr = get_Price_SMA_Ratio(symbols=syms,dates=dates,lookback=14) rsi = get_RSI(symbols=syms,dates=dates,lookback=14) mfi = get_MFI(symbols=syms,dates=dates,lookback=14) spsr = psr.ix[:,symbol] srsi = rsi.ix[:,symbol] smfi = mfi.ix[:,symbol] dpsr=self.Discretization(spsr,steps=5) drsi=self.Discretization(srsi,steps=5) dmfi=self.Discretization(smfi,steps=5) prices = prices.ix[:,symbol] dr = prices.copy() dr[0] = np.nan dr[1:] = (prices[1:] / prices[:-1].values) - 1 States = dpsr * 100 + drsi + dmfi States = States.ix[:,'discretized_value'] self.learner = ql.QLearner(num_states=1000, num_actions=3) oldprofit = 0 for iteration in range(100): current_holding = 0 total_profit = 0 rewards = 0 for i in range(dr.shape[0] - 1): if (i > 0): total_profit += prices[i - 1] * current_holding * dr[i] state = States[i] if i == 0: action = self.learner.querysetstate(state) else: action = self.learner.query(state, rewards) holding, rewards = self.trade_actions(current_holding, action, dr[i + 1]) current_holding = holding total_profit += prices[-2] * current_holding * dr[-1] if total_profit == oldprofit: break oldprofit = total_profit
def testPolicy(self,symbol,sd,ed,sv): symbols = [] symbols.append(symbol) dates = pd.date_range(sd, ed) price = get_data(symbols, dates) orders = [] holdings = {sym: 0 for sym in symbols} lookback = 14 psr = get_Price_SMA_Ratio(symbols,dates,lookback=14) rsi = get_RSI(symbols,dates,lookback=14) mfi = get_MFI(symbols,dates) for day in range(price.shape[0]): for sym in symbols: if (psr.ix[day, sym] < 1.05) and (rsi.ix[day, sym] < 15) and (mfi.ix[day, sym] < 10): if holdings[sym] < 1000: holdings[sym] = holdings[sym] + 1000 orders.append([price.index[day].date(), sym, 'BUY', 1000]) else: orders.append([price.index[day].date(), sym, 'NOTHING', 0]) elif (psr.ix[day, sym] > 0.95) and (rsi.ix[day, sym] > 55) and (mfi.ix[day, sym] > 40): if holdings[sym] > -1000: holdings[sym] = holdings[sym] - 1000 orders.append([price.index[day].date(), sym, 'SELL', 1000]) else: orders.append([price.index[day].date(), sym, 'NOTHING', 0]) elif (psr.ix[day, sym] < 1) and (psr.ix[day-1,sym] > 1) and (holdings[sym] < 0): holdings[sym] = holdings[sym] + 1000 orders.append([price.index[day].date(), sym, 'BUY', 1000]) elif (psr.ix[day, sym] > 1) and (psr.ix[day-1,sym] < 1) and (holdings[sym] > 0): holdings[sym] = holdings[sym] - 1000 orders.append([price.index[day].date(), sym, 'SELL', 1000]) else: orders.append([price.index[day].date(), sym, 'NOTHING', 0]) df_trades = pd.DataFrame(orders, columns=["Date", "Symbol", "Order", "Shares"]) df_trades.set_index('Date', inplace=True) return df_trades
def testPolicy(self, symbol="AAPL", sd=dt.datetime(2010,1,1), ed=dt.datetime(2011,12,31), sv=100000): dates = pd.date_range(sd, ed) total_prices = ut.get_data([symbol], dates) syms = [symbol] prices = total_prices[syms] psr = get_Price_SMA_Ratio(symbols=syms, dates=dates, lookback=14) rsi = get_RSI(symbols=syms, dates=dates, lookback=14) mfi = get_MFI(symbols=syms, dates=dates, lookback=14) spsr = psr.ix[:, symbol] srsi = rsi.ix[:, symbol] smfi = mfi.ix[:, symbol] dpsr = self.Discretization(spsr, steps=5) drsi = self.Discretization(srsi, steps=5) dmfi = self.Discretization(smfi, steps=5) States = dpsr * 100 + drsi + dmfi States = States.ix[:, 'discretized_value'] prices = prices.ix[:, symbol] dr = prices.copy() trades = prices.copy() trades[:] = 0 dr[0] = 0 dr[1:] = (prices[1:] / prices[:-1].values) - 1 current_holding = 0 total_profit = 0 for i in range(len(dr)- 1): if (i > 0): total_profit += prices[i - 1] * current_holding * dr[i] state = States[i] action = self.learner.querysetstate(state) holding, rewards = self.trade_actions(current_holding, action, dr[i + 1]) trades[i] = (holding - current_holding) current_holding = holding total_profit += prices[-2] * current_holding * dr[-1] trades = pd.DataFrame(trades, columns=[symbol]) return trades
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
def showvalues(): # Specify the start and end dates for this period. start_d = dt.date(2008, 1, 1) #end_d = dt.datetime(2018, 10, 30) yesterday = dt.date.today() - dt.timedelta(1) # Get portfolio values from Yahoo symbol = request.form['symbol'] portf_value = fetchOnlineData(start_d, yesterday, symbol) # ****Stock prices chart**** plot_prices = plot_stock_prices(portf_value.index, portf_value['Adj Close'], symbol) # ****Momentum chart**** # Normalize the prices Dataframe normed = pd.DataFrame() normed['Adj Close'] = portf_value['Adj Close'].values / portf_value[ 'Adj Close'].iloc[0] # Compute momentum sym_mom = get_momentum(normed['Adj Close'], window=10) # Create momentum chart plot_mom = plot_momentum(portf_value.index, normed['Adj Close'], sym_mom, "Momentum Indicator", (12, 8)) # ****Bollinger Bands**** # Compute rolling mean rm_JPM = get_rolling_mean(portf_value['Adj Close'], window=10) # Compute rolling standard deviation rstd_JPM = get_rolling_std(portf_value['Adj Close'], window=10) # Compute upper and lower bands upper_band, lower_band = get_bollinger_bands(rm_JPM, rstd_JPM) # Plot raw symbol values, rolling mean and Bollinger Bands dates = pd.date_range(start_d, yesterday) plot_boll = plot_bollinger(dates, portf_value.index, portf_value['Adj Close'], symbol, upper_band, lower_band, rm_JPM, num_std=1, title="Bollinger Indicator", fig_size=(12, 6)) # ****Simple moving average (SMA)**** # Compute SMA sma_JPM, q = get_sma(normed['Adj Close'], window=10) # Plot symbol values, SMA and SMA quality plot_sma = plot_sma_indicator(dates, portf_value.index, normed['Adj Close'], symbol, sma_JPM, q, "Simple Moving Average (SMA)") # ****Relative Strength Index (RSI)**** # Compute RSI rsi_value = get_RSI(portf_value['Adj Close']) # Plot RSI plot_rsi = plot_rsi_indicator(dates, portf_value.index, portf_value['Adj Close'], symbol, rsi_value, window=14, title="RSI Indicator", fig_size=(12, 6)) # Session variables session['start_val'] = request.form['start_val'] session['symbol'] = request.form['symbol'] session['start_d'] = start_d.strftime('%Y/%m/%d') session['num_shares'] = request.form['num_shares'] session['commission'] = request.form['commission'] session['impact'] = request.form['impact'] return render_template( # name of template "stockpriceschart.html", # now we pass in our variables into the template start_val=request.form['start_val'], symbol=request.form['symbol'], commission=request.form['commission'], impact=request.form['impact'], num_shares=request.form['num_shares'], start_date=start_d, end_date=yesterday, tables=[portf_value.to_html(classes=symbol)], titles=['na', 'Stock Prices '], div_placeholder_stock_prices=Markup(plot_prices), div_placeholder_momentum=Markup(plot_mom), div_placeholder_bollinger=Markup(plot_boll), div_placeholder_sma=Markup(plot_sma), div_placeholder_rsi=Markup(plot_rsi))