1

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()
8
  • From the error it looks like closep represents more than one value. Can you please verify ? Commented Apr 5, 2014 at 19:49
  • it does... closep is an array of closing prices for Apple stock Commented Apr 5, 2014 at 19:55
  • 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 Commented Apr 5, 2014 at 19:58
  • Your code didn't show how you get movingAverage. Is it an array or a scalar? Commented Apr 5, 2014 at 20:00
  • 1
    I think you trigger a buy when the current closing price is above 20 day simple moving average, am I right? Commented Apr 5, 2014 at 20:07

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

He only used one line for that: np.convolve(DATA_TO_MA, weights, 'valid')
Right. In which case, this should probably be submitted to codereview.stackexchange.com instead? PS -- Didn't know about 'valid' option for convolve; that's a much better approach. Very cool; thanks!
valid control the behavior of the moving average, here especially when DATA_TO_MA is shorter than Weights. Try np.convolve(range(10), np.repeat(1.0, 20)/20, 'full') V.S. same or valid
range(10) give you [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]. Just to make up something that is shorter than np.repeat(1.0, 20)/20
i have edited my script, see above. the for loop still doesnt solve my issue.
1

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.

8 Comments

one problem with this - is that I needed to change closep[19:] > smas because i got an error: 'ValueError: operands could not be broadcast together with shapes (522) (503)'
No, you are interested in the current closing price, rather than that ALL previous 522 closing prices have to be higher than SMA. So, no, just get the most current by slice both arrays by [0] or [-1] depending on your data. If you want to do the latter, you need (closep[19:] > smas).all()
so I followed those inxs, and noticed that the backtester immediately stops... because it is not a loop, I am simply looking at one period. but I have an array of closing prices and an array of moving averages...
okay -tried this as well and created a new error.. really sorry that some of this stuff I do not understand ' File "C:/Users/antoniozeus/Desktop/backtester2.py", line 173, in <module> backTest() File "C:/Users/antoniozeus/Desktop/backtester2.py", line 104, in backTest buyPrice_list=closep[-19:][closep[-19]>smas] ValueError: too many boolean indices'
LOL okay, true, but now this: File "C:/Users/antoniozeus/Desktop/backtester2.py", line 104, in backTest buyPrice_list=closep[-19:][closep[-19:]>smas] ValueError: operands could not be broadcast together with shapes (19) (503)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.