commit
b78020f0b8
@ -2,7 +2,7 @@
|
||||
|
||||
CSV载入模块在vnpy根目录下vnpy\app\csv_loader文件夹内,engine.py里面的CsvLoaderEngine类负责载入功能实现。
|
||||
|
||||
## 1. 初始化
|
||||
## 初始化配置
|
||||
初始化数据载入相关信息,可以分成3类:
|
||||
|
||||
- CSV文件路径
|
||||
@ -26,7 +26,7 @@ CSV载入模块在vnpy根目录下vnpy\app\csv_loader文件夹内,engine.py里
|
||||
|
||||
|
||||
|
||||
## 2. 数据载入
|
||||
## 数据载入
|
||||
|
||||
从文件路径中读取CSV文件,然后在每一次迭代中载入数据到数据库中。
|
||||
```
|
||||
|
@ -1,14 +1,47 @@
|
||||
# CTA回测模块
|
||||
CTA回测模块是基于PyQt5和pyqtgraph的图形化回测工具。启动VN Trader后,在菜单栏中点击“功能-> CTA回测”即可进入该图形化回测界面,如下图。CTA回测模块主要实现3个功能:历史行情数据的下载、策略回测、参数优化。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/cta_backtester.png)
|
||||
|
||||
|
||||
|
||||
## 加载启动
|
||||
进入图形化回测界面“CTA回测”后,会立刻完成初始化工作:初始化回测引擎、初始化RQData客户端。
|
||||
|
||||
## 1.下载数据
|
||||
数据下载功能是基于RQData的get_price()函数实现的。
|
||||
```
|
||||
get_price(order_book_ids, start_date='2013-01-04', end_date='2014-01-04', frequency='1d', fields=None, adjust_type='pre', skip_suspended =False, market='cn')
|
||||
def init_engine(self):
|
||||
""""""
|
||||
self.write_log("初始化CTA回测引擎")
|
||||
|
||||
self.backtesting_engine = BacktestingEngine()
|
||||
# Redirect log from backtesting engine outside.
|
||||
self.backtesting_engine.output = self.write_log
|
||||
|
||||
self.write_log("策略文件加载完成")
|
||||
|
||||
self.init_rqdata()
|
||||
|
||||
def init_rqdata(self):
|
||||
"""
|
||||
Init RQData client.
|
||||
"""
|
||||
result = rqdata_client.init()
|
||||
if result:
|
||||
self.write_log("RQData数据接口初始化成功")
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## 下载数据
|
||||
在开始策略回测之前,必须保证数据库内有充足的历史数据。故vnpy提供了历史数据一键下载的功能。
|
||||
下载数据功能主要是基于RQData的get_price()函数实现的。
|
||||
```
|
||||
get_price(
|
||||
order_book_ids, start_date='2013-01-04', end_date='2014-01-04',
|
||||
frequency='1d', fields=None, adjust_type='pre', skip_suspended =False,
|
||||
market='cn'
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
@ -20,27 +53,71 @@ get_price(order_book_ids, start_date='2013-01-04', end_date='2014-01-04', freque
|
||||
|
||||
填写完字段信息后,点击下方“下载数据”按钮启动下载程序,下载成功如图所示。
|
||||
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/data_loader.png)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2.加载启动
|
||||
## 策略回测
|
||||
下载完历史数据后,需要配置以下字段:交易策略、手续费率、交易滑点、合约乘数、价格跳动、回测资金。
|
||||
这些字段主要对应BacktesterEngine类的run_backtesting函数。
|
||||
```
|
||||
def run_backtesting(
|
||||
self, class_name: str, vt_symbol: str, interval: str, start: datetime,
|
||||
end: datetime, rate: float, slippage: float, size: int, pricetick: float,
|
||||
capital: int, setting: dict
|
||||
):
|
||||
```
|
||||
|
||||
点击下方的“开始回测”按钮可以开始回测:
|
||||
首先会弹出如图所示的参数配置窗口,用于调整策略参数。该设置对应的是run_backtesting()函数的setting字典。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/parameter_setting.png)
|
||||
|
||||
|
||||
|
||||
点击“确认”按钮后开始运行回测,同时日志界面会输出相关信息,如图。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/backtesting_log.png)
|
||||
|
||||
回测完成后会显示统计数字图表。
|
||||
|
||||
|
||||
|
||||
### 统计数据
|
||||
用于显示回测完成后的相关统计数值, 如结束资金、总收益率、夏普比率、收益回撤比。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/show_result.png)
|
||||
|
||||
|
||||
|
||||
### 图表分析
|
||||
以下四个图分别是代表账号净值、净值回撤、每日盈亏、盈亏分布。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/show_result_chat.png)
|
||||
|
||||
|
||||
|
||||
|
||||
## 参数优化
|
||||
|
||||
参数优化功能使用的是穷举算法,即多进程对所有参数组合进行回测,并输出最终解集。其操作流程如下:
|
||||
|
||||
- 点击“参数优化”按钮,会弹出“优化参数配置”窗口,用于设置优化目标(如最大化夏普比率、最大化收益回撤比)和设置需要优化的参数以及优化区间,如图。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/optimize_setting.png)
|
||||
|
||||
- 设置好需要优化的参数后,点击“优化参数配置”窗口下方的“确认”按钮开始进行调用CPU多核进行多进程并行优化,同时日志会输出相关信息。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/optimize_log.png)
|
||||
|
||||
- 点击“优化结果”按钮可以看出优化结果,如图的参数组合是基于目标数值(夏普比率)由高到低的顺序排列的。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/optimize_result.png)
|
||||
|
||||
|
||||
|
||||
|
||||
## 3.策略回测
|
||||
|
||||
### 3.1统计数据
|
||||
|
||||
|
||||
### 3.2图表分析
|
||||
|
||||
|
||||
|
||||
## 4.参数优化
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CTA策略模块
|
||||
|
||||
|
||||
## 1. 模块构成
|
||||
## 模块构成
|
||||
|
||||
CTA策略模块主要由7部分构成,如下图:
|
||||
|
||||
@ -14,21 +14,163 @@ CTA策略模块主要由7部分构成,如下图:
|
||||
- engine:定义了CTA策略实盘引擎,其中包括:RQData客户端初始化和数据载入、策略的初始化和启动、推送Tick订阅行情到策略中、挂撤单操作、策略的停止和移除等。
|
||||
- ui:基于PyQt5的GUI图形应用。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_strategy/seix_elementos.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_strategy/seix_elementos.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
## 2. 历史数据
|
||||
## 历史数据
|
||||
|
||||
### 回测历史数据
|
||||
回测所需要的历史数据可通过运行getdata.py文件进行下载。该文件处于根目录下tests\backtesting文件夹内。
|
||||
下载历史数据的原理是调用RQData的get_price()函数把数据下载到内存里面;再通过generate_bar_from_row()函数,以固定格式把数据从内存载入到硬盘数据库中。
|
||||
|
||||
下面介绍具体流程:
|
||||
|
||||
- 填写RQData的账号密码,初始化RQData
|
||||
```
|
||||
import rqdatac as rq
|
||||
|
||||
|
||||
USERNAME = ""
|
||||
PASSWORD = ""
|
||||
FIELDS = ["open", "high", "low", "close", "volume"]
|
||||
|
||||
rq.init(USERNAME, PASSWORD, ("rqdatad-pro.ricequant.com", 16011))
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 定义数据插入格式。需要插入的数据包括:合约代码、交易所、K线周期、开盘价、最高价、最低价、收盘价、成交量、数据库名称、vt_symbol(注意:K线周期可以是"1m"、"1h"、"d"、"w"。to_pydatetime()用于时间转换成datetime格式)
|
||||
```
|
||||
def generate_bar_from_row(row, symbol, exchange):
|
||||
""""""
|
||||
bar = DbBarData()
|
||||
|
||||
bar.symbol = symbol
|
||||
bar.exchange = exchange
|
||||
bar.interval = "1m"
|
||||
bar.open_price = row["open"]
|
||||
bar.high_price = row["high"]
|
||||
bar.low_price = row["low"]
|
||||
bar.close_price = row["close"]
|
||||
bar.volume = row["volume"]
|
||||
bar.datetime = row.name.to_pydatetime()
|
||||
bar.gateway_name = "DB"
|
||||
bar.vt_symbol = f"{symbol}.{exchange}"
|
||||
|
||||
return bar
|
||||
```
|
||||
|
||||
|
||||
|
||||
- 定义数据下载函数。主要调用RQData的get_price()获取指定合约或合约列表的历史数据(包含起止日期,日线或分钟线)。目前仅支持中国市场的股票、期货、ETF和上金所现货的行情数据,如黄金、铂金和白银产品。(注意:起始日期默认是2013-01-04,结束日期默认是2014-01-04)
|
||||
|
||||
```
|
||||
def download_minute_bar(vt_symbol):
|
||||
"""下载某一合约的分钟线数据"""
|
||||
print(f"开始下载合约数据{vt_symbol}")
|
||||
symbol, exchange = vt_symbol.split(".")
|
||||
|
||||
start = time()
|
||||
|
||||
df = rq.get_price(symbol, start_date="2018-01-01", end_date="2019-01-01", frequency="1m", fields=FIELDS)
|
||||
|
||||
with DB.atomic():
|
||||
for ix, row in df.iterrows():
|
||||
print(row.name)
|
||||
bar = generate_bar_from_row(row, symbol, exchange)
|
||||
DbBarData.replace(bar.__data__).execute()
|
||||
|
||||
end = time()
|
||||
cost = (end - start) * 1000
|
||||
|
||||
print(
|
||||
"合约%s的分钟K线数据下载完成%s - %s,耗时%s毫秒"
|
||||
% (symbol, df.index[0], df.index[-1], cost)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## 3. 策略开发
|
||||
|
||||
### 实盘历史数据
|
||||
在实盘中,RQData通过实时载入数据进行策略的初始化。该功能主要在CTA实盘引擎engine.py内实现。
|
||||
下面介绍具体流程:
|
||||
- 配置json文件:在用户目录下.vntrader文件夹找到vt_setting.json,输入RQData的账号和密码,如图。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_strategy/RQData_setting.png "enter image title here")
|
||||
|
||||
- 初始化RQData客户端:从vt_setting.json中读取RQData的账户、密码到rq_client.init()函数进行初始化
|
||||
|
||||
```
|
||||
def init_rqdata(self):
|
||||
"""
|
||||
Init RQData client.
|
||||
"""
|
||||
username = SETTINGS["rqdata.username"]
|
||||
password = SETTINGS["rqdata.password"]
|
||||
if not username or not password:
|
||||
return
|
||||
|
||||
import rqdatac
|
||||
|
||||
self.rq_client = rqdatac
|
||||
self.rq_client.init(username, password,
|
||||
('rqdatad-pro.ricequant.com', 16011))
|
||||
```
|
||||
|
||||
|
||||
- RQData载入实盘数据:输入vt_symbol后,首先会转换成符合RQData格式的rq_symbol,通过get_price()函数下载数据,并且插入到数据库中。
|
||||
|
||||
```
|
||||
def query_bar_from_rq(
|
||||
self, vt_symbol: str, interval: Interval, start: datetime, end: datetime
|
||||
):
|
||||
"""
|
||||
Query bar data from RQData.
|
||||
"""
|
||||
symbol, exchange_str = vt_symbol.split(".")
|
||||
rq_symbol = to_rq_symbol(vt_symbol)
|
||||
if rq_symbol not in self.rq_symbols:
|
||||
return None
|
||||
|
||||
end += timedelta(1) # For querying night trading period data
|
||||
|
||||
df = self.rq_client.get_price(
|
||||
rq_symbol,
|
||||
frequency=interval.value,
|
||||
fields=["open", "high", "low", "close", "volume"],
|
||||
start_date=start,
|
||||
end_date=end
|
||||
)
|
||||
|
||||
data = []
|
||||
for ix, row in df.iterrows():
|
||||
bar = BarData(
|
||||
symbol=symbol,
|
||||
exchange=Exchange(exchange_str),
|
||||
interval=interval,
|
||||
datetime=row.name.to_pydatetime(),
|
||||
open_price=row["open"],
|
||||
high_price=row["high"],
|
||||
low_price=row["low"],
|
||||
close_price=row["close"],
|
||||
volume=row["volume"],
|
||||
gateway_name="RQ"
|
||||
)
|
||||
data.append(bar)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 策略开发
|
||||
CTA策略模板提供完整的信号生成和委托管理功能,用户可以基于该模板自行开发策略。新策略可以放在根目录下vnpy\app\cta_strategy\strategies文件夹内,也可以放在用户运行的文件内(VN Station模式)。注意:策略文件命名是以下划线模式,如boll_channel_strategy.py;而策略类命名采用的是驼峰式,如BollChannelStrategy。
|
||||
|
||||
下面通过BollChannelStrategy策略示例,来展示策略开发的具体步骤:
|
||||
|
||||
### 3.1 参数设置
|
||||
### 参数设置
|
||||
|
||||
定义策略参数并且初始化策略变量。策略参数为策略类的公有属性,用户可以通过创建新的实例来调用或者改变策略参数。
|
||||
|
||||
@ -54,7 +196,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
short_stop = 0
|
||||
```
|
||||
|
||||
### 3.2 类的初始化
|
||||
### 类的初始化
|
||||
初始化分3步:
|
||||
- 通过super( )的方法继承CTA策略模板,在__init__( )函数传入CTA引擎、策略名称、vt_symbol、参数设置。
|
||||
- 调用K线生成模块:通过时间切片来把Tick数据合成1分钟K线数据,然后更大的时间周期数据,如15分钟K线。
|
||||
@ -71,7 +213,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
self.am = ArrayManager()
|
||||
```
|
||||
|
||||
### 3.3 策略的初始化、启动、停止
|
||||
### 策略的初始化、启动、停止
|
||||
通过“CTA策略”组件的相关功能按钮实现。
|
||||
|
||||
注意:函数load_bar(10),代表策略初始化需要载入10个交易日的历史数据。该历史数据可以是Tick数据,也可以是K线数据。
|
||||
@ -96,7 +238,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
"""
|
||||
self.write_log("策略停止")
|
||||
```
|
||||
### 3.4 Tick数据回报
|
||||
### Tick数据回报
|
||||
策略订阅某品种合约行情,交易所会推送Tick数据到该策略上。
|
||||
|
||||
由于BollChannelStrategy是基于15分钟K线来生成交易信号的,故收到Tick数据后,需要用到K线生成模块里面的update_tick函数,通过时间切片的方法,聚合成1分钟K线数据,并且推送到on_bar函数。
|
||||
@ -109,7 +251,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
self.bg.update_tick(tick)
|
||||
```
|
||||
|
||||
### 3.5 K线数据回报
|
||||
### K线数据回报
|
||||
|
||||
收到推送过来的1分钟K线数据后,通过K线生成模块里面的update_bar函数,以分钟切片的方法,合成15分钟K线数据,并且推送到on_15min_bar函数。
|
||||
```
|
||||
@ -120,7 +262,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
self.bg.update_bar(bar)
|
||||
```
|
||||
|
||||
### 3.6 15分钟K线数据回报
|
||||
### 15分钟K线数据回报
|
||||
|
||||
负责CTA信号的生成,由3部分组成:
|
||||
- 清空未成交委托:为了防止之前下的单子在上一个15分钟没有成交,但是下一个15分钟可能已经调整了价格,就用cancel_all()方法立刻撤销之前未成交的所有委托,保证策略在当前这15分钟开始时的整个状态是清晰和唯一的。
|
||||
@ -169,7 +311,7 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
self.put_event()
|
||||
```
|
||||
|
||||
### 3.7 委托回报、成交回报、停止单回报
|
||||
### 委托回报、成交回报、停止单回报
|
||||
|
||||
在策略中可以直接pass,其具体逻辑应用交给回测/实盘引擎负责。
|
||||
```
|
||||
@ -197,10 +339,10 @@ CTA策略模板提供完整的信号生成和委托管理功能,用户可以
|
||||
|
||||
|
||||
|
||||
## 4. 回测研究
|
||||
## 回测研究
|
||||
backtesting.py定义了回测引擎,下面主要介绍相关功能函数,以及回测引擎应用示例:
|
||||
|
||||
### 4.1 加载策略
|
||||
### 加载策略
|
||||
|
||||
把CTA策略逻辑,对应合约品种,以及参数设置(可在策略文件外修改)载入到回测引擎中。
|
||||
```
|
||||
@ -213,7 +355,7 @@ backtesting.py定义了回测引擎,下面主要介绍相关功能函数,以
|
||||
```
|
||||
|
||||
|
||||
### 4.2 载入历史数据
|
||||
### 载入历史数据
|
||||
|
||||
负责载入对应品种的历史数据,大概有4个步骤:
|
||||
- 根据数据类型不同,分成K线模式和Tick模式;
|
||||
@ -254,7 +396,7 @@ backtesting.py定义了回测引擎,下面主要介绍相关功能函数,以
|
||||
```
|
||||
|
||||
|
||||
### 4.3 撮合成交
|
||||
### 撮合成交
|
||||
|
||||
载入CTA策略以及相关历史数据后,策略会根据最新的数据来计算相关指标。若符合条件会生成交易信号,发出具体委托(buy/sell/short/cover),并且在下一根K线成交。
|
||||
|
||||
@ -349,7 +491,7 @@ backtesting.py定义了回测引擎,下面主要介绍相关功能函数,以
|
||||
|
||||
|
||||
|
||||
### 4.4 计算策略盈亏情况
|
||||
### 计算策略盈亏情况
|
||||
|
||||
基于收盘价、当日持仓量、合约规模、滑点、手续费率等计算总盈亏与净盈亏,并且其计算结果以DataFrame格式输出,完成基于逐日盯市盈亏统计。
|
||||
|
||||
@ -404,7 +546,7 @@ backtesting.py定义了回测引擎,下面主要介绍相关功能函数,以
|
||||
|
||||
|
||||
|
||||
### 4.5 计算策略统计指标
|
||||
### 计算策略统计指标
|
||||
calculate_statistics函数是基于逐日盯市盈亏情况(DateFrame格式)来计算衍生指标,如最大回撤、年化收益、盈亏比、夏普比率等。
|
||||
|
||||
```
|
||||
@ -456,7 +598,7 @@ calculate_statistics函数是基于逐日盯市盈亏情况(DateFrame格式)
|
||||
```
|
||||
|
||||
|
||||
### 4.6 统计指标绘图
|
||||
### 统计指标绘图
|
||||
通过matplotlib绘制4幅图:
|
||||
- 资金曲线图
|
||||
- 资金回撤图
|
||||
@ -495,7 +637,7 @@ calculate_statistics函数是基于逐日盯市盈亏情况(DateFrame格式)
|
||||
|
||||
|
||||
|
||||
### 4.7 回测引擎使用示例
|
||||
### 回测引擎使用示例
|
||||
|
||||
- 导入回测引擎和CTA策略
|
||||
- 设置回测相关参数,如:品种、K线周期、回测开始和结束日期、手续费、滑点、合约规模、起始资金
|
||||
@ -533,10 +675,10 @@ engine.show_chart()
|
||||
|
||||
|
||||
|
||||
## 5. 参数优化
|
||||
## 参数优化
|
||||
参数优化模块主要由3部分构成:
|
||||
|
||||
### 5.1 参数设置
|
||||
### 参数设置
|
||||
|
||||
- 设置参数优化区间:如boll_window设置起始值为18,终止值为24,步进为2,这样就得到了[18, 20, 22, 24] 这4个待优化的参数了。
|
||||
- 设置优化目标字段:如夏普比率、盈亏比、总收益率等。
|
||||
@ -598,7 +740,7 @@ class OptimizationSetting:
|
||||
|
||||
|
||||
|
||||
### 5.2 参数对组合回测
|
||||
### 参数对组合回测
|
||||
|
||||
多进程优化时,每个进程都会运行optimize函数,输出参数对组合以及目标优化字段的结果。其步骤如下:
|
||||
- 调用回测引擎
|
||||
@ -652,7 +794,7 @@ def optimize(
|
||||
|
||||
|
||||
|
||||
### 5.3 多进程优化
|
||||
### 多进程优化
|
||||
|
||||
- 根据CPU的核数来创建进程:若CPU为4核,则创建4个进程
|
||||
- 在每个进程都调用apply_async( )的方法运行参数对组合回测,其回测结果添加到results中 (apply_async是异步非阻塞的,即不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。)
|
||||
@ -697,5 +839,215 @@ def optimize(
|
||||
|
||||
|
||||
|
||||
## 6. 实盘运行
|
||||
## 实盘运行
|
||||
在实盘环境,用户可以基于编写好的CTA策略来创建新的实例,一键初始化、启动、停止策略。
|
||||
|
||||
|
||||
### 创建策略实例
|
||||
用户可以基于编写好的CTA策略来创建新的实例,策略实例的好处在于同一个策略可以同时去运行多个品种合约,并且每个实例的参数可以是不同的。
|
||||
在创建实例的时候需要填写如图的实例名称、合约品种、参数设置。注意:实例名称不能重名;合约名称是vt_symbol的格式,如IF1905.CFFEX。
|
||||
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_strategy/add_strategy.png)
|
||||
|
||||
创建策略流程如下:
|
||||
- 检查策略实例重名
|
||||
- 添加策略配置信息(strategy_name, vt_symbol, setting)到strategies字典上
|
||||
- 添加该策略要订阅行情的合约信息到symbol_strategy_map字典中;
|
||||
- 把策略配置信息保存到json文件内;
|
||||
- 在图形化界面更新状态信息。
|
||||
|
||||
```
|
||||
def add_strategy(
|
||||
self, class_name: str, strategy_name: str, vt_symbol: str, setting: dict
|
||||
):
|
||||
"""
|
||||
Add a new strategy.
|
||||
"""
|
||||
if strategy_name in self.strategies:
|
||||
self.write_log(f"创建策略失败,存在重名{strategy_name}")
|
||||
return
|
||||
|
||||
strategy_class = self.classes[class_name]
|
||||
|
||||
strategy = strategy_class(self, strategy_name, vt_symbol, setting)
|
||||
self.strategies[strategy_name] = strategy
|
||||
|
||||
# Add vt_symbol to strategy map.
|
||||
strategies = self.symbol_strategy_map[vt_symbol]
|
||||
strategies.append(strategy)
|
||||
|
||||
# Update to setting file.
|
||||
self.update_strategy_setting(strategy_name, setting)
|
||||
|
||||
self.put_strategy_event(strategy)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 初始化策略
|
||||
- 调用策略类的on_init()回调函数,并且载入历史数据;
|
||||
- 恢复上次退出之前的策略状态;
|
||||
- 调用接口的subcribe()函数订阅指定行情信息;
|
||||
- 策略初始化状态变成True,并且更新到日志上。
|
||||
|
||||
```
|
||||
def _init_strategy(self):
|
||||
"""
|
||||
Init strategies in queue.
|
||||
"""
|
||||
while not self.init_queue.empty():
|
||||
strategy_name = self.init_queue.get()
|
||||
strategy = self.strategies[strategy_name]
|
||||
|
||||
if strategy.inited:
|
||||
self.write_log(f"{strategy_name}已经完成初始化,禁止重复操作")
|
||||
continue
|
||||
|
||||
self.write_log(f"{strategy_name}开始执行初始化")
|
||||
|
||||
# Call on_init function of strategy
|
||||
self.call_strategy_func(strategy, strategy.on_init)
|
||||
|
||||
# Restore strategy data(variables)
|
||||
data = self.strategy_data.get(strategy_name, None)
|
||||
if data:
|
||||
for name in strategy.variables:
|
||||
value = data.get(name, None)
|
||||
if value:
|
||||
setattr(strategy, name, value)
|
||||
|
||||
# Subscribe market data
|
||||
contract = self.main_engine.get_contract(strategy.vt_symbol)
|
||||
if contract:
|
||||
req = SubscribeRequest(
|
||||
symbol=contract.symbol, exchange=contract.exchange)
|
||||
self.main_engine.subscribe(req, contract.gateway_name)
|
||||
else:
|
||||
self.write_log(f"行情订阅失败,找不到合约{strategy.vt_symbol}", strategy)
|
||||
|
||||
# Put event to update init completed status.
|
||||
strategy.inited = True
|
||||
self.put_strategy_event(strategy)
|
||||
self.write_log(f"{strategy_name}初始化完成")
|
||||
|
||||
self.init_thread = None
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 启动策略
|
||||
- 检查策略初始化状态;
|
||||
- 检查策略启动状态,避免重复启动;
|
||||
- 调用策略类的on_start()函数启动策略;
|
||||
- 策略启动状态变成True,并且更新到图形化界面上。
|
||||
|
||||
```
|
||||
def start_strategy(self, strategy_name: str):
|
||||
"""
|
||||
Start a strategy.
|
||||
"""
|
||||
strategy = self.strategies[strategy_name]
|
||||
if not strategy.inited:
|
||||
self.write_log(f"策略{strategy.strategy_name}启动失败,请先初始化")
|
||||
return
|
||||
|
||||
if strategy.trading:
|
||||
self.write_log(f"{strategy_name}已经启动,请勿重复操作")
|
||||
return
|
||||
|
||||
self.call_strategy_func(strategy, strategy.on_start)
|
||||
strategy.trading = True
|
||||
|
||||
self.put_strategy_event(strategy)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 停止策略
|
||||
- 检查策略启动状态;
|
||||
- 调用策略类的on_stop()函数停止策略;
|
||||
- 更新策略启动状态为False;
|
||||
- 对所有为成交的委托(市价单/限价单/本地停止单)进行撤单操作;
|
||||
- 在图形化界面更新策略状态。
|
||||
|
||||
```
|
||||
def stop_strategy(self, strategy_name: str):
|
||||
"""
|
||||
Stop a strategy.
|
||||
"""
|
||||
strategy = self.strategies[strategy_name]
|
||||
if not strategy.trading:
|
||||
return
|
||||
|
||||
# Call on_stop function of the strategy
|
||||
self.call_strategy_func(strategy, strategy.on_stop)
|
||||
|
||||
# Change trading status of strategy to False
|
||||
strategy.trading = False
|
||||
|
||||
# Cancel all orders of the strategy
|
||||
self.cancel_all(strategy)
|
||||
|
||||
# Update GUI
|
||||
self.put_strategy_event(strategy)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 编辑策略
|
||||
- 重新配置策略参数字典setting;
|
||||
- 更新参数字典到策略中;
|
||||
- 在图像化界面更新策略状态。
|
||||
|
||||
```
|
||||
def edit_strategy(self, strategy_name: str, setting: dict):
|
||||
"""
|
||||
Edit parameters of a strategy.
|
||||
"""
|
||||
strategy = self.strategies[strategy_name]
|
||||
strategy.update_setting(setting)
|
||||
|
||||
self.update_strategy_setting(strategy_name, setting)
|
||||
self.put_strategy_event(strategy)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 移除策略
|
||||
- 检查策略状态,只有停止策略后从可以移除策略;
|
||||
- 从json文件移除策略配置信息(strategy_name, vt_symbol, setting);
|
||||
- 从symbol_strategy_map字典中移除该策略订阅的合约信息;
|
||||
- 从strategy_orderid_map字典移除活动委托记录;
|
||||
- 从strategies字典移除该策略的相关配置信息。
|
||||
|
||||
```
|
||||
def remove_strategy(self, strategy_name: str):
|
||||
"""
|
||||
Remove a strategy.
|
||||
"""
|
||||
strategy = self.strategies[strategy_name]
|
||||
if strategy.trading:
|
||||
self.write_log(f"策略{strategy.strategy_name}移除失败,请先停止")
|
||||
return
|
||||
|
||||
# Remove setting
|
||||
self.remove_strategy_setting(strategy_name)
|
||||
|
||||
# Remove from symbol strategy map
|
||||
strategies = self.symbol_strategy_map[strategy.vt_symbol]
|
||||
strategies.remove(strategy)
|
||||
|
||||
# Remove from active orderid map
|
||||
if strategy_name in self.strategy_orderid_map:
|
||||
vt_orderids = self.strategy_orderid_map.pop(strategy_name)
|
||||
|
||||
# Remove vt_orderid strategy map
|
||||
for vt_orderid in vt_orderids:
|
||||
if vt_orderid in self.orderid_strategy_map:
|
||||
self.orderid_strategy_map.pop(vt_orderid)
|
||||
|
||||
# Remove from strategies
|
||||
self.strategies.pop(strategy_name)
|
||||
|
||||
return True
|
||||
```
|
||||
|
@ -2,12 +2,35 @@
|
||||
|
||||
* 快速入门
|
||||
* [项目简介](introduction.md)
|
||||
* [环境安装](install.md)
|
||||
* [安装指南](install.md)
|
||||
* [Windows安装](install.md#Windows)
|
||||
* [Ubuntu安装](install.md#Ubuntu)
|
||||
* [基本使用](quickstart.md)
|
||||
* [启动VN Trader](quickstart.md#启动VNTrader)
|
||||
* [连接接口](quickstart.md#连接接口)
|
||||
* [订阅行情](quickstart.md#订阅行情)
|
||||
* [委托交易](quickstart.md#委托交易)
|
||||
* [数据监控](quickstart.md#数据监控)
|
||||
* [应用模块](quickstart.md#应用模块)
|
||||
|
||||
|
||||
* 应用模块
|
||||
* [CTA策略](cta_strategy.md)
|
||||
* [CSV载入](csv_loader.md)
|
||||
* [初始化配置](csv_loader.md#初始化配置)
|
||||
* [数据载入](csv_loader.md#数据载入)
|
||||
* [CTA策略](cta_strategy.md)
|
||||
* [模块构成](cta_strategy.md#模块构成)
|
||||
* [历史数据](cta_strategy.md#历史数据)
|
||||
* [策略开发](cta_strategy.md#策略开发)
|
||||
* [回测研究](cta_strategy.md#回测研究)
|
||||
* [参数优化](cta_strategy.md#参数优化)
|
||||
* [实盘运行](cta_strategy.md#实盘运行)
|
||||
* [CTA回测](cta_backtester.md)
|
||||
* [加载启动](cta_backtester.md#加载启动)
|
||||
* [下载数据](cta_backtester.md#下载数据)
|
||||
* [策略回测](cta_backtester.md#策略回测)
|
||||
* [参数优化](cta_backtester.md#参数优化)
|
||||
|
||||
|
||||
* [交易接口](gateway.md)
|
||||
|
||||
|
@ -1,25 +1,25 @@
|
||||
# 基本使用
|
||||
|
||||
|
||||
## 1. 启动VN Trader
|
||||
### 1.1 VN Station模式
|
||||
## 启动VNTrader
|
||||
### VN Station模式
|
||||
登陆VN Station后,点击VN Trade Lite快速进入VN Trader(只有CTP接口);或者点击VN Trader Pro先选择如下图的底层接口和上层应用,再进入VN Trader。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/VnTrader_Pro.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/VnTrader_Pro.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
### 1.2 脚本模式
|
||||
### 脚本模式
|
||||
|
||||
在文件夹tests\trader中找到run.py文件。按住“Shift” + 鼠标右键进入cmd窗口,输入下面命令进入如图VN Trader
|
||||
```
|
||||
python run.py
|
||||
```
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/Vntrader.PNG "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/Vntrader.PNG "enter image title here")
|
||||
|
||||
|
||||
|
||||
## 2. 连接接口
|
||||
## 连接接口
|
||||
以SinNow仿真交易账号登陆CTP接口为例:点击菜单栏的“系统”->“连接CTP”后,弹出如上图所示CTP接口的配置对话框,输入以下内容后即可登录:
|
||||
- 用户名username:111111 (6位纯数字账号)
|
||||
- 密码password:1111111 (需要修改一次密码用于盘后测试)
|
||||
@ -34,18 +34,18 @@ python run.py
|
||||
|
||||
|
||||
|
||||
## 3. 订阅行情
|
||||
## 订阅行情
|
||||
在交易组件输入交易所和合约代码,并且按“Enter”键即可订阅器行情。如订阅IF股指期货,交易所:CFFEX,名称:IF905;铁矿石期货,交易所:DCE,名称:i1905。
|
||||
|
||||
此时行情组件会显示最新行情信息;交易组件会显示合约名称,并且在下方显示深度行情报价:如最新价、买一价、卖一价。(数字货币品种可以显示十档行情)
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/subcribe_contract.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/subcribe_contract.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 4. 委托交易
|
||||
## 委托交易
|
||||
交易组件适用于手动交易。除了在行情订阅中输入的交易所和合约代码以外,还需要填写以下5个字段:委托方向、开平仓类型、委托类型、委托价格和委托数量。(若委托类型为市价单,委托价格可不填。)
|
||||
|
||||
发出委托同时本地缓存委托相关信息,并且显示到委托组件和活动组件,其委托状态为“提交中”,然后等待委托回报。
|
||||
@ -59,14 +59,14 @@ python run.py
|
||||
|
||||
|
||||
|
||||
## 5. 数据监控
|
||||
## 数据监控
|
||||
|
||||
数据监控由以下组件构成,并且附带2个辅助功能:选定以下任一组件,鼠标右键可以选择“调整列宽”(特别适用于屏幕分辨率较低),或者选择“保存数据”(csv格式)
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/2_optiones.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/2_optiones.png "enter image title here")
|
||||
|
||||
|
||||
### 5.1 行情组件
|
||||
### 行情组件
|
||||
用于对订阅的行情进行实时监控,如下图,监控内容可以分成3类:
|
||||
|
||||
- 合约信息:合约代码、交易所、合约名称
|
||||
@ -75,30 +75,30 @@ python run.py
|
||||
|
||||
- 其他信息:数据推送时间、接口
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/subcribe_contract_module.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/subcribe_contract_module.png "enter image title here")
|
||||
|
||||
|
||||
### 5.2 活动组件
|
||||
### 活动组件
|
||||
活动组件用于存放还未成交的委托,如限价单或者没有立刻成交的市价单,委托状态永远是“提交中”。在该组件中鼠标双击任一委托可以完成撤单操作。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/active_order.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/active_order.png "enter image title here")
|
||||
|
||||
### 5.3 成交组件
|
||||
### 成交组件
|
||||
成交组件用于存放已成交的委托,需要注意3个字段信息:价格、数量、时间。他们都是交易所推送过来的成交信息,而不是委托信息。
|
||||
|
||||
注意:有些接口会独立推送成交信息,如CTP接口;有些接口则需要从委托信息里面提取成交相关字段,如Tiger接口。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/trade.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/trade.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
### 5.4 委托组件
|
||||
### 委托组件
|
||||
委托组件用于存放用户发出的所有委托信息,其委托状态可以是提交中、已撤销、部分成交、全部成交、拒单等等。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/order.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/order.png "enter image title here")
|
||||
|
||||
|
||||
### 5.5 持仓组件
|
||||
### 持仓组件
|
||||
持仓组件用于记录其历史持仓。其中需要了解以下字段含义
|
||||
- 方向:期货品种具有多空方向;而股票品种方向为“净”持仓。
|
||||
- 昨仓:其出现衍生于上期所特有的平今、平昨模式的需要
|
||||
@ -108,9 +108,9 @@ python run.py
|
||||
|
||||
若平仓离场,持仓数量清零,浮动盈亏变成实际盈亏从而影响账号余额变化。故以下字段:数量、昨仓、冻结、均价、盈亏均为“0”,如下图。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/query_position.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/query_position.png "enter image title here")
|
||||
|
||||
### 5.6 资金组件
|
||||
### 资金组件
|
||||
资金组件显示了账号的基础信息,如下图需要注意3个字段信息:
|
||||
- 可用资金:可以用于委托的现金
|
||||
- 冻结:委托操作冻结的金额(与保证金不是一个概念)
|
||||
@ -118,58 +118,58 @@ python run.py
|
||||
|
||||
注意:若全部平仓,浮动盈亏变成实际盈亏,保证金和浮动盈亏清零,总资金等于可用资金
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/query_account.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/query_account.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
### 5.7 日志组件
|
||||
### 日志组件
|
||||
日志组件用于显示接口登陆信息以及委托报错信息,如下图。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/write_log.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/write_log.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 6. 应用模块
|
||||
## 应用模块
|
||||
vnpy官方目前提供2个应用模块组件,分别是用于自动交易的“CTA策略”组件;把第三方数据文件导入到数据库的“CSV载入”组件。在菜单栏中点击“功能”,即显示应用模块,如下图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/application.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/application.png "enter image title here")
|
||||
|
||||
### 6.1 CTA策略
|
||||
### CTA策略
|
||||
CTA策略组件默认使用RQData的数据进行自动交易,故需要配置好RQData相关数据。
|
||||
|
||||
1) 在用户目录下.vntrader文件夹找到vt_setting.json,输入RQData的账号和密码,保存退出后启动CTA策略组件,会显示“RQData数据接口初始化成功”,如图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/RQData.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/RQData.png "enter image title here")
|
||||
|
||||
|
||||
2)在左上方的菜单栏选择策略,如“AtrRsiStrategy”,然后点击右边的“添加策略”按钮,用于策略实例创建,选择策略适用品种和修改该测试示例的参数,如图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/trader_2.PNG "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/trader_2.PNG "enter image title here")
|
||||
|
||||
|
||||
3)每一个策略示例都有其“初始化”、“启动”、“停止”、“编辑”、“移除”按钮。注意在启动策略前必须先初始化,移除策略前需要先停止策略。右上方菜单栏有批量处理功能,方便用户快速启动、停止策略,如图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/turtle_strategy.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/turtle_strategy.png "enter image title here")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 6.2 CSV载入
|
||||
### CSV载入
|
||||
CSV文件是用户最主要的历史数据来源之一,用户只需根据CSV文件中的表头字段,以及时间格式灵活配置,即可实现一键载入历史数据。
|
||||
|
||||
CSV载入操作分为3步:
|
||||
|
||||
1)打开CSV文件,查看表头字段以及时间格式,如图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/csv_format.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/csv_format.png "enter image title here")
|
||||
|
||||
2)点击菜单栏的“功能”->“CSV载入”,进入界面后选择要载入的CSV文件,并且修改相关表头字段和时间格式(若有需要的话)。如下图:
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/csv_loader.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/csv_loader.png "enter image title here")
|
||||
|
||||
3)点击“载入数据”后,成功界面如下图所示。
|
||||
|
||||
![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/exito_csv_load.png "enter image title here")
|
||||
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/quick_start/exito_csv_load.png "enter image title here")
|
||||
|
Loading…
Reference in New Issue
Block a user