ошибка python - скользящая средняя по массиву numpy

Я ломаю голову над этим, так как я действительно запутался. Я пытаюсь вычислить скользящее среднее в массиве numpy. Массив numpy загружается из текстового файла.

Я также пытаюсь распечатать свою функцию smas (скользящее среднее значение, которое я вычисляю для загруженных данных) и не могу этого сделать!

вот код.

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

вот ошибка:

 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()

person antonio_zeus    schedule 05.04.2014    source источник
comment
Судя по ошибке, похоже, что closep представляет более одного значения. Можете ли вы проверить?   -  person heretolearn    schedule 05.04.2014
comment
да... closep — это массив цен закрытия акций Apple.   -  person antonio_zeus    schedule 05.04.2014
comment
В этом случае вы должны использовать цикл для перебора массива и проверки условия или, как говорит ошибка, используйте a.any(), если вы хотите проверить, больше ли какое-либо значение в массиве, чем movingAverage или a.all() чтобы проверить, все ли значения в массиве больше, чем movingAverage   -  person heretolearn    schedule 05.04.2014
comment
В вашем коде не показано, как вы получаете movingAverage. Это array или скаляр?   -  person CT Zhu    schedule 06.04.2014
comment
извинения - должно быть smas, а не movingAverage   -  person antonio_zeus    schedule 06.04.2014
comment
как мне настроить цикл for? в смысле, как бы я передал ему данные?   -  person antonio_zeus    schedule 06.04.2014
comment
Я думаю, вы инициируете покупку, когда текущая цена закрытия выше 20-дневной простой скользящей средней, я прав?   -  person CT Zhu    schedule 06.04.2014
comment
да сэр! это именно то, что я пытаюсь сделать   -  person antonio_zeus    schedule 06.04.2014


Ответы (2)


Если у вас есть массив 1-D numpy, есть действительно удобный способ делать скользящие средние с использованием cumsum (через 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

В вашем фрагменте кода много кода, не связанного с рассматриваемой проблемой.

person Travis D.    schedule 05.04.2014
comment
Он использовал для этого только одну строку: np.convolve(DATA_TO_MA, weights, 'valid') - person CT Zhu; 06.04.2014
comment
Верно. В этом случае его, вероятно, следует отправить на codereview.stackexchange.com? PS -- Не знал о «допустимой» опции для свертки; это гораздо лучший подход. Очень круто; Спасибо! - person Travis D.; 06.04.2014
comment
valid управляют поведением скользящей средней, особенно когда DATA_TO_MA короче Weights. Попробуйте np.convolve(range(10), np.repeat(1.0, 20)/20, 'full') В.С. same или valid - person CT Zhu; 06.04.2014
comment
range(10) дать вам [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]. Просто чтобы придумать что-то короче, чем np.repeat(1.0, 20)/20 - person CT Zhu; 06.04.2014
comment
я отредактировал свой скрипт, см. выше. цикл for по-прежнему не решает мою проблему. - person antonio_zeus; 06.04.2014

Измените closep > smas на closep[-1] > smas[-1] или closep[0] > smas[0]должно быть решением в соответствии с вашим предполагаемым поведением.

Будет ли это closep[-1] > smas[-1] или closep[0] > smas[0], зависит от ваших данных: самая актуальная цена, это последняя строка файла txt или первая в файле txt? Дважды проверьте это.

Чтобы получить все возможные «триггеры покупки» и их цены закрытия без использования цикла:

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

Затем buyPrice_list сохраняет все цены закрытия в триггерах покупки. См. Логическое индексирование, http://wiki.scipy.org/Cookbook/Indexing.

person CT Zhu    schedule 05.04.2014
comment
одна проблема с этим - это то, что мне нужно было изменить closep[19:] › smas, потому что я получил ошибку: "ValueError: операнды не могут быть переданы вместе с формами (522) (503)" - person antonio_zeus; 06.04.2014
comment
Нет, вас интересует текущая цена закрытия, а не то, что ВСЕ предыдущие 522 цены закрытия должны быть выше SMA. Итак, нет, просто получите самую актуальную информацию, разделив arrays на [0] или [-1] в зависимости от ваших данных. Если вы хотите сделать последнее, вам нужно (closep[19:] > smas).all() - person CT Zhu; 06.04.2014
comment
поэтому я проследил за этими индексами и заметил, что бэктестер сразу же останавливается... потому что это не цикл, я просто смотрю на один период. но у меня есть массив цен закрытия и массив скользящих средних... - person antonio_zeus; 06.04.2014
comment
хорошо - попробовал это и создал новую ошибку.. очень жаль, что некоторые из этих вещей я не понимаю ' Файл C:/Users/antoniozeus/Desktop/backtester2.py, строка 173, в файле ‹module› backTest() C:/Users/antoniozeus/Desktop/backtester2.py, строка 104, в backTest buyPrice_list=closep[-19:][closep[-19]›smas] ValueError: слишком много логических индексов - person antonio_zeus; 06.04.2014
comment
LOL хорошо, правда, но теперь это: Файл C:/Users/antoniozeus/Desktop/backtester2.py, строка 104, в backTest buyPrice_list=closep[-19:][closep[-19:]›smas] ValueError: операнды могли не транслироваться вместе с формами (19) (503) - person antonio_zeus; 06.04.2014
comment
Подожди! я думаю, что знаю, что происходит - person antonio_zeus; 06.04.2014
comment
должно быть closep[:-19], верно? В противном случае вы выбираете ПОСЛЕДНИЕ 19 элементов. - person CT Zhu; 06.04.2014
comment
Я добавил цикл for и все равно получаю ту же ошибку. Проверьте цены сейчас, они начинаются на 19 точек данных внутрь, так как моя скользящая средняя 20 должна быть одинаковой длины. - person antonio_zeus; 06.04.2014