关于订单有效期
buy/sell/close 方法有个参数 valid 控制订单的有效期,也就是到哪一天(含)之前订单都有效
但是,有效期对市价单和收盘价单是不起作用的,这两种订单肯定会在下一个实际bar上成交,对其他类型的订单。比如限价单,有效期起作用。
valid参数的值
1、买单有效期截止到valid 这一天的 23时59分59秒 (秒)
from datetime import timedelta
def next(self):
#当前日期时间之后三个自然日内有效
valid = self.data.datetime.datetime(0) + timedelta(days=3)
self.buy(
size=100,
valid=valid,
exectype=bt.Order.Limit,
price=10
)
2、根据实际bar数量(非自然日)来确定有效期
from datetime import timedelta
def next(self):
# 当前bar后面10根bar的结束时间到期
valid = self.data.datetime.datetime(10)
self.buy(
size=100,
valid=valid,
exectype=bt.Order.Limit,
price=10
)
关于涨停、跌停
是指开盘即涨停一直持续到收盘为止的K线形态。因为这种K线形态类似于汉字的一,因此称为一字涨停。
一字涨停的股票因为开盘就有大量买单封住涨停,而卖单数量远远小于买单。
代表人们对这只股票强烈看好,所以在一字涨停期间,几乎不可能买到这支股票
涨停:无法执行买单;跌停,无法执行卖单
import datetime
import backtrader as bt
from feed import feed
from logger import lg
import backtrader.indicators as btind
class SmaCross(bt.Strategy):
params = dict(
period=5
)
def __init__(self):
self.order = None
self.move_average = bt.ind.MovingAverageSimple(
self.data.close,
period=self.p.period
)
def log(self, txt, dt=None):
dt = dt or self.data.datetime.date(0)
if isinstance(dt, float):
dt = bt.num2date(dt)
lg.info(
'%s, %s' % (dt.isoformat(), txt)
)
def notify_order(self, order):
typ = lambda: "Buy" if order.isbuy() else "Sell"
self.log(f'订单状态 {order.getstatusname()} 订单类型 {typ()}')
if order.status in [order.Submitted, order.Accepted]:
self.order = order
return
if order.status in [order.Completed]:
self.log(
f' {typ()} 订单执行价格 {order.executed.price}'
)
self.order = None
def notify_trade(self, trade):
if trade.isclosed:
self.log(
f'毛收益 {trade.pnl}, 扣佣后收益 {trade.pnlcomm}, 佣金 {trade.commission}'
)
def next(self):
if self.order:
return
if not self.position:
if self.data.close[-1] < self.move_average[-1] \
and self.data.close[0] > self.move_average[0]:
validday = self.data.datetime.datetime(1)
# 次日涨停价判断条件
upperprice = self.data.close[0] * 1.1 - 0.02
# 必然触发涨停逻辑
# upperprice = self.data.close[0] * 1.1 - 5
self.order = self.buy(
size=100,
valid=validday,
exectype=bt.Order.Limit,
price=upperprice
)
elif self.data.close[-1] > self.move_average[-1] \
and self.data.close[0] < self.move_average[0]:
validday = self.data.datetime.datetime(1)
# 次日一字跌停判断条件
# lowerprice = self.data.close[0] * 0.9 + 0.02
# 必然触发一字跌停
lowerprice = self.data.close[0] * 0.9 + 5
self.log(
f'卖单跌停价格 {lowerprice}'
)
self.order = self.sell(
size=100,
valid=validday,
exectype=bt.Order.Limit,
plimit=lowerprice
)
if __name__ == '__main__':
cerebro = bt.Cerebro()
cerebro.adddata(feed)
cerebro.addstrategy(SmaCross)
cerebro.broker.setcash(10000.0)
cerebro.broker.setcommission(0.001)
cerebro.broker.set_slippage_fixed(0.05)
lg.warning(f'初始市值 {cerebro.broker.get_value()}')
cerebro.run(stdstats=False)
lg.warning(f'最终市值 {cerebro.broker.get_value()}')
cerebro.plot()