def get_bollinger(symbol='JPM', sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31)): bollinger_df = market.make_df_to_match_trading_days(colnames=['Date', 'bb1', 'bb2'], symbol=symbol, sd=sd, ed=ed) SMA_df = SMA(symbol, sd=sd, ed=ed) STD_rolling = rolling_STD(symbol, sd=sd, ed=ed) bollinger_df['bb1'] = SMA_df['SMA'] + (STD_rolling['STD20'] * 2) bollinger_df['bb2'] = SMA_df['SMA'] - (STD_rolling['STD20'] * 2) return bollinger_df
def rolling_STD(symbol='JPM', sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31)): sd_left_bracket = sd - dt.timedelta(days=40) #we need to go back in time to get data for SMA. #40 days is conservative STD_df = market.make_df_to_match_trading_days(colnames=['Date', 'STD20'], symbol='JPM', sd=sd_left_bracket, ed=ed) stock_price_library = market.get_stock_prices([symbol], sd_left_bracket, ed) STD_calcs = stock_price_library.rolling(window=20, min_periods=20, center=False).std() STD_df['STD20'] = STD_calcs[symbol] return STD_df[sd:ed] #returns the 20 day rolling mean for the symbol you feed it
def stochastic_oscillator_20(symbol='JPM', sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31)): sd_left_bracket = sd - dt.timedelta(days=40) STOK_df = market.make_df_to_match_trading_days(colnames=['Date', '%K'], symbol='JPM', sd=sd_left_bracket, ed=ed) stock_price_library = market.get_stock_close_nonadjusted([symbol], sd_left_bracket, ed) low_df = market.get_stock_lows([symbol], sd_left_bracket, ed) high_df = market.get_stock_highs([symbol], sd_left_bracket, ed) STOK_df['%K'] = ((stock_price_library - low_df.rolling(window=14, center=False).min()) / (high_df.rolling(window=14, center=False).max() - low_df.rolling(window=14, center=False).min())) * 100 STOK_df['%D'] = STOK_df.rolling(window=3, center=False).mean() return STOK_df[sd:ed]
def get_daily_returns(symbol='JPM', sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31)): daily_return_df = market.make_df_to_match_trading_days( colnames=['Date', 'bb1', 'bb2'], symbol=symbol, sd=sd, ed=ed) stock_price_library = market.get_stock_prices([symbol], sd, ed) daily_returns = stock_price_library[symbol] daily_returns[1:] = ( stock_price_library[symbol].ix[1:] / stock_price_library[symbol].ix[:-1].values) - 1 # from lecture daily_returns.ix[0] = 0 daily_return_df['dr'] = daily_returns return daily_return_df
def benchmark_policy(symbol="JPM", sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31), sv=100000): orders_df = market.make_df_to_match_trading_days(colnames=['Date','Symbol', 'Order', 'Shares'], symbol='JPM', sd=sd, ed=ed) orders_df['Symbol'] = symbol #assign to JPM orders_df['Order'] = "" #initialize with no orders orders_df['Shares'] = 0.0 #initialize with no shares orders_df['Date'] = orders_df.index first_order_date = orders_df.iloc[0]['Date'] orders_df.set_value(first_order_date, 'Order', 'BUY') orders_df.set_value(first_order_date, 'Shares', 1000) #print orders_df return orders_df
def testPolicy(symbol="JPM", sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31), sv=100000): orders_df = market.make_df_to_match_trading_days(colnames=['Date','Symbol', 'Order', 'Shares'], symbol='JPM', sd=sd, ed=ed) stock_price_library = market.get_stock_prices([symbol], sd, ed) day_to_day_difference = stock_price_library.diff() day_to_day_difference = day_to_day_difference[symbol].shift(-1) #negative values mean the price will decrease tomorrow #iterate through stock price library and short before all the drops and buy for all the gains orders_df['Symbol'] = symbol #assign to JPM orders_df['Order'] = "" #initialize with no orders orders_df['Shares'] = 0.0 #initialize with no shares orders_df['Date'] = orders_df.index state = 0 for row in orders_df.itertuples(index=True): order_date = getattr(row, 'Date') symbol = getattr(row, 'Symbol') # print "The symbol is ", symbol order = getattr(row, 'Order') shares = getattr(row, 'Shares') if day_to_day_difference.loc[order_date] < 0: #this means the next day will show a decline orders_df.set_value(order_date, 'Order', 'SELL') orders_df.set_value(order_date, 'Shares', abs(-1000 - state)) state = -1000 #short state if day_to_day_difference.loc[order_date] > 0: #this means the next day will show a rise orders_df.set_value(order_date, 'Order', 'BUY') orders_df.set_value(order_date, 'Shares', abs(1000 - state)) state = 1000 #long state #my best policy (based on seeing the future) return orders_df
def testPolicy(symbol="JPM", sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31), sv=100000): orders_df = market.make_df_to_match_trading_days( colnames=['Date', 'Symbol', 'Order', 'Shares'], symbol='JPM', sd=sd, ed=ed) stock_price_library = market.get_stock_prices([symbol], sd, ed) #iterate through stock price library and short before all the drops and buy for all the gains orders_df['Symbol'] = symbol #assign to JPM orders_df['Order'] = "" #initialize with no orders orders_df['Shares'] = 0.0 #initialize with no shares orders_df['Date'] = orders_df.index state = 0 short_price = 0.0 days_in_short = 0 #load indicators bollinger_df = indicators.get_bollinger(symbol, sd=sd, ed=ed) STOK_df = indicators.stochastic_oscillator_20(symbol, sd=sd, ed=ed) SMA_df = indicators.SMA(symbol, sd=sd, ed=ed) for row in orders_df.itertuples(index=True): order_date = getattr(row, 'Date') symbol = getattr(row, 'Symbol') # print "The symbol is ", symbol order = getattr(row, 'Order') shares = getattr(row, 'Shares') bollinger_high_today = bollinger_df.loc[order_date]['bb1'] bollinger_low_today = bollinger_df.loc[order_date]['bb2'] STOK_D_today = STOK_df.loc[order_date]['%D'] stock_price_today = stock_price_library.loc[order_date][symbol] P_over_SMA_today = SMA_df.loc[order_date]['P/SMA'] total_votes = [] bb_vote = 0 bb_weight = 1 stochastic_vote = 0 stochastic_weight = 1 sma_vote = 0 sma_weight = 0.5 if stock_price_today > bollinger_high_today: bb_vote = -1 #sell! elif stock_price_today < bollinger_low_today: bb_vote = 1 #buy! if STOK_D_today < 20: stochastic_vote = 1 #buy! elif STOK_D_today > 80: stochastic_vote = -1 #get out of there! if P_over_SMA_today < 0.7: sma_vote = -1 #looks like a selling opp total_votes.append(bb_vote * bb_weight) total_votes.append(stochastic_vote * stochastic_weight) total_votes.append(sma_vote * sma_weight) average_vote = sum(total_votes) / len(total_votes) if state < 0: days_in_short += 1 if state < 0 and stock_price_today > 1.2 * short_price or days_in_short > 45: #if the price has risen 20% above our short price #or if we have been in a short position for more than 45 #get out of our position and wait for next move. orders_df.set_value(order_date, 'Order', 'BUY') orders_df.set_value(order_date, 'Shares', abs(0 - state)) state = 0 #reset days_in_short = 0 else: if average_vote < 0: #this means I want to sell if abs(-1000 - state) == 0: #legality check for sale transaction pass else: orders_df.set_value(order_date, 'Order', 'SELL') orders_df.set_value(order_date, 'Shares', abs(-1000 - state)) short_price = stock_price_today state = -1000 #short state if average_vote > 0: #this means I want to buy if abs(1000 - state) == 0: #legality check for buy transaction pass else: orders_df.set_value(order_date, 'Order', 'BUY') orders_df.set_value(order_date, 'Shares', abs(1000 - state)) state = 1000 #long state days_in_short = 0 else: pass #my best policy (based on seeing the future) return orders_df
def plot_code( sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31), impact=0.0): # orders_df = bps.testPolicy(sd=start_date, ed=end_date) plt.figure() # I'm going to try to cheat orders_df = ms.testPolicy(sd=sd, ed=ed, sv=100000) benchmark_policy = ind.benchmark_policy(sd=sd, ed=ed, sv=100000) #get strat learner orders strat_learner = sl.StrategyLearner(verbose=False, impact=impact) strat_learner.addEvidence(symbol="JPM", sd=sd, ed=ed, sv=100000) strat_orders_df = strat_learner.testPolicy(sd=sd, ed=ed, sv=100000) strat_orders_df = strat_learner.get_classic_policy_for_testing() benchmark_policy.to_csv('benchmark.csv') orders_df.to_csv('orders.csv') strat_orders_df.to_csv('strat_orders.csv') # portvals_raw = compute_portvals_abridged(orders_df, commission=0, impact=0) portvals_raw = market.compute_portvals_abridged(orders_df, commission=0, impact=impact) benchmark_portvals_raw = market.compute_portvals_abridged(benchmark_policy, commission=0, impact=impact) strat_portvals_raw = market.compute_portvals_abridged(strat_orders_df, commission=0, impact=impact) # clean up portvals = market.extract_portvals_only(portvals_raw) benchmark_portvals = market.extract_portvals_only(benchmark_portvals_raw) strat_portvals = market.extract_portvals_only(strat_portvals_raw) cum_ret, avg_daily_ret, std_daily_ret, sharpe_ratio = market.compute_portval_stats( portvals, rfr=0.0, sf=252, sv=100000) bench_cum_ret, bench_avg_daily_ret, bench_std_daily_ret, bench_sharpe_ratio = market.compute_portval_stats( benchmark_portvals, rfr=0.0, sf=252, sv=100000) learn_cum_ret, learn_avg_daily_ret, learn_std_daily_ret, learn_sharpe_ratio = market.compute_portval_stats( strat_portvals, rfr=0.0, sf=252, sv=100000) # # Get SPY data # symbols = ['SPY'] # allocations = [1] # start_val = 1000000 # risk_free_rate = 0.0 # sample_freq = 252 # # # Assess the portfolio of SPY # cum_ret_SPY, avg_daily_ret_SPY, std_daily_ret_SPY, sharpe_ratio_SPY, ev = market.assess_portfolio(sd=sd, # ed=ed, # syms=symbols, # allocs=allocations, # sv=100000, # gen_plot=False) # Compare portfolio against $SPX print "Impact is {}".format(impact) print "Date Range: {} to {}".format(sd, ed) print print "Sharpe Ratio of Manual Strategy: {}".format(sharpe_ratio) print "Sharpe Ratio of Benchmark: {}".format(bench_sharpe_ratio) print "Sharpe Ratio of Strategy Learner: {}".format(learn_sharpe_ratio) print print "Cumulative Return of Manual Strategy: {}".format(cum_ret) print "Cumulative Return of Benchmark: {}".format(bench_cum_ret) print "Cumulative Return of Strategy Learner : {}".format(learn_cum_ret) print print "Standard Deviation of Manual Strategy: {}".format(std_daily_ret) print "Standard Deviation of Benchmark: {}".format(bench_std_daily_ret) print "Standard Deviation of Strategy Learner : {}".format( learn_std_daily_ret) print print "Average Daily Return of Manual Strategy: {}".format(avg_daily_ret) print "Average Daily Return of Benchmark: {}".format(bench_avg_daily_ret) print "Average Daily Return of Strategy Learner : {}".format( learn_avg_daily_ret) print print "Final Manual Strategy Value: {}".format(portvals[-1]) print "Final Benchmark Value: {}".format(benchmark_portvals[-1]) print "Final Strategy Learner Value: {}".format(strat_portvals[-1]) benchmark_normalized = market.normalize_data(benchmark_portvals_raw) benchmark_normalized = market.extract_portvals_only(benchmark_normalized) best_portfolio_normalized = market.normalize_data(portvals_raw) best_portfolio_normalized = market.extract_portvals_only( best_portfolio_normalized) strat_portfolio_normalized = market.normalize_data(strat_portvals_raw) strat_portfolio_normalized = market.extract_portvals_only( strat_portfolio_normalized) stock_library = market.make_df_to_match_trading_days( colnames=['Date', 'Value'], symbol='JPM', sd=sd, ed=ed) benchmark_line = plt.plot(stock_library.index, benchmark_normalized.values, label="Benchmark") plt.setp(benchmark_line, linestyle='-', color='b', linewidth=1.0) best_portfolio_line = plt.plot(stock_library.index, best_portfolio_normalized.values, label="Manual Strategy") plt.setp(best_portfolio_line, linestyle='-', color='k', linewidth=3.0) strat_portfolio_line = plt.plot(stock_library.index, strat_portfolio_normalized.values, label="Learner Strategy") plt.setp(strat_portfolio_line, linestyle='-', color='r', linewidth=1.0) legend = plt.legend(loc='best', shadow=True) plt.title("Normalized chart for Portfolios - impact={})".format(impact)) plt.ylabel("Normalized Value") plt.grid() plt.savefig("chart_impact_{}.png".format(impact)) return cum_ret, learn_cum_ret
def testPolicy(self, symbol="JPM", sd=dt.datetime(2008, 1, 1), ed=dt.datetime(2009, 12, 31), sv=100000, variables=[1, 20]): print variables orders_df = market.make_df_to_match_trading_days( colnames=['Date', 'Symbol', 'Order', 'Shares'], symbol=self.symbol, sd=sd, ed=ed) print("Test Policy refreshed orders DF") orders_df['Symbol'] = symbol #assign to JPM orders_df['Order'] = "" #initialize with no orders orders_df['Shares'] = 0.0 #initialize with no shares orders_df['Date'] = orders_df.index short_price = 0.0 days_in_short = 0 # bollinger_df['bb1'] = SMA_df['SMA'] + (STD_rolling['STD20'] * 2) # bollinger_df['bb2'] = SMA_df['SMA'] - (STD_rolling['STD20'] * 2) #load indicators #bollinger_df = indicators.get_bollinger(symbol, sd=sd, ed=ed) #STOK_df = indicators.stochastic_oscillator_20(symbol, sd=sd, ed=ed) #SMA_df = indicators.SMA(symbol, sd=sd, ed=ed) for row in orders_df.itertuples(index=True): order_date = getattr(row, 'Date') symbol = getattr(row, 'Symbol') # print "The symbol is ", symbol order = getattr(row, 'Order') shares = getattr(row, 'Shares') self.current_stats = self.market.loc[order_date] bollinger_high_today = self.current_stats['SMA'] + ( self.current_stats['STD20'] * 2) * variables[0] * 2 bollinger_low_today = self.current_stats['SMA'] - ( self.current_stats['STD20'] * 2) * variables[0] * 2 STOK_D_today = self.current_stats[ 'STOKD'] #STOK_df.loc[order_date]['%D'] stock_price_today = self.current_stats[symbol] P_over_SMA_today = self.current_stats['PSMA'] total_votes = [] bb_vote = 0 bb_weight = 1 stochastic_vote = 0 stochastic_weight = 1 sma_vote = 0 sma_weight = 0.5 #load in the variables if stock_price_today > bollinger_high_today: bb_vote = -1 #sell! elif stock_price_today < bollinger_low_today: bb_vote = 1 #buy! if STOK_D_today < variables[1] * 100: stochastic_vote = 1 #buy! elif STOK_D_today > (100 - variables[1] * 100): stochastic_vote = -1 #get out of there! if P_over_SMA_today < variables[2]: sma_vote = -1 #looks like a selling opp total_votes.append(bb_vote * bb_weight) #total_votes.append(stochastic_vote*stochastic_weight) total_votes.append(sma_vote * sma_weight) average_vote = sum(total_votes) / len(total_votes) if self.shares < 0: days_in_short += 1 if self.shares < 0 and stock_price_today > 1.2 * short_price or days_in_short > 45: #if the price has risen 20% above our short price #or if we have been in a short position for more than 45 #get out of our position and wait for next move. orders_df.set_value(order_date, 'Order', 'BUY') orders_df.set_value(order_date, 'Shares', abs(self.shares)) self.cash_out(order_date) #self.shares = 0 #reset days_in_short = 0 else: if average_vote < 0: #this means I want to sell if abs(-1000 - self.shares ) == 0: #legality check for sale transaction pass else: self.sell(trading_day=order_date) orders_df.set_value(order_date, 'Order', 'SELL') orders_df.set_value(order_date, 'Shares', 1000) short_price = stock_price_today #self.shares = -1000 #short self.shares if average_vote > 0: #this means I want to buy if abs(1000 - self.shares ) == 0: #legality check for buy transaction pass else: self.buy(trading_day=order_date) orders_df.set_value(order_date, 'Order', 'BUY') orders_df.set_value(order_date, 'Shares', 1000) #self.shares = 1000 #long self.shares days_in_short = 0 else: pass if abs(self.shares) > 1000: print "This should never happen" #my best policy (based on seeing the future) #print orders_df #print orders_df.index #print orders_df self.trades.to_csv('test.csv') return orders_df