我正在使用Python 2.7并继续收到以下错误。如果您需要完整的代码,请告诉我,但它有点长。谢谢你的帮助。
Warning (from warnings module):
File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 3619
FutureWarning)
FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated.
Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index
这是类Portfolio
class Portfolio(object):
"""An abstract base class representing a portfolio of
positions (including both instruments and cash), determined
on the basis of a set of signals provided by a Strategy."""
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def generate_positions(self):
raise NotImplementedError("Should implement generate_positions()!")
@abc.abstractmethod
def backtest_portfolio(self):
raise NotImplementedError("Should implement backtest_portfolio()!")
这是导致&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;如果名称 ==&#34; 主要&#34;
import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pandas.io.data import DataReader
from backtest import Strategy, Portfolio
class MovingAverageCrossStrategy(Strategy):
def __init__(self, symbol, bars, short_window=8, long_window=50):
self.symbol = symbol
self.bars = bars
self.short_window = short_window
self.long_window = long_window
def generate_signals(self):
signals = pd.DataFrame(index=self.bars.index)
signals['signal'] = 0.0
# Create the set of short and long simple moving averages over the
# respective periods
signals['short_mavg'] = pd.rolling_mean(bars['Close'], self.short_window, min_periods=1)
signals['long_mavg'] = pd.rolling_mean(bars['Close'], self.long_window, min_periods=1)
# Create a 'signal' (invested or not invested) when the short moving average crosses the long
# moving average, but only for the period greater than the shortest moving average window
signals['signal'][self.short_window:] = np.where(signals['short_mavg'][self.short_window:]
> signals['long_mavg'][self.short_window:], 1.0, 0.0)
# Take the difference of the signals in order to generate actual trading orders
signals['positions'] = signals['signal'].diff()
return signals
class MarketOnClosePortfolio(Portfolio):
def __init__(self, symbol, bars, signals, initial_capital=100000.0):
self.symbol = symbol
self.bars = bars
self.signals = signals
self.initial_capital = float(initial_capital)
self.positions = self.generate_positions()
def generate_positions(self):
positions = pd.DataFrame(index=signals.index).fillna(0.0)
positions[self.symbol] = 100*signals['signal'] # This strategy buys 100 shares
return positions
def backtest_portfolio(self):
portfolio = self.positions*self.bars['Close']
pos_diff = self.positions.diff()
portfolio['holdings'] = (self.positions*self.bars['Close']).sum(axis=1)
portfolio['cash'] = self.initial_capital - (pos_diff*self.bars['Close']).sum(axis=1).cumsum()
portfolio['total'] = portfolio['cash'] + portfolio['holdings']
portfolio['returns'] = portfolio['total'].pct_change()
return portfolio
if __name__ == "__main__":
# Obtain daily bars of stock from Yahoo Finance for the period
# 1st Jan 1990 to 1st Jan 2014 - This is an example from ZipLine
symbol = 'AAPL'
bars = DataReader(symbol, "yahoo", datetime.datetime(1990,1,1), datetime.datetime(2014,1,1))
# Create a Moving Average Cross Strategy instance with a short moving
# average window of 8 days and a long window of 50 days
mac = MovingAverageCrossStrategy(symbol, bars, short_window=8, long_window=50)
signals = mac.generate_signals()
# Create a portfolio of stock, with $100,000 initial capital
portfolio = MarketOnClosePortfolio(symbol, bars, signals, initial_capital=100000.0)
returns = portfolio.backtest_portfolio()
答案 0 :(得分:5)
无法运行代码,很难指出确切的原因,但请在generate_positions
中使用此行:
portfolio = self.positions*self.bars['Close']
假设self.positions
是一个DataFrame,self.bars['Close']
是一个系列(在本例中是一个DataFrame列,以系列形式返回)。我尝试用玩具示例来解释这个问题:
首先生成一个数据帧和一个系列(带有datetimeindex):
In [3]: idx = pd.date_range('2012-01-01', periods=3)
In [5]: df = pd.DataFrame({'A':[1,2,3], 'B':[10,20,30]}, index=idx)
In [6]: df
Out[6]:
A B
2012-01-01 1 10
2012-01-02 2 20
2012-01-03 3 30
In [7]: s = pd.Series([1,2,3], index=idx)
In [8]: s
Out[8]:
2012-01-01 1
2012-01-02 2
2012-01-03 3
Freq: D, dtype: int64
现在,如果我们将两者相乘,我们会收到你注意到的警告:
In [10]: df * s
/home/joris/scipy/pandas-np16/pandas/core/frame.py:2920: FutureWarning: TimeSeries
broadcasting along DataFrame index by default is deprecated. Please use DataFrame.<op>
to explicitly broadcast arithmetic operations along the index
FutureWarning)
Out[10]:
A B
2012-01-01 1 10
2012-01-02 4 40
2012-01-03 9 90
这是因为我在评论中提到的内容在此解释:http://pandas.pydata.org/pandas-docs/stable/dsintro.html?highlight=broadcasting#data-alignment-and-arithmetic。通常,如果数据帧和系列相乘,则系列会在列上广播,而对于时间序列,这是在行上完成的。但这已被弃用 因此,您应该使用等效运算符作为警告建议。在乘法的情况下:
In [13]: df.mul(s, axis=0)
Out[13]:
A B
2012-01-01 1 10
2012-01-02 4 40
2012-01-03 9 90
因此,对于每个运算符(+,*;&lt;,&gt;,/等),都有一个等效的方法。请参阅此处获取方法列表:http://pandas.pydata.org/pandas-docs/stable/api.html#id4 [url updated]
要显示'广播列上'的含义,另一个例子是:
In [14]: s2 = pd.Series([10, 100], index=['A', 'B'])
In [15]: s2
Out[15]:
A 10
B 100
dtype: int64
In [16]: df * s2
Out[16]:
A B
2012-01-01 10 1000
2012-01-02 20 2000
2012-01-03 30 3000
正如您所看到的,系列的每个元素都与一列匹配,然后将整列与该值相乘。在时间序列的情况下,系列的每个元素都与一行匹配。