Пример #1
0
    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]))
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
               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')
Пример #5
0
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))
Пример #6
0
    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)
Пример #7
0
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
Пример #10
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)