1
votes

I am scratching my head on this, as I am really confused. I am trying to compute a moving average on a numpy array. The numpy array is loaded from a txt file.

I also try to print my smas function (the moving average that I am computing on the loaded data) and fail to do so!

here is the code.

def backTest():
    portfolio = 50000
    tradeComm = 7.95

    stance = 'none'
    buyPrice = 0
    sellPrice = 0
    previousPrice = 0

    totalProfit = 0

    numberOfTrades = 0
    startPrice = 0


    startTime = 0
    endTime = 0
    totalInvestedTime = 0
    overallStartTime = 0
    overallEndTime = 0

    unixConvertToWeeks = 7*24*60*60
    unixConvertToDays = 24*60*60
    date, closep, highp, lowp, openp, volume = np.genfromtxt('AAPL2.txt', delimiter=',', unpack=True,
                                                          converters={ 0: mdates.strpdate2num('%Y%m%d')})


    window = 20
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(closep, weights, 'valid')

    prices = closep[19:]

    for price in prices:
        if stance == 'none':
            if prices > smas:
                print "buy triggered"
                buyPrice = closep
                print "bought stock for", buyPrice
                stance = "holding"
                startTime = unixStamp
                print 'Enter Date:', time.strftime('%m/%d/%Y', time.localtime(startTime))

            if numberOfTrades == 0:
                startPrice = buyPrice
                overallStartTime = unixStamp

            numberOfTrades += 1


        elif stance == 'holding':
            if prices < smas:
                print 'sell triggered'
                sellPrice = closep
                print 'finished trade, sold for:',sellPrice
                stance = 'none'
                tradeProfit = sellPrice - buyPrice
                totalProfit += tradeProfit
                print totalProfit
                print 'Exit Date:', time.strftime('%m/%d/%Y', time.localtime(endTime))
                endTime = unixStamp
                timeInvested = endTime - startTime
                totalInvestedTime += timeInvested

                overallEndTime = endTime

                numberOfTrades += 1

        previousPrice = closep

here is the error:

 Traceback (most recent call last):
  File "C:\Users\antoniozeus\Desktop\backtester2.py", line 180, in <module>
backTest()
  File "C:\Users\antoniozeus\Desktop\backtester2.py", line 106, in backTest
if prices > smas:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
2
From the error it looks like closep represents more than one value. Can you please verify ? - heretolearn
it does... closep is an array of closing prices for Apple stock - antonio_zeus
In that case you should use a loop to iterate over the array and check the condition or as the error says use "a.any()" in case you want to check if any value in the array is greater than movingAverage or "a.all()" to check if all value in the array is greater than movingAverage - heretolearn
Your code didn't show how you get movingAverage. Is it an array or a scalar? - CT Zhu
I think you trigger a buy when the current closing price is above 20 day simple moving average, am I right? - CT Zhu

2 Answers

1
votes

If you have a 1-D numpy array, there's a really slick way of doing moving averages using cumsum (via https://stackoverflow.com/a/14314054/1345536):

def moving_average(a, n=3) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

Your code snippet has a lot of code that is extraneous to the problem at hand.

1
votes

Change closep > smas to closep[-1] > smas[-1] or closep[0] > smas[0]should be the solution, according to your intended behavior.

Whether to closep[-1] > smas[-1] or closep[0] > smas[0] depends on your data: the most current price, is it the last row of the txt file, or the first in the txt file? Double check that.

To get all the possible 'buy triggers' and their closing prices, without using a loop:

if stance == 'none':
    buyPrice_list=closep[19:][closep[19:] > smas] #change it to [:-19] if the current price is the first row.

Then buyPrice_list stores all the closing prices at buy triggers. See Boolean indexing, http://wiki.scipy.org/Cookbook/Indexing.