data = defineData() # gets AAPL between the in-sample dates set as default smaWindow = 60 bbWindow = 20 momWindow = 10 crossWindow = 25 sma = getSma(data, smaWindow) bb = getBb(data, bbWindow) bbUpper = sma + 2 * data.rolling(window=bbWindow).std() bbLower = sma - 2 * data.rolling(window=bbWindow).std() mom = getMom(data, momWindow) crossover = getCross(data, crossWindow) order = bestPossibleStrategy(data) createOrder(order, 'bestPossibleStrategy') cumReturn, portVals = testcode_marketsim('bestPossibleStrategy', verbose=False) print 'cumulative return of best possible strategy [%] = {}'.format( cumReturn * 100) plt.figure(figsize=(12, 14)) plt.subplot(421) data.plot(label='adj. close') sma.plot(label='sma') plt.ylabel('prices') lg = plt.legend(loc='best') lg.draw_frame(False) plt.subplot(422) plt.plot(data / sma - 1) plt.ylabel('sma indicator') plt.xlim((data.index[0], data.index[-1]))
def optimizeY(prices): """ @Summary: Optimize Ybuy/Ysell parameters by plotting averaged error & cumulative return for training/cross-val datasets vs. Ybuy (assuming Ybuy = Ysell) @param prices: Series, contains adj. close price with date indices @returns nothing """ numParam = 13 tryParam = np.logspace(-4, -1, num=numParam) # values of Ybuy = Ysell # to iterate over fname = 'ML_based' # name of orders file cumRetTrain = np.zeros(numParam) cumRetCrossVal = np.zeros(numParam) accTrain = np.zeros(numParam) accCrossVal = np.zeros(numParam) learner = rt.RTclassLearner(leaf_size=5, verbose=False) # create learner reps = 100 # number of RTclassLearners whose predictions to average over start = time.time() for i in range(numParam): # X is a ndarray, Y is a 1darray X, Y, dates = getXY(prices, Ybuy=tryParam[i], Ysell=tryParam[i]) split = int(0.6 * len(Y)) # divide into train and cross-val sets trainX = X[:split - 1, :] trainY = Y[:split - 1] trainDates = dates[:split - 1] crossValX = X[split:, :] crossValY = Y[split:] crossValDates = dates[split:] print tryParam[i] # print parameter values during computation for j in range(reps): learner.add_Evidence(trainX, trainY) # train on trainX, trainY # training sample querying pred = learner.query(trainX) # get the predictions accTrain[i] += np.sum(pred == trainY) / float( len(trainY)) # accuracy signal = pd.Series( pred, index=trainDates) # create Series from predictions order = tradingStrategy(signal) createOrder(order, fname) # write order to disk cumReturn, portVals = testcode_marketsim(fname, verbose=False) cumRetTrain[i] += cumReturn # cross-validation sample querying pred = learner.query(crossValX) # get the predictions accCrossVal[i] += np.sum(pred == crossValY) / float(len(crossValY)) signal = pd.Series(pred, index=crossValDates) order = tradingStrategy(signal) createOrder(order, fname) cumReturn, portVals = testcode_marketsim(fname, verbose=False) cumRetCrossVal[i] += cumReturn stop = time.time() print 'Time to calculate cumulative return & error vs the selected parameters: {} s' \ .format(stop - start) plt.figure(figsize=(6, 8)) plt.subplot(211) plt.semilogx(tryParam * 100, cumRetTrain * 100 / reps, '.-', label='training') plt.semilogx(tryParam * 100, cumRetCrossVal * 100 / reps, '.-', label='cross-val') plt.ylabel('cumulative return [%]') plt.title('Random Decision Tree (leaf size = 5)') lg = plt.legend(loc='best') lg.draw_frame(False) plt.subplot(212) plt.semilogx(100 * tryParam, 100 - 100 * accTrain / reps, '.-', label='training') plt.semilogx(100 * tryParam, 100 - 100 * accCrossVal / reps, '.-', label='cross-val') plt.xlabel('Ybuy or Ysell [% change]') plt.ylabel('error [%]') lg = plt.legend(loc='best') lg.draw_frame(False)
def testcode(): prices = defineData(startDate = '01-01-2008', stopDate = '31-12-2009', \ symList = ['AAPL']) # in-sample dates # optimizeY(prices) # UNCOMMENT to optimize Ybuy/Ysell Ybuy = 0.01 Ysell = 0.01 holdTime = 21 X, Y, dates = getXY(prices, Ybuy, Ysell, holdTime) # X is an ndarray, Y is # a 1darray # optimizeParam(X, Y, dates) # UNCOMMENT to optimize leaf size of RTclassLearner # or numher of bags of BagClassLearner ##### create a learner learner = rt.RTclassLearner(leaf_size=75, verbose=False) # create learner split = int(0.6 * len(Y)) # divide into training and cross-val sets trainX = X[:split - 1, :] trainY = Y[:split - 1] trainDates = dates[:split - 1] crossValX = X[split:, :] crossValY = Y[split:] crossValDates = dates[split:] #####Training on the entire in-sample data (USE WITH CAUTION) # learner.add_Evidence(X, Y)# train it # pred = learner.query(X)# get the predictions # accuracy = np.sum(pred == Y) / float( len(Y) ) # print("In sample results") # print ('Error [%]: ', round(100 - 100 * accuracy, 4) ) # # Generate order from in-sample predictions # signal = pd.Series(pred, index = dates) # order = tradingStrategy(signal) # createOrder(order, 'ML_based') # cumReturn, portVals = testcode_marketsim('ML_based', verbose = False) # # # Plot entire in-sample data, training indicators and their predictions (USE WITH CAUTION) # plt.figure(figsize = (11,13)) # plt.subplot(411) # plt.plot(prices / prices[0], color = 'k', label = 'benchmark') # plt.plot(portVals / portVals[0], color = 'g', label = 'ML-based') # plt.xticks(rotation=30) # plt.ylabel('normalized') # plt.title('cumulative return = {} %'.format(round(cumReturn * 100))) # plotVline(order) # lg = plt.legend(loc = 'best') # lg.draw_frame(False) # # plt.subplot(412) # plt.plot(signal / 2) # plt.xlim((prices.index[0], prices.index[-1])) # plt.xticks(rotation=30) # # plt.subplot(413) # plt.scatter(X[Y == 0, 1], X[Y == 0, 2], color = 'k', label = 'hold') # plt.scatter(X[Y == 1, 1], X[Y == 1, 2], color = 'g', label = 'buy') # plt.scatter(X[Y == -1, 1], X[Y == -1, 2], color = 'r', label = 'sell') # plt.title('in-sample data and labels before training') # lg = plt.legend(loc = 'best') # lg.draw_frame(True) # # plt.subplot(414) # plt.scatter(X[pred == 0, 1], X[pred == 0, 2], color = 'k', label = 'hold') # plt.scatter(X[pred == 1, 1], X[pred == 1, 2], color = 'g', label = 'buy') # plt.scatter(X[pred == -1, 1], X[pred == -1, 2], color = 'r', label = 'sell') # plt.xlabel('Momentum indicator'); plt.ylabel('Crossover indicator') # plt.title('in-sample data and predictions after training') # lg = plt.legend(loc = 'best') # lg.draw_frame(True) # ######out of sample testing after training on training set testPrices = defineData('01-01-2010', '31-12-2011') # out-of-sample dates testX, testY, testDates = getXY(testPrices, Ybuy, Ysell, holdTime) # testX # is an ndarray, testY is a 1darray cumRetTest = 0.0 accTest = 0.0 reps = 1 # number of configuratiokns of RTclassLearners whose predictions # to average over start = time.time() for j in range(reps): learner.add_Evidence(trainX, trainY) # train it pred = learner.query(testX) # get the predictions accTest += np.sum(pred == testY) / float(len(testY)) # accuracy # Generate order from out of sample predictions signal = pd.Series(pred, index=testDates) order = tradingStrategy(signal) createOrder(order, 'ML_based') cumReturn, portVals = testcode_marketsim('ML_based', verbose=False) cumRetTest += cumReturn stop = time.time() print("Test sample results") print('Error [%]: ', round(100 - 100 * accTest / reps, 4)) print('Cumulative return [%]: ', round(cumRetTest * 100 / reps, 4)) print('Elapsed time [s]: ', round(stop - start, 2)) plt.plot(prices[:split - 1] / prices.values[0], label='train') plt.plot(prices[split:] / prices.values[0], label='cross-val') plt.plot(testPrices / prices.values[0], label='test') lg = plt.legend(loc='best') lg.draw_frame(False) plt.xticks(rotation=30)
1 * ((bbIndicator < -1) & (standardize(data).diff(1) > bbThreshold)) crossIndicator, crossWindow = getCrossIndicator(data) crossThreshold = 0.08 # 0.08 optimized value on manual trading strategy 1 # generate a buy/sell signal if indicator is close to 0.5/-0.5 crossSignal = 1 * ((crossIndicator - 0.5).abs() < crossThreshold) + \ -1 * ((crossIndicator + 0.5).abs() < crossThreshold) # Combine individual signals. bbSignal is neglected here since including it # with the other signals did not result in label-free trading using strategy 1 signal = 1 * ((smaSignal == 1) & (momSignal ==1) & (crossSignal == 1)) \ + -1 * ((smaSignal == -1) & (momSignal == -1) & (crossSignal == -1)) order = tradingStrategy(signal, holdTime) createOrder(order, 'rule_based') cumReturn, portVals = testcode_marketsim('rule_based', verbose=False) print('Cumulative return [%]: ', round(cumReturn * 100, 4)) plt.figure(figsize=(10, 10)) plt.subplot(311) plt.plot(data / data[0], label='benchmark', color='k') plt.plot(portVals / portVals[0], label='rule-based') plt.xticks(rotation=30) plotVline(order) plt.title('rule-based with sma + mom + crossover indicators') lg = plt.legend(loc='best') lg.draw_frame(False) plt.ylabel('normalized') plt.subplot(312) plt.plot(smaSignal / 2, label='sma')
def optimizeParam(X, Y, dates): """ @Summary: Optimize leaf size of RTclassLearner or number of bags of BagClassLearner by plotting averaged error and cumulative return for training & cross-val datasets vs. leaf size / number of bags @param X: ndarray, of technical indicators. Examples in rows, features in columns @param Y: 1darray, of the labels -1 (sell), 0 (hold), and 1 (buy) based on future returns after a holding time period @returns nothing """ numParam = 1 tryParam = np.linspace(75, 75, num=numParam) # values of leaf size / number # of bags to iterate over fname = 'ML_based' # name of orders file cumRetTrain = np.zeros(numParam) cumRetCrossVal = np.zeros(numParam) accTrain = np.zeros(len(tryParam)) accCrossVal = np.zeros(len(tryParam)) reps = 1000 # number of configurations of RTclassLearners or #BagClassLearners whose predictions to average over split = int(0.6 * len(Y)) # divide into train and cross-val sets trainX = X[:split - 1, :] trainY = Y[:split - 1] trainDates = dates[:split - 1] crossValX = X[split:, :] crossValY = Y[split:] crossValDates = dates[split:] start = time.time() for i in range( numParam): # initialize either RTclassLearner/BagClassLearner learner = rt.RTclassLearner(leaf_size=tryParam[i], verbose=False) # create learner # learner = bl.BagClassLearner(learner = rt.RTclassLearner, kwargs = {"leaf_size":75}, \ # bags = int(tryParam[i]), boost = False, verbose = False) # create BagClassLearner print tryParam[i] # print parameter values during computation for j in range(reps): learner.add_Evidence(trainX, trainY) # train on trainX, trainY # training sample querying pred = learner.query(trainX) # get the predictions accTrain[i] += np.sum(pred == trainY) / float( len(trainY)) # accuracy signal = pd.Series( pred, index=trainDates) # create Series from predictions order = tradingStrategy(signal) createOrder(order, fname) # write order to disk cumReturn, portVals = testcode_marketsim(fname, verbose=False) cumRetTrain[i] += cumReturn # cross-validation sample querying pred = learner.query(crossValX) # get the predictions accCrossVal[i] += np.sum(pred == crossValY) / float(len(crossValY)) signal = pd.Series(pred, index=crossValDates) order = tradingStrategy(signal) createOrder(order, fname) cumReturn, portVals = testcode_marketsim(fname, verbose=False) cumRetCrossVal[i] += cumReturn stop = time.time() print 'Time to calculate error vs the selected parameter: {} s'.format( \ round( stop - start, 2)) plt.figure(figsize=(6, 8)) plt.subplot(211) plt.plot(tryParam, cumRetTrain * 100 / reps, '.-', label='training') plt.plot(tryParam, cumRetCrossVal * 100 / reps, '.-', label='cross-val') plt.ylabel('cumulative return [%]') plt.title('RT Learner (Ybuy = Ysell = 1 %)') # CHECK Ybuy/Ysell value here lg = plt.legend(loc='best') lg.draw_frame(False) print('Cumulative return [%]: ', round(cumRetCrossVal[-1] * 100 / reps, 4)) plt.subplot(212) plt.plot(tryParam, 100 - 100 * accTrain / reps, '.-', label='training') plt.plot(tryParam, 100 - 100 * accCrossVal / reps, '.-', label='cross-val') plt.xlabel('leaf size') # CHECK leaf size OR number of bags plt.ylabel('error') lg = plt.legend(loc='best') lg.draw_frame(False) print('Error [%]: ', round(100 - 100 * accCrossVal[-1] / reps, 4))
trainY = Y[:split - 1] trainDates = dates[:split - 1] crossValX = X[split:, :] crossValY = Y[split:] crossValDates = dates[split:] learner.addEvidence(X, Y) # Training on the entire in-sample data pred = learner.query(X) # get the predictions accuracy = np.sum(pred == Y) / float(len(Y)) print("In sample results") print ('Error [%]: ', round(100 - 100 * accuracy, 4)) signal = pd.Series(pred, index=dates) # Generate order from in-sample predictions order = tradingStrategy(signal) createOrder(order, 'ML_Strat') cumReturn, portVals = testcode_marketsim('ML_Strat', verbose=False) # Plot entire in-sample data, training indicators and their predictions plt.figure(figsize=(11, 13)) plt.subplot(411) plt.plot(prices / prices[0], color='k', label='benchmark') plt.plot(portVals / portVals[0], color='g', label='ML-based') plt.xticks(rotation=30) plt.ylabel('normalized') plt.title('cumulative return = {} %'.format(round(cumReturn * 100))) plotVline(order) lg = plt.legend(loc='best') lg.draw_frame(False) plt.subplot(412) plt.plot(signal / 2)
def testcode(): data = defineData() # get AAPL between the in-sample dates set as default holdTime = 21 # in days smaIndicator, smaWindow = getSmaIndicator(data) smaThreshold = 0.012 #0.012 # optimized value on manual trading strategy 1 # generate a buy signal (1) if price falls significantly below sma # generate a sell signal (-1) if prices rises significantly above sma smaSignal = 1 * (smaIndicator < -smaThreshold) + \ -1 * (smaIndicator > smaThreshold) momIndicator, momWindow = getMomIndicator(data) momThreshold = 0.06 #0.055 # optimized value on manual trading strategy 1 # generate a buy/sell signal if momentum is greatly positive/negative momSignal = -1 * (momIndicator < -momThreshold) + \ 1 * (momIndicator > momThreshold) bbWindow = 10 #48 NOT OPTIMIZED bbIndicator = getBb(data, bbWindow) bbThreshold = 0 #0.2 NOT OPTIMIZED # generate a buy/sell signal if indicator is below/above the lower/upper BB # and the indicator is rising/falling significantly bbSignal = -1 * ((bbIndicator > 1) & \ (standardize(data).diff(1) < -bbThreshold)) + \ 1 * ((bbIndicator < -1) & \ (standardize(data).diff(1) > bbThreshold)) crossIndicator, crossWindow = getCrossIndicator(data) crossThreshold = 0.08 #0.08 # optimized value on manual trading strategy 1 # generate a buy/sell signal if indicator is close to 0.5/-0.5 crossSignal = 1 * ( (crossIndicator - 0.5).abs() < crossThreshold) + \ -1 * ( (crossIndicator + 0.5).abs() < crossThreshold ) # Combine individual signals. bbSignal is neglected here since including it # with the other signals did not result in label-free trading using strategy 1 signal = 1 * ( (smaSignal == 1) & (momSignal ==1 ) & (crossSignal == 1) ) \ + -1 * ( (smaSignal == -1) & (momSignal == -1) & (crossSignal == -1) ) order = tradingStrategy(signal, holdTime) createOrder(order, 'rule_based') cumReturn, portVals = testcode_marketsim('rule_based', verbose=False) print('Cumulative return [%]: ', round(cumReturn * 100, 4)) plt.figure(figsize=(10, 10)) plt.subplot(311) plt.plot(data / data[0], label='benchmark', color='k') plt.plot(portVals / portVals[0], label='rule-based') plt.xticks(rotation=30) plotVline(order) plt.title('rule-based with sma + mom + crossover indicators') lg = plt.legend(loc='best') lg.draw_frame(False) plt.ylabel('normalized') plt.subplot(312) plt.plot(smaSignal / 2, label='sma') plt.plot(momSignal / 1.3, '.', label='mom') plt.plot(crossSignal / 1.1, '.', label='crossover') plt.plot(signal, label='overall signal') plt.xticks(rotation=30) plt.ylabel('indicator signals [a.u.]') lg = plt.legend(loc='center right') lg.draw_frame(False) plt.subplot(313) plt.scatter(momIndicator[signal==0], crossIndicator[signal==0], \ color = 'k', label = 'hold') plt.scatter(momIndicator[signal==1], crossIndicator[signal==1], \ color = 'g', label = 'buy') plt.scatter(momIndicator[signal==-1], crossIndicator[signal==-1], \ color = 'r', label = 'sell') lg = plt.legend(loc='best') lg.draw_frame(True) plt.xlabel('Momentum Indicator') plt.ylabel('Crossover Indicator')
def testPolicy(self, symbol = "IBM", sd=dt.datetime(2009,1,1), \ ed=dt.datetime(2010,1,1), sv = 10000): """ @Summary: uses the existing Q-table policy and tests it against new data @returns cumReturn: float, cumulative return of portfolio obtained by trading with the learnt Q-table policy """ syms=[symbol] dates = pd.date_range(sd, ed) prices_all = ut.get_data(syms, dates) # automatically adds SPY prices = prices_all[syms] # only portfolio symbols without SPY # prices[symbol] converts prices DataFrame to Series df = self.getIndicators(prices[symbol]) numIndicators = len(self.thresholdList) order = pd.DataFrame(np.zeros(len(df)), index = df.index, \ columns = ['number of units']) currOrder = 0 #current order status: short= -1, noPos = 0, long = 1 action = 1 # short = 0, hold = 1, long = 2 rList = [] # list of rewards, used only for plotting numDays = len(df); day = 0 oldPrice = prices.ix[df.index[0]] # to calculate reward, get price on first trading day # initialize discretized indicators computed below for each day # in the trading period dailyDiscrete = -1 * np.ones( numIndicators ) while day < numDays: date = df.index[day] for i in range( numIndicators ): step = 0 # initialize to first bin # threshold in thresholdList are ordered by ascending values for threshold in self.thresholdList[i]: if df.ix[date, i] <= threshold: dailyDiscrete[i] = step break step += 1 else: # for loop fell through without identifying a threshold dailyDiscrete[i] = len(self.thresholdList[i]) - 1 # get unique state with currOrder incremented by unity so it # takes values >= 0 state = self.getState(currOrder + 1, dailyDiscrete, self.numSteps) priceDifference = prices.ix[date, 0] - oldPrice r = currOrder * priceDifference rList.append([date, self.scaleForPlot * r]) # use the QLearner's query that does not update the Q-table action = self.learner.querysetstate(state) signal = action - 1 order.ix[date, 0], currOrder, day = \ self.dailyTradingStrategy(signal, currOrder, \ date, df.index[-1], day, self.holdTime) if order.ix[date, 0] != 0: # anchor oldPrice to when a oldPrice = prices.ix[date, 0] # transaction is made if day >= numDays: order.ix[df.index[-1], 0] = -currOrder createOrder(order['number of units'], 'QL_based', \ symbol = symbol, unit = self.unit) cumReturn, portVals = testcode_marketsim('QL_based', \ sv = sv, leverLimit = False, verbose = False) if self.verbose: plt.figure(figsize = (11,4)) plt.plot([item[0] for item in rList], \ [item[1] for item in rList], '.g', label = 'scaled reward') plt.plot(prices / prices.ix[df.index[0]] - 1, 'k', \ label = 'benchmark') plt.xlim((df.index[0], df.index[-1])) plt.plot(portVals / portVals[0] - 1, 'g', label = 'QL-based') plt.legend(loc = 'best') plt.ylabel('normalized return') plt.title('Test data, cumulative return = {}'.format(cumReturn)) plotVline(order['number of units']) plt.axhline(y = 0, color = 'k', linestyle = ':') return cumReturn
def addEvidence(self, symbol = "IBM", sd=dt.datetime(2008,1,1), \ ed=dt.datetime(2009,1,1), sv = 10000): """ @Summary: creates a QLearner, and trains it for trading @returns nothing """ def discretize(df, numSteps = np.asarray([10, 10, 10])): """ @Summary: Converts continuous indicators of a stock into discretized indicators by deciding how many elements will be in each bin (say n), sorting each indicator, & setting the thresholds to be the value of every nth element @parameter df: DataFrame, continuous indicators @parameter numsteps: ndarray, each element corresponds to number of steps or bins used to discretize each indicator. Each element can be independently varied. @returns dfThresholded: DataFrame, discretized indicators @returns thresholdList: List, of sublists of increasing values of thresholds used for binning. Each sublist corresponds to one indicator """ dfSorted = df.copy() # make copy so that we can sort in-place # without changing the original dataFrame counter = 0 # iterator for numSteps desired for each indicator thresholdList = [] for col in list(dfSorted): # for each column of indicators # stepSize = number of elements in each bin stepSize = int( round( len(df) / float(numSteps[counter]) ) ) threshold = np.zeros( numSteps[counter] ) # appropriate number # of thresholds initialized dfSorted.sort_values(col, inplace = True) #sort on selected col for i in range(numSteps[counter]): if i == (numSteps[counter] - 1):# for last bin, thresh=max threshold[i] = dfSorted[col].values[-1] # or last value # set all remaining elements in the sorted column of # indicators to be in the last bin or step dfSorted[col].ix[i * stepSize :] = i else: # set threshold = every stepSize-th element threshold[i] = \ dfSorted[col].values[(i +1) * stepSize] # set all prior elements in the sorted column of # indicators to have the appropriate bin or step number dfSorted[col].ix[i * stepSize : (i + 1) * stepSize] = i thresholdList.append(threshold) # append ndarray of thresholds counter += 1 # END OUTER for LOOP dfThresholded = dfSorted.sort_index() # restore sort on df indices return dfThresholded, thresholdList # MAIN BODY OF addEvidence METHOD syms=[symbol] dates = pd.date_range(sd, ed) prices_all = ut.get_data(syms, dates) # automatically adds SPY prices = prices_all[syms] # only portfolio symbols, prices is a DataFrame # prices[symbol] converts prices DataFrame to Series df = self.getIndicators(prices[symbol]) # df of continuous indicators dfThresholded, thresholdList = discretize(df, self.numSteps) self.thresholdList = thresholdList # save for reference by testPolicy # initialize QLearner. 3 accounts for no-position, short and long # states and for hold, sell and buy actions self.learner = ql.QLearner(num_states = 3 * np.prod(self.numSteps), \ num_actions = 3, dyna = 200, verbose = False) maxIteration = 10 # iterations to try for convergence to a policy cumReturn = np.zeros(maxIteration); iteration = 0 numDays = len(df) # maximum number of days in the trading period start = time.time() if self.verbose: plt.figure(figsize = (11,4)) while (iteration < maxIteration): order = pd.DataFrame(np.zeros(len(df)), index = df.index, \ columns = ['number of units']) currOrder = 0 #current order status: short= -1, noPos = 0, long = 1 action = 1 # short = 0, hold = 1, long = 2 day = 0 # start of period for which indicators are available rList = [] # list of rewards, used only for plotting while day < numDays: date = df.index[day] dailyDiscrete = dfThresholded.values[day, :] # today's discretized indicator values # get unique state with currOrder incremented by unity so it # takes values >= 0 state = self.getState(currOrder + 1, dailyDiscrete, \ self.numSteps) if day == 0: # the first day with technical indicators. No reward since we enter with no-position action = self.learner.querysetstate(state) signal = action - 1 # to represent short = -1, hold = 0, long = 1 oldPrice = prices.ix[date, 0] # [date,0] returns a pure number from the prices DataFrame else: priceDifference = prices.ix[date, 0] - oldPrice # reward/penalty for prior selection of the position to be in r = currOrder * priceDifference action = self.learner.query(state, r) signal = action - 1 rList.append([date, self.scaleForPlot * r]) # update current order, current position and index of next date order.ix[date, 0], currOrder, day = \ self.dailyTradingStrategy(signal, currOrder, \ date, df.index[-1], day, self.holdTime) if order.ix[date, 0] != 0: # anchor oldPrice to when a oldPrice = prices.ix[date, 0] # transaction is made if day >= numDays: # if index of next date to trade is outside trading period, order.ix[df.index[-1], 0] = -currOrder # redeem outstanding positions createOrder(order['number of units'], 'QL_based', \ symbol = symbol, unit = self.unit) cumReturn[iteration], portVals = \ testcode_marketsim('QL_based', sv = sv, leverLimit = False, \ verbose = False) if self.verbose: print 'iteration = {}, Cumulative return = {}'.format(\ iteration, cumReturn[iteration]) if (iteration > 0) & \ (cumReturn[iteration] == cumReturn[iteration - 1]): iteration += 1 break iteration += 1 # end While loop stop = time.time() if self.verbose: print 'Elapsed time for training = {} s'.format( round(stop - start, 2) ) plt.plot([item[0] for item in rList], \ [item[1] for item in rList], '.g', label = 'scaled reward') plt.plot( prices.ix[df.index] / prices.ix[df.index[0]] - 1, \ 'k', label = 'benchmark') plt.plot(portVals / portVals[0] - 1, 'g', label = 'QL-based') plt.ylabel('normalized return') plt.title('Training data, final cumulative return = {}'.format( \ cumReturn[iteration - 1]) ) plt.legend(loc = 'best') plotVline(order['number of units']) plt.axhline(y = 0, color = 'k', linestyle = ':') # plot horizontal line at y = 0
def testcode(): data = defineData() # get AAPL between the in-sample dates set as default smaWindow = 60 sma = getSma(data, smaWindow) bbWindow = 20 bb = getBb(data, bbWindow) bbUpper = sma + 2 * data.rolling(window = bbWindow).std() bbLower = sma - 2 * data.rolling(window = bbWindow).std() momWindow = 10 mom = getMom(data, momWindow) crossWindow = 25 crossover = getCross(data, crossWindow) plt.figure(figsize = (12,14)) plt.subplot(421) data.plot(label='adj. close') sma.plot(label='sma') plt.ylabel('prices') lg = plt.legend(loc = 'best') lg.draw_frame(False) plt.subplot(422) plt.plot(data / sma - 1) plt.ylabel('sma indicator') plt.xlim((data.index[0], data.index[-1])) plt.xticks(rotation=30) plt.subplot(423) data.plot(label='adj. close') plt.plot(bbUpper, label='upper BB') plt.plot(bbLower, label='lower BB') plt.ylabel('prices') lg = plt.legend(loc = 'best') lg.draw_frame(False) plt.subplot(424) plt.plot(bb) plt.ylabel('Bollinger band indicator') plt.xlim((data.index[0], data.index[-1])) plt.xticks(rotation=30) plt.subplot(426) plt.plot(mom) plt.ylabel('momentum') plt.xlim((data.index[0], data.index[-1])) plt.xticks(rotation=30) plt.subplot(427) plt.plot(1 / (1 + data / getSma(data, crossWindow))) plt.ylabel('crossover value') plt.xlim((data.index[0], data.index[-1])) plt.xticks(rotation=30) plt.subplot(428) plt.plot(crossover) plt.ylabel('crossover indicator') plt.xlim((data.index[0], data.index[-1])) plt.xticks(rotation=30) order = bestPossibleStrategy(data) createOrder(order, 'bestPossibleStrategy') cumReturn, portVals = testcode_marketsim('bestPossibleStrategy', verbose = False) print 'cumulative return of best possible strategy [%] = {}'.format(cumReturn * 100)