请参阅附图。买入和卖出订单价格是由'f“Price: {order.executed.price:6.2f}”'确认的次日开盘价,当运行' cerebro.addwriter(bt.WriterFile , csv=True, out='outputfiles{}.csv'.format(ticker)) ' 记录在文件中的价格与执行价格不同。
我在这里附上了代码
import math
import datetime
import backtrader as bt
def run_test_single():
ticker="OXY"
print("ticker")
print(ticker)
macd_stock_test2(ticker)
def macd_stock_test2(ticker):
cerebro = bt.Cerebro()
cerebro.addstrategy(GoldCross)
cerebro.broker.set_cash(1000000)
feed = bt.feeds.YahooFinanceData(
dataname=ticker,
timeframe=bt.TimeFrame.Days,
fromdate=datetime.datetime(1996, 1, 1),
todate=datetime.datetime(2020, 12, 31),
reverse=False,
)
cerebro.adddata(feed)
cerebro.addwriter(bt.WriterFile, csv=True, out='outputfiles\{}.csv'.format(ticker))
print("starting portfolio value: %.2f" % cerebro.broker.getvalue())
cerebro.run()
print("final portfolio value: %.2f" % cerebro.broker.getvalue())
cerebro.plot(style='candle')
class GoldCross(bt.Strategy): #unknow gold cross
# set parameters to define fast and slow
params = (
("fast", 12),
("slow", 26),
("order_percentage", 0.95),
("ticker", "stock"),
)
# define constractors
def __init__(self):
print("position size:", self.position.size)
self.fast_moving_average = bt.indicators.EMA(
self.data.close, period=self.params.fast, plotname="12 day moving average"
)
self.slow_moving_average = bt.indicators.EMA(
self.data.close, period=self.params.slow, plotname="26 day moving average"
)
self.crossover = bt.indicators.CrossOver(
self.fast_moving_average, self.slow_moving_average
)
def log(self, txt, dt=None):
""" Logging function fot this strategy"""
dt = dt or self.data.datetime[0]
if isinstance(dt, float):
dt = bt.num2date(dt)
print("%s, %s" % (dt.date(), txt))
def notify_order(self, order):
""" Triggered upon changes to orders. """
# Suppress notification if it is just a submitted order.
if order.status == order.Submitted:
return
# Print out the date, security name, order number and status.
dt, dn = self.datetime.date(), order.data._name
type = "Buy" if order.isbuy() else "Sell"
self.log(
# print(dn)
f"{order.data._name:<6} Order: {order.ref:3d}\tType: {type:<5}\tStatus"
f" {order.getstatusname():<8} \t"
f"Size: {order.created.size:9.1f} Price: {order.created.price:9.4f} "
f"Position: {self.getposition(order.data).size}"
)
if order.status == order.Margin:
return
# Check if an order has been completed
if order.status in [order.Completed]:
self.log(
f"{order.data._name:<6} {('BUY' if order.isbuy() else 'SELL'):<5} "
f"EXECUTED for: {dn} "
f"Price: {order.executed.price:6.2f} "
f"Cost: {order.executed.value:6.2f} "
f"Comm: {order.executed.comm:4.2f} "
f"Size: {order.created.size:9.4f} "
)
def notify_trade(self, trade):
"""Provides notification of closed trades."""
if trade.isclosed:
self.log(
"{} Closed: PnL Gross {}, Net {},".format(
trade.data._name,
round(trade.pnl, 2),
round(trade.pnlcomm, 1),
)
)
def next(self):
if self.position.size == 0:
if self.crossover > 0:
amount_to_invest = self.params.order_percentage * self.broker.cash
self.size = math.floor(amount_to_invest / self.data.close)
self.log(
"Buy {} shares of {} at {}".format(
self.size,
self.params.ticker,
self.data.close[0],
)
)
self.buy(size=self.size,price=self.data.close[0])
if self.position.size > 0:
if self.crossover < 0:
self.log(
"Sell {} shares of {} at {}".format(
self.size, self.params.ticker, self.data.close[0],
)
)
self.sell(size=self.size,price=self.data.close[0])
def end(self):
self.sell(size=self.size, price=self.data.close[0])
return
if __name__ == "__main__":
print("File one executed when ran directly")
run_test_single()
else:
print("File one executed when imported")