def minimize_this(self, variables): #print variables orders_df = self.testPolicy(symbol=self.symbol, sd=self.sd, ed=self.ed, sv=self.sv, variables=variables) #attempting to make this faster if self.stock_price_library is None: #pre-processing orders_df = orders_df.sort_values(['Date']) orders_column = orders_df['Date'] start_date = orders_column.head(1).dt end_date = orders_column.tail(1).dt start_date = dt.datetime(start_date.year, start_date.month, start_date.day) end_date = dt.datetime(end_date.year, end_date.month, end_date.day) list_of_symbols = orders_df.Symbol.unique().tolist() # This really makes me wish Python was typesafe self.stock_price_library = market.get_stock_prices(list_of_symbols, start_date, end_date) portvals_raw = market.compute_portvals_abridged_faster(orders_df, commission=self.commission, impact=self.impact, stock_price_library=self.stock_price_library) # clean up portvals = market.extract_portvals_only(portvals_raw) cum_ret, avg_daily_ret, std_daily_ret, sharpe_ratio = market.compute_portval_stats(portvals, rfr=0.0, sf=252, sv=self.sv) if sharpe_ratio <=0: return sharpe_ratio*-10e6 #some big number we don't want print("sharpe is ", sharpe_ratio, "for ", self.symbol) return float(1)/sharpe_ratio #minimizing the inverse of sharpe will maximize sharpe
def minimize_this(self, variables): if self.verbose: print variables orders_df = self.testPolicy(symbol=self.symbol, sd=self.sd, ed=self.ed, sv=self.sv, variables=variables) #attempting to make this faster if self.stock_price_library is None: self.stock_price_library = market.get_stock_prices([self.symbol], self.sd, self.ed) portvals_raw = market.compute_portvals_abridged_faster( orders_df, commission=self.commission, impact=self.impact, stock_price_library=self.stock_price_library) portvals = portvals_raw[portvals_raw.columns[0]] cum_ret = portvals[-1] / float(self.sv) - 1 #lightning optimization return -cum_ret #I apply a negative so negative returns are positive, and positive returns are negative
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 plot_prices(symbol='JPM', sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,12,31)): stock_price_library = market.get_stock_prices([symbol], sd, ed) #print stock_price_library price_line = plt.plot(stock_price_library.index, stock_price_library[symbol], label=symbol) plt.setp(price_line, color='r', linewidth=1.0) plt.xlabel("Date") plt.ylabel(("Stock Price")) plt.title("Stock Price vs Date") return #fig #generate some plots
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 minimize_this(self, variables): #print variables orders_df = self.testPolicy(symbol=self.symbol, sd=self.sd, ed=self.ed, sv=self.sv, variables=variables) #attempting to make this faster if self.stock_price_library is None: self.stock_price_library = market.get_stock_prices([self.symbol], self.sd, self.ed) portvals_raw = market.compute_portvals_abridged_faster( orders_df, commission=self.commission, impact=self.impact, stock_price_library=self.stock_price_library) # sddr = daily_returns.std() # # # back calculate daily risk free rate given the annual risk free rate # daily_rfr = (1 + rfr) ** (1 / float(252)) - 1 # # sr = (daily_returns - daily_rfr).mean() / (daily_returns - daily_rfr).std() # # # Convert to annualized sharpe ratio # K = sf ** (1 / float(2)) # sr = K * sr # clean up portvals = market.extract_portvals_only(portvals_raw) cum_ret, avg_daily_ret, std_daily_ret, sharpe_ratio = market.compute_portval_stats( portvals, rfr=0.0, sf=252, sv=self.sv) if sharpe_ratio <= 0: return sharpe_ratio * -10e6 #some big number we don't want print("sharpe is ", sharpe_ratio, "for ", self.symbol) print("cumulative return is ", cum_ret) return float( 1 ) / sharpe_ratio #minimizing the inverse of sharpe will maximize sharpe
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