Backtrader从0到1——第一个回测策略
Backtrader从0到1——第一个回测策略
- 0. 前言
- 1. lines && index
- 2. 生成大脑
- 3. 设置起始资金和佣金
- 4. 添加数据(重点)
- 5. 第一个策略——双均线
- 5.1 策略类
- 5.2 策略参数
- 5.3 添加指标
- 5.4 买卖与订单order
- 5.5 完整策略代码
0. 前言
本人翻阅了大量资料,以及市面上的Backtrade教程,大多都晦涩难懂,或者模棱两可,也不系统。迫于无奈,只能通过Backtrader的官方文档慢慢学习。可官方文档是英文的,使用翻译软件翻译的结果,也差强人意,只能凭借着即将消失的英文记忆,慢慢啃原文。
于是,笔者决定,将啃到的内容做一下整理,分享给大家。也是做一个Backtrader的系统性教程,希望大家支持。本系列文章除了讲解文档中的内容外,还有一些我自己的理解。
笔者不生产文档,只是文档的搬运工!!!
1. lines && index
要学习Backtrader,首先需要了解其中两个核心概念,lines
和index
。
1. lines
- 股票等金融产品中,往往有如下几个基本数据:
- Open(开盘价),High(最高价),Low(最低价),Close(收盘价), Volume(成交量),OpenInterest(持仓量)。
- 这些基本数据,沿着时间看,就是一条一条的线。因此一个数据源
Feed
中,通常存在6个line
。如果算上时间,就有7个line
。这些line
组成一个lines
,就像一个表格一样。
2. index
- 在Python中,可以用索引0访问数组的第一个元素;
- 在Backtrader中,索引0表示
lines
中当前的值,1表示下一个值,-1表示上一个值,当然还有2,-2,3…以此类推(这里不理解没关系,后面结合代码理解,有个印象即可,即Backtrader中line
的索引和传统意义上的索引不一样)。
2. 生成大脑
1. 要知道,所谓量化回测,是模拟人的思维方式,自动化的进行回测。在这个过程中,我们要再现人的思考过程。表现在代码中就是:
- a. 要思考,要先有一个脑子
cerebro
,通过bt.Cerebro()
实例化出一个; - b. 有了脑子之后,还要让脑子转起来,思考起来
cerebro.run()
。
import backtrader as btif __name__ == '__main__':cerebro = bt.Cerebro() # 创建决策大脑print('初始投资组合总价值: %.2f' % cerebro.broker.getvalue())cerebro.run() # 大脑开始思考print('最终投资组合总价值: %.2f' % cerebro.broker.getvalue())
-
可是这个大脑里面空空如也,什么也没有,所以此时
cerebro.run()
就相当于是人在发呆了,什么也没干。 -
上面代码中用到了
cerebro.broker.getvalue()
方法,作用是返回当前投资组合的总价值,计算公式为:总价值 = 现金 + ∑(持仓数量 × 最新价格)。
2. 输出结果
初始投资组合总价值: 10000.00
最终投资组合总价值: 10000.00
- 可以看到,这个实例化出的脑子中,有一个初始总价值,为1W。对一些经济商来说,1W通常是一个起始价值。
broker
的意思是经纪人,在早些时候,我们要想知道自己在股市中有多少钱,是需要到证券公司,找经纪人确认的。这里就是模拟了你向经纪人询问自己有多少钱的行为。后面这个broker
我们还会经常用到。
3. 设置起始资金和佣金
1W太少了,我要拿10W进股市!!!
- 通过
setcash()
方法,可以设置初始资金。通过setcommission()
方法设置佣金,如果是1%就填0.01,1除以100。
import backtrader as btif __name__ == '__main__':cerebro = bt.Cerebro() # 创建决策大脑cerebro.broker.setcash(100000.0)cerebro.broker.setcommission(0.0002) # 0.02%的佣金print('初始投资组合总价值: %.2f' % cerebro.broker.getvalue())cerebro.run() # 大脑开始思考print('最终投资组合总价值: %.2f' % cerebro.broker.getvalue())
- 输出:
初始投资组合总价值: 100000.00
最终投资组合总价值: 100000.00
4. 添加数据(重点)
数据源来自
akshare
,大家可以自行去官方文档查看相关接口。https://akshare.akfamily.xyz/index.html
1. 整理数据格式
- Backtrader需要的数据要有6个基本属性,可以通过
bt.feeds.PandasData(dataname=, fromdate=, todate=)
构造:- Open(开盘价),High(最高价),Low(最低价),Close(收盘价), Volume(成交量),OpenInterest(持仓量)。
- Backtrade需要的数据对索引十分敏感,必须是时间类型。
import akshare as ak
import pandas as pd# 1. 获取股票日线数据(akshare)
def GetStockDataDailyAK(code, fromdate, todate):"""code: str,股票代码formdate: date,开始日期todate: date,结束日期"""fromdate = fromdate.strftime('%Y%m%d')todate = todate.strftime('%Y%m%d')# 获取某只股票的日线级别前复权K线数据df = ak.stock_zh_a_hist(symbol=code, period="daily", start_date=fromdate, end_date=todate, adjust="qfq")# 改列名,让之后的操作更符合backtrade一般的操作习惯df = df.rename(columns={'日期':'date', '开盘':'open', '收盘':'close', '最高':'high', '成交量':'volume', '最低':'low'})# 新增一列 openinterestdf['openinterest'] = 0# 设置索引为日期格式df.index = pd.to_datetime(df.date)# 对dateframe的数据列进行整合,使其符合backtrader期望的数据格式df = df[['open', 'high', 'low', 'close', 'volume', 'openinterest']]return df
2. 添加数据
- 使用
bt.feeds.PandasData()
方法构造数据源后,使用cerebro.adddata()
方法将数据塞进大脑。
if __name__=='__main__':fromdate = datetime(2017, 1, 1)todate = datetime(2020, 1, 1)# 获取茅台的数据stock_df = GetStockDataDailyAK('600519', fromdate, todate)# 加载并读取数据源,fromdate(日期格式),todate(日期格式)data = bt.feeds.PandasData(dataname=stock_df, fromdate=fromdate, todate=todate)# 3. 策略设置cerebro = bt.Cerebro() # 创建大脑# 将数据加入回测系统cerebro.adddata(data)# 经纪人startcash = 100000 # 初始资金为10Wcerebro.broker.setcash(startcash)# 4. 执行回测print('初始总价值: %.2f' % cerebro.broker.getvalue())cerebro.run()print('最终总价值: %.2f' % cerebro.broker.getvalue())
5. 第一个策略——双均线
5.1 策略类
Backtrader中,策略也是一个类,需要继承bt.Strategy
。
1. 我们来实现一个简单的策略,打印每一天的收盘价:
class MyStrategy(bt.Strategy):def log(self, txt, dt=None):''' Logging function for this strategy'''dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def __init__(self):# Keep a reference to the "close" line in the data[0] dataseriesself.dataclose = self.datas[0].closedef next(self):# Simply log the closing price of the series from the referenceself.log('Close, %.2f' % self.dataclose[0])
2. 里面有几个核心功能:
log
:- 日志功能,通常在进行一些操作时进行日志记录,如买入和卖出。使用方法也很简单,直接调用
self.log(txt)
,传一个字符串参数txt
即可。打印格式为“日期,txt”。
- 日志功能,通常在进行一些操作时进行日志记录,如买入和卖出。使用方法也很简单,直接调用
init
:- 初始化功能,通常用来定义一些成员变量。这里需要着重解释一下,
cerebro.adddata()
方法可以执行多次,就是说可以向大脑中加入多个类似于1中的表格,也叫多个lines
。使用self.datas[0]
就访问到了第一次加入的lines
。再.close
就拿出了close
对应的这一列。所以self.dataclose
就是一条line
,之后可以通过索引访问。
- 初始化功能,通常用来定义一些成员变量。这里需要着重解释一下,
next
:- 策略执行的核心方法,Backtrader会遍一行一行的遍历
lines
。通过self.dataclose[0]
,就可以访问到遍历位置的当前收盘价。
- 策略执行的核心方法,Backtrader会遍一行一行的遍历
3. 策略加入大脑并执行
cerebro.addstrategy(MyStrategy)
知识涌进大脑!
if __name__=='__main__':fromdate = datetime(2017, 1, 1)todate = datetime(2020, 1, 1)# 获取茅台的数据stock_df = GetStockDataDailyAK('600519', fromdate, todate)# 加载并读取数据源,fromdate(日期格式),todate(日期格式)data = bt.feeds.PandasData(dataname=stock_df, fromdate=fromdate, todate=todate)# 3. 策略设置cerebro = bt.Cerebro() # 创建大脑# 将数据加入回测系统cerebro.adddata(data)# 加入自己的策略cerebro.addstrategy(MyStrategy)# 经纪人startcash = 100000 # 初始资金为10Wcerebro.broker.setcash(startcash)# 设置手续费cerebro.broker.setcommission(0.0002)# 4. 执行回测s = fromdate.strftime("%Y-%m-%d")t = todate.strftime("%Y-%m-%d")print('初始总价值: %.2f' % cerebro.broker.getvalue())cerebro.run()print('最终总价值: %.2f' % cerebro.broker.getvalue())
- 输出:
初始总价值: 100000.00
2017-01-03, Close, 122.56
2017-01-04, Close, 139.91
2017-01-05, Close, 134.74
2017-01-06, Close, 138.76
2017-01-09, Close, 136.51
2017-01-10, Close, 137.00
...
2019-12-27, Close, 983.32
2019-12-30, Close, 1006.12
2019-12-31, Close, 1003.32
最终总价值: 100000.00
- 之前我们的大脑只能发呆,现在至少可以做一些简单的“思考”了,不错,再接再厉。
5.2 策略参数
将策略中的某些值硬编码,并且无法轻松更改,这有点不切实际。参数可以派上用场。
1. 参数的定义很简单,如下所示:
class MyStrategy(bt.Strategy):params = (('myparam', 27),('exitbars', 5),)
2. 添加策略时,可以指定参数的值
# Add a strategy
cerebro.addstrategy(TestStrategy, myparam=20, exitbars=7)
5.3 添加指标
指标相信大家都不陌生,就是买卖的信号嘛。今天我们就为策略添加一个最最常见的指标,20日均线。
添加20日均线self.ma
- Backtrader中,提供了很多方便的指标计算方法,其中就包括均线;
bt.indicators.SimpleMovingAverage()
可以计算简单移动平均线,第一个参数传入收盘价,line
格式,第二个参数传周期,因为我们是20日均线,所以传20即可。
class MyStrategy(bt.Strategy):params = (('maperiod', 20),)def __init__(self):self.ma = bt.indicators.SimpleMovingAverage(self.datas[0], period=self.params.maperiod)# 引用到输入数据的close价格self.dataclose = self.datas[0].close
- 该方法返回的也是一条
line
,可以通过Backtrader特殊的索引形式访问。 - 需要注意的是,该指标至少需要20天,才可以算出一个,也就意味着,
next
方法将从lines
的20行开始遍历。
5.4 买卖与订单order
1. notify_order模块
- 这里要向大家普及一个基本常识,当我们想买入一支股票时,首先要将这个买入请求,报到场内,这个买入请求就是一个订单。
- 当一个订单报到场内后,会有如下几种情况:
- a. 订单已提交,但尚未被经纪商接受;
- b. 订单已被经纪商接受,但尚未执行;
- c. 订单执行,并已完成;
- d. 订单被取消、保证金不足或拒绝。
- 重点关心订单被取消的情况,多数情况下是因为资金不够了,买不起了。
notify_order
模块就模拟了订单在场内的各种情况。订单处理完后要及时置空。
class MyStrategy(bt.Strategy):...def notify_order(self, order):if order.status in [order.Submitted]:# 订单已提交,但尚未被经纪商接受self.log('ORDER SUBMITTED')self.order = orderelif order.status in [order.Accepted]:# 订单已被经纪商接受,但尚未执行self.log('ORDER Accepted')self.order = orderelif order.status in [order.Completed]:# 订单执行,并已完成if order.isbuy():self.log('BUY EXECUTED, %.2f' % order.executed.price)else:self.log('SELL EXECUTED, %.2f' % order.executed.price)self.order = Noneelif order.status in [order.Canceled, order.Margin, order.Rejected]:# 订单被取消、保证金不足或拒绝self.log('ORDER CANCELED/MARGIN/REJECTED')self.order = None
1. 买卖
- 我们指定一个很经典的买卖策略,当天收盘价上穿20日均线就买入,下穿20日均线就卖出。
- 买卖用
buy()/sell()
方法即可,该方法会返回一个订单类型,用self.order
接收,这是一个继承自父类的成员变量。
class MyStrategy(bt.Strategy):...def next(self):# 判断是否有订单正在进行if(self.order):return# 空仓(当前没有持仓)if not self.position:if self.datas[0].close[0] > self.ma[0]:self.order = self.buy(size=200) # 买入两百股else:if self.datas[0].close[0] < self.ma[0]:self.order = self.sell(size=200) # 卖出两百股
- 参数
size
可以指定买入多少股。
5.5 完整策略代码
import pandas as pd
from datetime import datetime
import backtrader as bt
import akshare as ak# 1. 获取股票日线数据(akshare)
def GetStockDataDailyAK(code, fromdate, todate):"""code: str,股票代码formdate: date,开始日期todate: date,结束日期"""fromdate = fromdate.strftime('%Y%m%d')todate = todate.strftime('%Y%m%d')# 获取某只股票的日线级别前复权K线数据df = ak.stock_zh_a_hist(symbol=code, period="daily", start_date=fromdate, end_date=todate, adjust="qfq")# 改列名,让之后的操作更符合backtrade一般的操作习惯df = df.rename(columns={'日期':'date', '开盘':'open', '收盘':'close', '最高':'high', '成交量':'volume', '最低':'low'})# 新增一列 openinterestdf['openinterest'] = 0# 设置索引为日期格式df.index = pd.to_datetime(df.date)# 对dateframe的数据列进行整合,使其符合backtrader期望的数据格式df = df[['open', 'high', 'low', 'close', 'volume', 'openinterest']]return df# 2. 构建策略:上穿20日均线买入,跌穿20日均线卖出
class MyStrategy(bt.Strategy):params = (('maperiod', 20),)def __init__(self):self.order = Noneself.ma = bt.indicators.SimpleMovingAverage(self.datas[0], period=self.params.maperiod)# 引用到输入数据的close价格self.dataclose = self.datas[0].closedef log(self, txt, dt=None):''' 提供记录功能'''dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def notify_order(self, order):if order.status in [order.Submitted]:# 订单已提交,但尚未被经纪商接受self.log('ORDER SUBMITTED')self.order = orderelif order.status in [order.Accepted]:# 订单已被经纪商接受,但尚未执行self.log('ORDER Accepted')self.order = orderelif order.status in [order.Completed]:# 订单执行,并已完成if order.isbuy():self.log('BUY EXECUTED, %.2f' % order.executed.price)else:self.log('SELL EXECUTED, %.2f' % order.executed.price)self.order = Noneelif order.status in [order.Canceled, order.Margin, order.Rejected]:# 订单被取消、保证金不足或拒绝self.log('ORDER CANCELED/MARGIN/REJECTED')self.order = Nonedef next(self):# 判断是否有交易指令正在进行if(self.order):return# 空仓(当前没有持仓)if not self.position:if self.datas[0].close[0] > self.ma[0]:self.order = self.buy(size=200) # 买入两百股else:if self.datas[0].close[0] < self.ma[0]:self.order = self.sell(size=200) # 卖出两百股if __name__=='__main__':fromdate = datetime(2017, 1, 1)todate = datetime(2020, 1, 1)# 获取茅台的数据stock_df = GetStockDataDailyAK('600519', fromdate, todate)# 加载并读取数据源,fromdate(日期格式),todate(日期格式)data = bt.feeds.PandasData(dataname=stock_df, fromdate=fromdate, todate=todate)# 3. 策略设置cerebro = bt.Cerebro() # 创建大脑# 将数据加入回测系统cerebro.adddata(data)# 加入自己的策略cerebro.addstrategy(MyStrategy)# 经纪人startcash = 100000 # 初始资金为10Wcerebro.broker.setcash(startcash)# 设置手续费cerebro.broker.setcommission(0.0002)# 4. 执行回测s = fromdate.strftime("%Y-%m-%d")t = todate.strftime("%Y-%m-%d")print(f'初始资金:{startcash}\n回测时间:{s} {t}')cerebro.run()portval = cerebro.broker.getvalue()print(f'剩余总资金:{portval}\n回测时间:{s} {t}')
输出
初始资金:100000
回测时间:2017-01-01 2020-01-01
2017-02-14, ORDER SUBMITTED
2017-02-14, ORDER Accepted
2017-02-14, BUY EXECUTED, 137.54
2017-02-17, ORDER SUBMITTED
2017-02-17, ORDER Accepted
2017-02-17, SELL EXECUTED, 136.90
2017-02-20, ORDER SUBMITTED
2017-02-20, ORDER Accepted
2017-02-20, BUY EXECUTED, 138.41
2017-05-09, ORDER SUBMITTED
2017-05-09, ORDER Accepted
2017-05-09, SELL EXECUTED, 192.44
2017-05-10, ORDER SUBMITTED
2017-05-10, ORDER Accepted
2017-05-10, BUY EXECUTED, 196.40
2017-07-04, ORDER SUBMITTED
2017-07-04, ORDER Accepted
2017-07-04, SELL EXECUTED, 246.96
2017-07-12, ORDER SUBMITTED
2017-07-12, ORDER Accepted
2017-07-12, BUY EXECUTED, 260.58
2017-07-13, ORDER SUBMITTED
2017-07-13, ORDER Accepted
2017-07-13, SELL EXECUTED, 250.13
2017-07-21, ORDER SUBMITTED
2017-07-21, ORDER Accepted
2017-07-21, BUY EXECUTED, 261.74
2017-09-06, ORDER SUBMITTED
2017-09-06, ORDER Accepted
2017-09-06, SELL EXECUTED, 284.78
2017-09-14, ORDER SUBMITTED
2017-09-14, ORDER Accepted
2017-09-14, BUY EXECUTED, 287.77
2017-11-23, ORDER SUBMITTED
2017-11-23, ORDER Accepted
2017-11-23, SELL EXECUTED, 436.78
2017-12-12, ORDER SUBMITTED
2017-12-12, ORDER Accepted
2017-12-12, BUY EXECUTED, 453.48
2018-01-30, ORDER SUBMITTED
2018-01-30, ORDER Accepted
2018-01-30, SELL EXECUTED, 530.78
2018-02-01, ORDER SUBMITTED
2018-02-01, ORDER Accepted
2018-02-01, BUY EXECUTED, 561.78
2018-02-02, ORDER SUBMITTED
2018-02-02, ORDER Accepted
2018-02-02, SELL EXECUTED, 547.00
2018-02-23, ORDER SUBMITTED
2018-02-23, ORDER Accepted
2018-02-23, BUY EXECUTED, 541.78
2018-03-01, ORDER SUBMITTED
2018-03-01, ORDER Accepted
2018-03-01, SELL EXECUTED, 522.78
2018-03-02, ORDER SUBMITTED
2018-03-02, ORDER Accepted
2018-03-02, BUY EXECUTED, 532.78
2018-03-06, ORDER SUBMITTED
2018-03-06, ORDER Accepted
2018-03-06, SELL EXECUTED, 519.78
2018-03-09, ORDER SUBMITTED
2018-03-09, ORDER Accepted
2018-03-09, BUY EXECUTED, 522.33
2018-03-14, ORDER SUBMITTED
2018-03-14, ORDER Accepted
2018-03-14, SELL EXECUTED, 504.45
2018-03-15, ORDER SUBMITTED
2018-03-15, ORDER Accepted
2018-03-15, BUY EXECUTED, 522.80
2018-03-23, ORDER SUBMITTED
2018-03-23, ORDER Accepted
2018-03-23, SELL EXECUTED, 495.78
2018-04-25, ORDER SUBMITTED
2018-04-25, ORDER Accepted
2018-04-25, BUY EXECUTED, 483.78
2018-04-27, ORDER SUBMITTED
2018-04-27, ORDER Accepted
2018-04-27, SELL EXECUTED, 480.03
2018-05-08, ORDER SUBMITTED
2018-05-08, ORDER Accepted
2018-05-08, BUY EXECUTED, 492.81
2018-06-20, ORDER SUBMITTED
2018-06-20, ORDER Accepted
2018-06-20, SELL EXECUTED, 546.78
2018-06-21, ORDER SUBMITTED
2018-06-21, ORDER Accepted
2018-06-21, BUY EXECUTED, 571.00
2018-06-27, ORDER SUBMITTED
2018-06-27, ORDER Accepted
2018-06-27, SELL EXECUTED, 557.78
2018-07-13, ORDER SUBMITTED
2018-07-13, ORDER Accepted
2018-07-13, BUY EXECUTED, 548.08
2018-07-31, ORDER SUBMITTED
2018-07-31, ORDER Accepted
2018-07-31, SELL EXECUTED, 526.08
2018-08-28, ORDER SUBMITTED
2018-08-28, ORDER Accepted
2018-08-28, BUY EXECUTED, 498.78
2018-09-03, ORDER SUBMITTED
2018-09-03, ORDER Accepted
2018-09-03, SELL EXECUTED, 457.78
2018-09-05, ORDER SUBMITTED
2018-09-05, ORDER Accepted
2018-09-05, BUY EXECUTED, 480.78
2018-09-06, ORDER SUBMITTED
2018-09-06, ORDER Accepted
2018-09-06, SELL EXECUTED, 457.78
2018-09-19, ORDER SUBMITTED
2018-09-19, ORDER Accepted
2018-09-19, BUY EXECUTED, 472.36
2018-10-11, ORDER SUBMITTED
2018-10-11, ORDER Accepted
2018-10-11, SELL EXECUTED, 440.79
2018-10-23, ORDER SUBMITTED
2018-10-23, ORDER Accepted
2018-10-23, BUY EXECUTED, 494.78
2018-10-24, ORDER SUBMITTED
2018-10-24, ORDER Accepted
2018-10-24, SELL EXECUTED, 433.89
2018-12-03, ORDER SUBMITTED
2018-12-03, ORDER Accepted
2018-12-03, BUY EXECUTED, 394.78
2018-12-20, ORDER SUBMITTED
2018-12-20, ORDER Accepted
2018-12-20, SELL EXECUTED, 382.00
2019-01-02, ORDER SUBMITTED
2019-01-02, ORDER Accepted
2019-01-02, BUY EXECUTED, 415.76
2019-03-11, ORDER SUBMITTED
2019-03-11, ORDER Accepted
2019-03-11, SELL EXECUTED, 545.82
2019-03-12, ORDER SUBMITTED
2019-03-12, ORDER Accepted
2019-03-12, BUY EXECUTED, 569.60
2019-03-13, ORDER SUBMITTED
2019-03-13, ORDER Accepted
2019-03-13, SELL EXECUTED, 551.28
2019-03-14, ORDER SUBMITTED
2019-03-14, ORDER Accepted
2019-03-14, BUY EXECUTED, 562.78
2019-05-07, ORDER SUBMITTED
2019-05-07, ORDER Accepted
2019-05-07, SELL EXECUTED, 699.06
2019-05-30, ORDER SUBMITTED
2019-05-30, ORDER Accepted
2019-05-30, BUY EXECUTED, 715.78
2019-06-03, ORDER SUBMITTED
2019-06-03, ORDER Accepted
2019-06-03, SELL EXECUTED, 697.78
2019-06-12, ORDER SUBMITTED
2019-06-12, ORDER Accepted
2019-06-12, BUY EXECUTED, 712.00
2019-07-16, ORDER SUBMITTED
2019-07-16, ORDER Accepted
2019-07-16, SELL EXECUTED, 795.77
2019-07-30, ORDER SUBMITTED
2019-07-30, ORDER Accepted
2019-07-30, BUY EXECUTED, 796.82
2019-08-02, ORDER SUBMITTED
2019-08-02, ORDER Accepted
2019-08-02, SELL EXECUTED, 764.32
2019-08-09, ORDER SUBMITTED
2019-08-09, ORDER Accepted
2019-08-09, BUY EXECUTED, 798.82
2019-09-12, ORDER SUBMITTED
2019-09-12, ORDER Accepted
2019-09-12, SELL EXECUTED, 886.32
2019-09-19, ORDER SUBMITTED
2019-09-19, ORDER CANCELED/MARGIN/REJECTED
2019-09-20, ORDER SUBMITTED
2019-09-20, ORDER CANCELED/MARGIN/REJECTED
2019-09-23, ORDER SUBMITTED
2019-09-23, ORDER CANCELED/MARGIN/REJECTED
2019-09-24, ORDER SUBMITTED
2019-09-24, ORDER CANCELED/MARGIN/REJECTED
2019-09-25, ORDER SUBMITTED
2019-09-25, ORDER CANCELED/MARGIN/REJECTED
2019-09-26, ORDER SUBMITTED
2019-09-26, ORDER CANCELED/MARGIN/REJECTED
2019-09-27, ORDER SUBMITTED
2019-09-27, ORDER CANCELED/MARGIN/REJECTED
2019-09-30, ORDER SUBMITTED
2019-09-30, ORDER CANCELED/MARGIN/REJECTED
2019-10-08, ORDER SUBMITTED
2019-10-08, ORDER CANCELED/MARGIN/REJECTED
2019-10-09, ORDER SUBMITTED
2019-10-09, ORDER CANCELED/MARGIN/REJECTED
2019-10-10, ORDER SUBMITTED
2019-10-10, ORDER CANCELED/MARGIN/REJECTED
2019-10-11, ORDER SUBMITTED
2019-10-11, ORDER CANCELED/MARGIN/REJECTED
2019-10-14, ORDER SUBMITTED
2019-10-14, ORDER CANCELED/MARGIN/REJECTED
2019-10-15, ORDER SUBMITTED
2019-10-15, ORDER CANCELED/MARGIN/REJECTED
2019-10-16, ORDER SUBMITTED
2019-10-16, ORDER CANCELED/MARGIN/REJECTED
2019-10-17, ORDER SUBMITTED
2019-10-17, ORDER CANCELED/MARGIN/REJECTED
2019-10-18, ORDER SUBMITTED
2019-10-18, ORDER CANCELED/MARGIN/REJECTED
2019-10-21, ORDER SUBMITTED
2019-10-21, ORDER CANCELED/MARGIN/REJECTED
2019-10-22, ORDER SUBMITTED
2019-10-22, ORDER CANCELED/MARGIN/REJECTED
2019-10-23, ORDER SUBMITTED
2019-10-23, ORDER CANCELED/MARGIN/REJECTED
2019-10-28, ORDER SUBMITTED
2019-10-28, ORDER CANCELED/MARGIN/REJECTED
2019-10-29, ORDER SUBMITTED
2019-10-29, ORDER CANCELED/MARGIN/REJECTED
2019-10-30, ORDER SUBMITTED
2019-10-30, ORDER CANCELED/MARGIN/REJECTED
2019-10-31, ORDER SUBMITTED
2019-10-31, ORDER CANCELED/MARGIN/REJECTED
2019-11-01, ORDER SUBMITTED
2019-11-01, ORDER CANCELED/MARGIN/REJECTED
2019-11-04, ORDER SUBMITTED
2019-11-04, ORDER CANCELED/MARGIN/REJECTED
2019-11-05, ORDER SUBMITTED
2019-11-05, ORDER CANCELED/MARGIN/REJECTED
2019-11-06, ORDER SUBMITTED
2019-11-06, ORDER CANCELED/MARGIN/REJECTED
2019-11-07, ORDER SUBMITTED
2019-11-07, ORDER CANCELED/MARGIN/REJECTED
2019-11-08, ORDER SUBMITTED
2019-11-08, ORDER CANCELED/MARGIN/REJECTED
2019-11-11, ORDER SUBMITTED
2019-11-11, ORDER CANCELED/MARGIN/REJECTED
2019-11-12, ORDER SUBMITTED
2019-11-12, ORDER CANCELED/MARGIN/REJECTED
2019-11-13, ORDER SUBMITTED
2019-11-13, ORDER CANCELED/MARGIN/REJECTED
2019-11-14, ORDER SUBMITTED
2019-11-14, ORDER CANCELED/MARGIN/REJECTED
2019-11-15, ORDER SUBMITTED
2019-11-15, ORDER CANCELED/MARGIN/REJECTED
2019-11-18, ORDER SUBMITTED
2019-11-18, ORDER CANCELED/MARGIN/REJECTED
2019-11-19, ORDER SUBMITTED
2019-11-19, ORDER CANCELED/MARGIN/REJECTED
2019-11-20, ORDER SUBMITTED
2019-11-20, ORDER CANCELED/MARGIN/REJECTED
2019-11-21, ORDER SUBMITTED
2019-11-21, ORDER CANCELED/MARGIN/REJECTED
2019-11-22, ORDER SUBMITTED
2019-11-22, ORDER CANCELED/MARGIN/REJECTED
2019-12-18, ORDER SUBMITTED
2019-12-18, ORDER CANCELED/MARGIN/REJECTED
2019-12-19, ORDER SUBMITTED
2019-12-19, ORDER CANCELED/MARGIN/REJECTED
2019-12-30, ORDER SUBMITTED
2019-12-30, ORDER CANCELED/MARGIN/REJECTED
2019-12-31, ORDER SUBMITTED
2019-12-31, ORDER CANCELED/MARGIN/REJECTED
剩余总资金:192051.28319999998
回测时间:2017-01-01 2020-01-01
可以看到,钱将近翻了一倍,茅台还是猛啊!!!后来我们的订单请求一直被拒绝,是因为股票涨的太狠,我们买不起了!