Copy disabled (too large)
Download .txt
Showing preview only (34,296K chars total). Download the full file to get everything.
Repository: vnpy/vnpy
Branch: master
Commit: 3d00af968323
Files: 155
Total size: 32.4 MB
Directory structure:
gitextract_unzv_8vm/
├── .github/
│ ├── CODE_OF_CONDUCT.md
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── SUPPORT.md
│ └── workflows/
│ └── pythonapp.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_ENG.md
├── docs/
│ ├── community/
│ │ ├── app/
│ │ │ ├── algo_trading.md
│ │ │ ├── chart_wizard.md
│ │ │ ├── cta_backtester.md
│ │ │ ├── cta_strategy.md
│ │ │ ├── data_manager.md
│ │ │ ├── data_recorder.md
│ │ │ ├── excel_rtd.md
│ │ │ ├── index.rst
│ │ │ ├── option_master.md
│ │ │ ├── paper_account.md
│ │ │ ├── portfolio_manager.md
│ │ │ ├── portfolio_strategy.md
│ │ │ ├── risk_manager.md
│ │ │ ├── rpc_service.md
│ │ │ ├── script_trader.md
│ │ │ ├── spread_trading.md
│ │ │ └── web_trader.md
│ │ ├── index.rst
│ │ ├── info/
│ │ │ ├── contribution.md
│ │ │ ├── database.md
│ │ │ ├── datafeed.md
│ │ │ ├── gateway.md
│ │ │ ├── i18n.md
│ │ │ ├── index.rst
│ │ │ ├── introduction.md
│ │ │ ├── pycharm.md
│ │ │ ├── veighna_station.md
│ │ │ ├── veighna_trader.md
│ │ │ └── vscode.md
│ │ └── install/
│ │ ├── index.rst
│ │ ├── mac_install.md
│ │ ├── ubuntu_install.md
│ │ └── windows_install.md
│ ├── conf.py
│ ├── elite/
│ │ ├── extension/
│ │ │ ├── elite_algotrading.md
│ │ │ ├── elite_dingtalk.md
│ │ │ ├── elite_feishu.md
│ │ │ ├── elite_ladder.md
│ │ │ └── index.rst
│ │ ├── index.rst
│ │ ├── info/
│ │ │ ├── elite_install.md
│ │ │ ├── elite_lab.md
│ │ │ ├── elite_trader.md
│ │ │ └── index.rst
│ │ └── strategy/
│ │ ├── elite_algotrading.md
│ │ ├── elite_ctastrategy.md
│ │ ├── elite_datamanager.md
│ │ ├── elite_filter.md
│ │ ├── elite_function.md
│ │ ├── elite_optionstrategy.md
│ │ ├── elite_portfoliostrategy.md
│ │ ├── elite_riskmanager.md
│ │ ├── elite_spreadtrading.md
│ │ └── index.rst
│ └── index.rst
├── examples/
│ ├── alpha_research/
│ │ ├── download_data_rq.ipynb
│ │ ├── download_data_xt.ipynb
│ │ ├── research_workflow_alpha101.ipynb
│ │ ├── research_workflow_lasso.ipynb
│ │ ├── research_workflow_lgb.ipynb
│ │ └── research_workflow_mlp.ipynb
│ ├── candle_chart/
│ │ └── run.py
│ ├── client_server/
│ │ ├── run_client.py
│ │ └── run_server.py
│ ├── cta_backtesting/
│ │ ├── backtesting_demo.ipynb
│ │ └── portfolio_backtesting.ipynb
│ ├── data_recorder/
│ │ └── data_recorder.py
│ ├── download_bars/
│ │ └── download_bars.ipynb
│ ├── no_ui/
│ │ └── run.py
│ ├── notebook_trading/
│ │ └── demo_notebook.ipynb
│ ├── portfolio_backtesting/
│ │ └── backtesting_demo.ipynb
│ ├── simple_rpc/
│ │ ├── test_client.py
│ │ └── test_server.py
│ ├── spread_backtesting/
│ │ └── backtesting.ipynb
│ └── veighna_trader/
│ ├── demo_script.py
│ └── run.py
├── install.bat
├── install.sh
├── install_osx.sh
├── pyproject.toml
├── tests/
│ └── test_alpha101.py
└── vnpy/
├── __init__.py
├── alpha/
│ ├── __init__.py
│ ├── dataset/
│ │ ├── __init__.py
│ │ ├── cs_function.py
│ │ ├── datasets/
│ │ │ ├── __init__.py
│ │ │ ├── alpha_101.py
│ │ │ └── alpha_158.py
│ │ ├── math_function.py
│ │ ├── processor.py
│ │ ├── ta_function.py
│ │ ├── template.py
│ │ ├── ts_function.py
│ │ └── utility.py
│ ├── lab.py
│ ├── logger.py
│ ├── model/
│ │ ├── __init__.py
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ ├── lasso_model.py
│ │ │ ├── lgb_model.py
│ │ │ └── mlp_model.py
│ │ └── template.py
│ └── strategy/
│ ├── __init__.py
│ ├── backtesting.py
│ ├── strategies/
│ │ ├── __init__.py
│ │ └── equity_demo_strategy.py
│ └── template.py
├── chart/
│ ├── __init__.py
│ ├── axis.py
│ ├── base.py
│ ├── item.py
│ ├── manager.py
│ └── widget.py
├── event/
│ ├── __init__.py
│ └── engine.py
├── py.typed
├── rpc/
│ ├── __init__.py
│ ├── client.py
│ ├── common.py
│ └── server.py
└── trader/
├── __init__.py
├── app.py
├── constant.py
├── converter.py
├── database.py
├── datafeed.py
├── engine.py
├── event.py
├── gateway.py
├── locale/
│ ├── __init__.py
│ ├── build_hook.py
│ ├── en/
│ │ └── LC_MESSAGES/
│ │ └── vnpy.po
│ ├── generate_mo.bat
│ ├── generate_pot.bat
│ └── vnpy.pot
├── logger.py
├── object.py
├── optimize.py
├── setting.py
├── ui/
│ ├── __init__.py
│ ├── ico/
│ │ └── __init__.py
│ ├── mainwindow.py
│ ├── qt.py
│ └── widget.py
└── utility.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# 行为准则
这是一份VeighNa项目社区的行为准则,也是项目作者自己在刚入行量化金融行业时对于理想中的社区的期望:
* 为交易员而生:作为一款从金融机构量化业务中诞生的交易系统开发框架,设计上都优先满足机构专业交易员的使用习惯,而不是其他用户(散户、爱好者、技术人员等)
* 对新用户友好,保持耐心:大部分人在接触新东西的时候都是磕磕碰碰、有很多的问题,请记住此时别人对你伸出的援助之手,并把它传递给未来需要的人
* 尊重他人,慎重言行:礼貌文明的交流方式除了能得到别人同样的回应,更能减少不必要的摩擦,保证高效的交流
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## 环境
* 操作系统: 如Windows 11或者Ubuntu 22.04
* Python版本: 如VeighNa Studio-4.0.0
* VeighNa版本: 如v4.0.0发行版或者dev branch 20250320(下载日期)
## Issue类型
三选一:Bug/Enhancement/Question
## 预期程序行为
## 实际程序行为
## 重现步骤
针对Bug类型Issue,请提供具体重现步骤以及报错截图
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
建议每次发起的PR内容尽可能精简,复杂的修改请拆分为多次PR,便于管理合并。
## 改进内容
1.
2.
3.
## 相关的Issue号(如有)
Close #
================================================
FILE: .github/SUPPORT.md
================================================
# 获取帮助
在开发和使用VeighNa项目的过程中遇到问题时,获取帮助的渠道包括:
* Github Issues:[Issues页面](https://github.com/vnpy/vnpy/issues)
* 官方QQ群: 262656087
* 项目论坛:[VeighNa量化社区](http://www.vnpy.com/forum)
* 项目邮箱: vn.py@foxmail.com
================================================
FILE: .github/workflows/pythonapp.yml
================================================
name: Python application
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.13
uses: actions/setup-python@v1
with:
python-version: '3.13'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff mypy uv types-tqdm
uv pip install ta-lib==0.6.4 --index=https://pypi.vnpy.com --system
uv pip install -e .[alpha,dev] --system
- name: Lint with ruff
run: |
# Run ruff linter based on pyproject.toml configuration
ruff check .
- name: Type check with mypy
run: |
# Run mypy type checking based on pyproject.toml configuration
mypy vnpy
- name: Build packages with uv
run: |
# Build source distribution and wheel distribution
uv build
================================================
FILE: .gitignore
================================================
# Python
*.pyc
*.pyo
*.pyd
*.egg-info/
# Jupyter
.ipynb_checkpoints
# IDE
.vscode
.idea
*.wpr
*.wpu
.vs
x64
# Temp
build
dist
*.local
# VeighNa
.vntrader
# Visual Studio intermediate files
*.exp
*.iobj
*.ipdb
*.pdb
# Documents
_build
_static
_templates
# Misc
.DS_Store
*.mo
# Alpha
lab/
/.mypy_cache
================================================
FILE: CHANGELOG.md
================================================
# 4.3.0版本
## 新增
1. vnpy.alpha增加WorldQuant的Alpha 101因子特征数据集
## 调整
1. vnpy_sec/vnpy_esunny升级适配4.0版本
2. vnpy_ctabacktester的策略代码编辑功能支持cursor和pycharm编辑器
3. vnpy_ctastrategy的回测引擎,增加RGR绩效统计指标(感谢上弦之月贡献)
4. ArrayManager增加对于指标计算函数重载(Function Overload)的类型提示声明
5. vnpy_ctp增加特殊情况撤单(非交易时段、资金不足等)的日志输出
6. DataProxy的所有比较运算,直接返回pl.Int32(而不是Bool)
7. 重构ts_slope / ts_rsquare / ts_resi算子函数
## 修复
1. vnpy_ib修复查询历史数据问题(query_history函数增加查询锁解决多线程冲突问题)
2. vnpy_optionmaster修复深度虚值期权的隐含波动率计算收敛问题
# 4.2.0版本
## 新增
1. vnpy_riskmanager模块重构
a. 采用插件式设计,提供标准化风控规则开发模板
b. 支持中国期货程序化交易系统监管要求中的风控规则
c. 输出拦截日志后播放提示声音,目前仅支持Windows系统
d. 使用系统托盘栏图标,弹出交易风控拦截日志气泡框
e. 提供Cython版本的风控规则开发模板以及具体规则实现
f. 支持自动扫描加载用户自定义风控规则(放置于Trader目录下的rules文件夹中)
2. vnpy_polygon数据服务接口,支持海外股票、期货、期权等资产品种的历史数据获取
## 调整
1. vnpy_ctp更新底层API到6.7.11(生产和测试统一版本)
2. vnpy_dolphindb升级适配4.0版本
3. vnpy_tqsdk简化时间戳的格式化方法,提高效率
4. vnpy_sqlite支持使用配置文件中声明的数据文件
5. vnpy_taos优化get_bar_overview和get_tick_overview函数性能(直接访问超级表的tags)
6. vnpy_spreadtrading / vnpy_portfoliostrategy / vnpy_scripttrader 注册模块日志输出到日志引擎
7. vnpy_optionmaster优化定价模型中期权最小价值边界判断的逻辑
8. 全局配置中的log.level改为INFO(10),默认启用详细日志记录输出
9. MainEngine增加交易功能函数的调用日志输出
10. vnpy.alpha中的Dataset增加process_data函数,便于测试不同数据处理器的效果
11. vnpy_ib更新支持ibapi至10.40.1版本
## 修复
1. vnpy_gm修复中金所和大商所合约代码转换的问题
2. vnpy_rqdata修复RqdataGateway中的行情订阅函数错误问题
3. vnpy_optionmaster修复关闭窗口时的异常报错
4. vnpy_portfoliostrategy修复遗传算法参数优化中的调用传参问题
5. 修复Linux系统上的sdist安装问题:vnpy_mini / vnpy_sopt / vnpy_rohon / vnpy_tap / vnpy_tts
6. vnpy_xt修复XtGateway断线重连时的传参错误
7. vnpy_optionmaster修复black-76模型中theta计算公式的问题
8. vnpy_postgresql修复写入主键冲突时数据不会更新的问题
# 4.1.0版本
# 新增
1. vnpy_mcdata新增对于Tick数据查询的支持
2. OrderType枚举值增加ETF类型,支持ETF申购和赎回业务
3. 增加遗传算法优化函数run_ga_optimization的入参,允许用户控制优化过程中所使用的全部超参
4. CTA策略回测引擎,增加对于遗传算法优化函数新入参的支持
## 调整
1. 升级扩展模块适配4.0版本:
* 交易接口:
* 期货类:vnpy_uft/vnpy_mini/vnpy_femas/vnpy_ctptest
* 股票类:vnpy_xtp/vnpy_tora
* 期权类:vnpy_hts/vnpy_sopt/vnpy_sopttest
* 资管类:vnpy_rohon/vnpy_lstar/vnpy_jees
* 其他类:vnpy_ksgold/vnpy_tts/vnpy_tap/vnpy_da/vnpy_ib
* 策略应用:
* 策略类:vnpy_portfoliostrategy/vnpy_ctabacktester/vnpy_spreadtrading/vnpy_scripttrader
* 交易类:vnpy_algotrading/vnpy_optionmaster/vnpy_portfoliomanager/vnpy_paperaccount
* 数据类:vnpy_datarecorder/vnpy_excelrtd/vnpy_datamanager
* 辅助类:vnpy_chartwizard/vnpy_webtrader/vnpy_rpcservice/vnpy_riskmanager
* 数据库:vnpy_mysql/vnpy_postgresql/vnpy_mongodb/vnpy_taos
* 数据服务:vnpy_gm/vnpy_xt/vnpy_tqsdk/vnpy_ifind/vnpy_tushare/vnpy_wind
2. 使用close函数替代unbind,来实现vnpy.rpc模块中zmq.Socket的安全关闭
3. 修改PySide6依赖版本为6.8.2.1,解决部分底层warning输出问题
4. 修改ta-lib依赖版本为0.6.4,解决Linux和Mac系统的安装问题
5. 调整Qt层捕捉到全局异常时的日志输出级别为Critical
6. vnpy_datarecorder移除不必要的行情录制异常抛出,改为记录日志
7. vnpy_rqdata下载股票数据时,除权方式有pre改为pre_volume
8. 数据库模块录制行情数据时,默认跳过extra字段
9. vnpy_ib支持10.30.1版本的ibapi,增加对于新版本撤单函数的传参支持
## 修复
1. 修复新版本ta-lib中,MA_Type类不再是枚举值导致的部分指标计算问题
2. 修复补全MainEngine缺失的get_tick函数
3. 修复邮件发送引擎在使用QQ邮箱时出现的发送后报错问题
4. 修复日志模块由于缺失默认gateway_name参数,在Qt层捕捉到全局异常时输出错误的问题
5. vnpy_rohon新增Linux安装脚本,解决动态库找不到的问题
6. vnpy_rqdata修复品种代码为小写合约的次主力88A2历史数据查询问题
# 4.0.0版本
## 新增
1. 新增面向机器学习多因子策略的vnpy.alpha模块
2. MultiCharts数据服务模块vnpy_mcdata
## 调整
1. 核心支持版本升级到Python 3.13
2. 使用pyproject.toml统一项目配置
3. 日志功能使用loguru替代logging
4. 使用mypy优化静态类型声明
5. 使用ruff优化代码细节质量
6. 使用uv作为开发环境管理工具
7. 升级扩展模块适配4.0版本:vnpy_ctp/vnpy_ctastrategy/vnpy_sqlite/vnpy_rqdata
## 修复
1. 修复PySide6中单元格排序可能出现的乱序问题
# 3.9.4版本
## 新增
1. vnpy_tora增加登录时终端动态密钥支持
2. vnpy_taos升级支持TDengine的3.0版本
## 调整
1. vnpy_xt行情接口增加实时行情中的涨跌停价字段
2. vnpy_taos移除不必要的时区转换提高性能
3. vnpy_dolphindb优化写入大量数据时候的内存占用
4. vnpy_portfoliostrategy简化回测引擎的calculate_pnl每日盈亏计算函数
5. vnpy_tap/vnpy_tts升级pybind11封装工具库的版本,支持Python 3.12编译
6. EmailEngine发送邮件失败后,捕捉异常并输出日志
## 修复
1. vnpy_optionmaster移除不必要的价格缓存代码
2. vnpy_dolphindb修复保存overview的时区不正确问题
# 3.9.3版本
## 新增
1. 利星资管交易接口vnpy_lstar
2. 咏春大师数据服务vnpy_voltrader
3. vnpy_rpcservice增加数据服务代理工具RpcDatafeed
## 调整
1. 适配6.3.0版本以上的PySide6模块:vnpy/vnpy_ctastrategy/vnpy_ctabacktester/vnpy_portfoliostrategy/vnpy_spreadtrading/vnpy_datamanager/vnpy_algotrading/vnpy_portfoliomananger/vnpy_optionmaster
2. vnpy_uft升级3.7.4.1004版本API
3. vnpy_ib的execDetails成交回报使用本地缓存的委托记录填充交易所,解决SMART交易所字段可能发生变化的问题
4. vnpy_ib的openOrder委托回报优先使用本地缓存的委托记录,解决交易所字段可能发生变化的问题
5. vnpy_ib的查询历史数据时,使用UTC时间戳传参
6. vnpy_ib的查询历史数据时,异步返回最长等待时间延长为600秒
7. vnpy_ib的增加期权链合约数据更新结束回报
8. vnpy_ib的合约乘数支持浮点数
9. 合约信息ContractData数据类,增加单笔最大委托数量max_volume
## 修复
1. 修复vnpy_spreadtrading回测引擎clear_data时,没有清空价差仓位的问题
2. 修复vnpy_ib查询历史数据失败时的日志输出错误
# 3.9.2版本
## 新增
1. vnpy_xt增加实时行情接口XtGateway
2. vnpy_xt增加基于文件锁实现的xtdc单例运行
3. vnpy_ib增加行情退订功能
4. vnpy_ib的合约乘数支持浮点数
5. vnpy_ib增加期权链合约数据更新结束回报
6. vnpy_ctabacktester、vnpy_ctastrategy、vnpy_portfoliostrategy增加i18n国际化支持
## 调整
1. vnpy_algotrading增加委托/成交推送时,对于算法状态的过滤
2. vnpy_tushare模块的to_ts_asset函数增加ETF基金支持
3. vnpy_xt更新适配xtquant的240613.1.1版本
4. vnpy_xt开启使用期货真实夜盘时间,增加期货历史数据集合竞价K线合成支持
5. vnpy_tts更新API版本到6.7.2
6. vnpy_rohon更新API版本:行情1.4.1.3,交易30.4.1.24
7. vnpy_tap完善API日志输出功能
8. vnpy_rest发送REST请求时,增加对于json参数的支持
9. vnpy_excelrtd优化PyXLL启动时加载模块的方式
10. vnpy_spreadtrading使用线程池实现策略初始化的异步执行
11. vnpy_ib移除期权合约的自动查询功能
12. vnpy_ib缓存查询返回的IB合约数据,简化行情切片查询函数
13. vnpy_ib查询历史数据时,使用UTC时间戳传参,并将最长等待时间延长为600秒
14. vnpy_ctastrategy的绩效统计值增加基于指数移动平均计算的EWM Sharpe比率
15. vnpy_ctastrategy回测引擎的show_chart函数直接返回图表对象
## 修复
1. 修复vnpy_rhon行情登录失败时的判断逻辑问题
2. 修复vnpy_datarecorder记录价差数据时缺失的localtime字段
3. 修复vnpy_spreadtraidng从datafeed加载数据时,时间戳传参缺失时区信息的问题
4. 修复vnpy_paperaccount委托数量为0撮合之后导致的ZeroDivisionError问题
5. 修复vnpy_portoliostrategy停止策略时,没有自动撤销策略委托的功能
# 3.9.1版本
## 新增
1. 增加i18n国际化支持,以及对应的英文翻译
2. 增加CFD和SWAP品种类型枚举值
3. vnpy_ib增加COMEX、Eurex交易所支持
4. vnpy_ib增加CFD品种支持
## 调整
1. vnpy_rqdata完善对于周五夜盘数据查询的支持
2. vnpy_ib订阅行情和委托下单时,检查代码字符串是否包含空格
3. vnpy_ib解析合约对象时,增加对于ConId是否包含非数字字符的检查
4. vnpy_ib查询历史K线数据,支持更长时间段跨度(不再限制半年)
5. vnpy_da更新API版本到1.18.2.0
6. vnpy_da移除历史数据查询功能
7. vnpy_tora调整期权接口的委托号生成规则,支持上限10万数量委托
8. vnpy_xtp调整账户冻结资金的计算逻辑
9. vnpy_optionmaster增加对IB的股票期权品种支持
10. vnpy_optionmaster定价模型改为计算理论希腊值
11. vnpy_optionmaster调整对象希腊值为理论模式
12. vnpy_optionmaster调整中值隐波动的计算方法
13. vnpy_spreadtrading使用线程池实现策略初始化的异步执行
14. vnpy_postgresql支持自动重用已经打开的数据库连接
15. vnpy_ctptest更新API版本至6.7.2
16. 接口封装升级更新pybind11到2.11.1版本:vnpy_ctptest、vnpy_sopttest
17. vnpy_ctp更新API版本到6.7.2
18. 调整extract_vt_symbol函数,兼容代码中带有"."的情况,如HHI.HK-HKD-FUT.HKFE
19. 更新vnpy框架的核心依赖模块到2024年较新的版本
## 修复
1. 修复vnpy_portfoliostrategy调用stop_strategy没有撤销活动委托的问题
2. 修复vnpy_xtp的API封装中queryTickersPriceInfo底层调用错误
3. 修复RpcClient中_last_received_ping变量的类型问题
# 3.9.0版本
## 新增
1. 迅投研数据服务vnpy_xt,支持股票、期货、期权、债券、基金历史数据获取
2. vnpy_ib增加对CBOE和CBOT交易所的支持、对指数期权的支持
3. vnpy_rqdata增加对于88A2连续次主力合约的支持
4. vnpy_wind增加广期所和上期能源交易所的数据支持
## 调整
1. vnpy_sopt升级3.7.0版本API
2. vnpy_portfoliostrategy回测引擎支持交易日参数annual_days
3. K线合成器(BarGenerator)移除对于Tick时间戳的检查过滤逻辑,交由用户层负责控制过滤
4. vnpy_ib收到期权合约数据后,自动查询其切片行情数据
5. vnpy_paperaccount实现对于IB接口合约的特殊路由处理
6. 接口封装升级更新pybind11到2.11.1版本:vnpy_ctp、vnpy_sopt、vnpy_tora
7. vnpy_ctp过滤不支持的委托状态推送
8. vnpy_mysql兼容无数据库写入权限情况下的数据表初始化
9. vnpy_chartwizard支持关闭单个图表标签页
10. vnpy_portfoliostrategy移除策略后同时清除对应的策略状态缓存数据
11. vnpy_portfoliostrategy调整每日盈亏清算对象开盘持仓数据的初始化方式
12. 策略模块遗传优化函数增加ngen_size和max_workers参数
## 修复
1. 修复vnpy_tora接口中的委托部分撤单状态映射缺失
2. 修复vnpy_wind查询日线历史数据时数值存在NaN的问题
3. 修复vnpy_mongodb的Tick汇总数据的条数统计错误
4. 修复vnpy_chartwizard对于升级后的vnpy_spreadtrading价差行情显示问题
5. 修复vnpy_ctastrategy回测成交记录为空时的报错
6. 修复vnpy_ctastrategy策略初始化时,历史数据重复推送调用on_bar的问题
# 3.8.0版本
## 新增
1. K线合成器(BarGenerator)增加对日K线的合成支持
2. 基于华鑫奇点柜台的C++ API重构vnpy_tora,实现VeighNa Station加载支持
3. 新增vnpy_ib对于期权合约查询、波动率和希腊值等扩展行情数据的支持
## 调整
1. vnpy_rest/vnpy_websocket限制在Windows上改为必须使用Selector事件循环
2. vnpy_rest/vnpy_websocket客户端关闭时确保所有会话结束,并等待有异步任务完成后安全退出
3. vnpy_ctp升级6.6.9版本API
4. vnpy_ctp支持大商所的1毫秒级别行情时间戳
5. vnpy_tqsdk过滤不支持的K线频率查询并输出日志
6. vnpy_datamanager增加数据频率下按交易所显示支持,优化数据加载显示速度
7. vnpy_ctabacktester如果加载的历史数据为空,则不执行后续回测
8. vnpy_spreadtrading采用轻量级数据结构,优化图形界面更新机制
9. vnpy_spreadtrading价差子引擎之间的事件推送,不再经过事件引擎,降低延迟水平
10. vnpy_rpcservice增加对下单返回委托号的gateway_name替换处理
11. vnpy_portfoliostrategy策略模板增加引擎类型查询函数get_engine_type
12. vnpy_sec更新行情API至1.6.45.0版本,更新交易API版本至1.6.88.18版本
13. vnpy_ib更新10.19.1版本的API,恢复对于数字格式代码(ConId)的支持
14. 没有配置数据服务或者加载模块失败的情况下,使用BaseDatafeed作为数据服务
15. 遗传优化算法运行时,子进程指定使用spawn方式启动,避免数据库连接对象异常
16. 合约管理控件,增加对于期权合约的特有数据字段显示
## 修复
1. 修复vnpy_datarecorder对于新版本vnpy_spreadtrading价差数据的录制支持
2. 修复vnpy_algotrading条件委托算法StopAlgo全部成交后状态更新可能缺失的问题
3. 修复vnpy_ctastrategy策略初始化时,历史数据重复推送调用on_bar的问题
4. 修复vnpy_wind查询日线历史数据时,数值存在NaN的问题
# 3.7.0版本
## 新增
1. 新增沪股通和深股通交易所枚举值
2. 增加vnpy_tap对于Linux系统的支持
3. 增加vnpy_rqdata对于新型主力合约数据支持(切换前一日收盘价比例复权)
## 调整
1. vnpy_ctastrategy/vnpy_ctabacktester加载策略类时,过滤TargetPosTemplate模板
2. vnpy_ctp连接登录过程中,只有在授权码错误的情况下,才禁止再次发起认证
3. vnpy_uft增加对广期所GFEX的支持
4. vnpy_tqsdk增加对于output日志输出功能的支持
5. vnpy_dolphindb允许指定用户自行配置具体的数据库实例
6. vnpy_rqdata优化对于郑商所期货和期权合约的查询代码转换规则
7. vnpy_rqdata增加对广期所GFEX的支持
8. vnpy_portfoliostrategy增加回测爆仓检查
9. vnpy_portfoliostrategy策略模板增加合约乘数查询函数get_size
10. vnpy_portfoliostrategy回测加载日线和小时线数据时,不使用分段加载
## 修复
1. 修复vnpy_rpcservice中,RPC接口对于推送数据的vt前缀相关字段错误问题
2. 修复vnpy_mini中,对于INE交易所今昨仓位的特殊处理
3. 修复vnpy_datamanager中,批量数据更新时缺失output函数的问题
4. 修复vnpy_spreadtrading中,回测加载数据时优先从数据服务获取历史数据的问题,改为优先从本地数据库加载
# 3.6.0版本
## 新增
1. 新增vnpy_ctp的Mac系统支持(M1/M2)
## 调整
1. BaseDatafeed的相关功能函数增加output入参用于输出日志
2. 修改相关数据服务模块适配output参数:vnpy_rqdata/vnpy_ifind/vnpy_wind/vnpy_tushare
3. 修改相关策略应用模块适配output参数:vnpy_ctastrategy/vnpy_ctabacktester/vnpy_portfoliostrategy/vnpy_spreadtrading/vnpy_datamanager
3. OffsetConverter增加对于SHFE/INE合约的锁仓模式支持
4. 在OmsEngine中添加全局的OffsetConverter功能,不再需要各AppEngine自行维护
5. 添加CTA策略模块在执行参数优化时的最大进程数量限制参数:vnpy_ctastrategy/vnpy_ctabacktester
6. 增加穷举优化算法运行过程中基于tqdm的进度条输出
7. 增加遗传优化算法运行过程中的迭代次数进度输出
8. 增加vnpy_optionmaster模块的期权产品对应标的合约的匹配函数,不再限制产品范围
9. 升级vnpy_tts的dll链接库,解决openctp升级导致的资金不显示的问题
10. 修改vnpy_ctastrategy使用vnpy.trader.database中统一定义的时区来加载数据
11. 增加vnpy_ctastrategy策略模板的合约乘数查询函数get_size
12. 增加vnpy_spreadtrading回测中统计绩效时对于爆仓情况的检查
13. 增加vnpy_scripttrader基于vt_symbol和direction查询持仓数据的函数
14. 修改vt_positionid的字符串内容,增加gateway_name前缀标识
## 修复
1. 修复异常捕捉钩子threading_excepthook的参数错误问题
2. 修复vnpy_ib获取历史数据时的异常失败问题
3. 修复vnpy_rest/vnpy_websocket中aiohttp的代理参数proxy传空时必须为None的问题
4. 修复vnpy_optionmaster模块的Greeks监控表行数设置不足的问题
5. 修复vnpy_rqdata查询股票期权数据报错的问题
6. 修复vnpy_rqdata中RqdataGateway获取期货指数和连续合约信息时错误的问题
7. 修复vnpy_portfoliostrategy中,从缓存文件恢复数据,导致defaultdict变成dict的问题
# 3.5.0版本
## 新增
1. 新增基于米筐RQData的跨市场行情数据接口RqdataGateway
2. 新增东方财富证券EMT柜台交易接口vnpy_emt
## 调整
1. 调整vnpy_algotrading模块设计(模板、引擎),只支持单合约算法执行交易
2. 优化vnpy_algotrading的算法状态控制,增加状态枚举值,算法支持暂停和恢复运行
3. 升级vnpy_hft接口支持HFT国君统一交易网关的2.0版本API
4. 优化vnpy_portfoliostrategy的策略模板,支持持仓目标调仓交易模式
## 修复
1. 修复后台线程异常捕捉钩子函数,对于Python 3.7的语法兼容性问题
2. 修复vnpy_mysql加载历史数据时存在时段重复的问题
3. 修复vnpy_ib由于TWS客户端升级导致的委托失败问题
4. 修复vnpy_rest/vnpy_websocket对Python 3.10后asyncio的支持
5. 修复vnpy_sopt由于流控导致的委托失败时,返回【提交中】状态委托的问题
# 3.4.0版本
## 新增
1. 新增杰宜斯资管系统交易接口vnpy_jees
## 调整
1. 开启vnpy.rpc的pyzmq连接keepalive机制,避免在复杂网络环境下闲置连接的断开
2. 移除vnpy_rpcservice中服务端的EVENT_TIMER定时事件推送
3. 调整vnpy_postgresql采用批量方式写入数据,提高效率
4. 添加VeighNa Trader中的子线程异常捕捉(需要Python>=3.8)
5. 调整vnpy_ib接口查询历史K线数据时,对外汇和贵金属均采用中间价(而非成交价)
6. 增加vnpy_ctastrategy对于回测过程中资金爆仓(小于等于0)情况的检查
7. 优化vnpy_webtrader模块的加密鉴权,支持web进程关闭重启
## 修复
1. 修复vnpy.rpc模块对于23.0以上版本pyzmq的NOBLOCK兼容性问题
2. 修复vnpy_taos由于TDengine版本升级,出现d的一系列兼容问题
3. 修复vnpy_datamanager刷新数据汇总信息显示时,老数据点移除失败的问题
# 3.3.0版本
## 新增
1. 新增数据库组件vnpy.trader.database中的TickOverview对象
2. 新增掘金仿真环境交易接口vnpy_gm
3. BaseData基础数据类型增加extra字段(字典类型),用于传送任意相关数据
## 调整
1. 使用Python内置的zoneinfo库替换三方的pytz库
2. 调整相关交易接口、数据服务接口、数据库适配器、应用模块,使用新的ZoneInfo对象来标识时区信息
3. 数据库适配器接口vnpy.trader.database写入数据时,新增流式写入参数stream,提高行情录制性能
# 3.2.0版本
## 新增
1. 添加广州期货交易所枚举值字段GFEX
2. 新增CTP期权(ETF)穿透式测试接口vnpy_sopttest
3. 新增Currency.CAD(加元)枚举值
4. 新增Exchange.TSE(多伦多交易所)和Exchange.AMEX(美洲交易所)枚举值
5. 新增vnpy_taos,涛思数据TDengine时序数据库适配器
5. 新增vnpy_timescaledb,TimescaleDB时序数据库适配器
## 调整
1. 更新vnpy_ctp/vnpy_ctptest支持广州期货交易所
2. 更新vnpy_tora的现货API接口到最新版本:API_Python3.7_交易_v4.0.3_20220222
3. 更新vnpy_tora的期权API接口到最新版本:API_Python3.7_v1.3.2_20211201
4. 更新vnpy_esunny/vnpy_tap添加关闭接口时对于API退出函数的调用
5. 移除vnpy_ctastrategy/vnpy_ctabacktester/vnpy_optionmaster的反向合约支持
6. 增加vnpy_ib对于沪股通、深股通、多伦多交易所、美洲交易所的支持
7. 增加vnpy_ib对于指数行情数据的支持
8. 添加vnpy_ctastrategy策略交易管理界面的策略实例查找功能
## 修复
1. 修复vnpy_mongodb中K线数据量统计的问题(使用新的count_documents函数)
2. 修复由于PySide6对象销毁先于__del__调用,导致的BaseMonitor衍生组件无法自动保存界面状态的问题
# 3.1.0版本
## 新增
1. 新增恒生云UF2.0证券仿真环境交易接口vnpy_uf
2. 新增火象投教仿真环境交易接口vnpy_hx
## 调整
1. 升级tzlocal库的版本到4.2,消除get_localzone()函数的warning
2. 完善代码中函数和变量类型提示
3. 使用QtCore.Signal代替老的QtCore.pyqtSignal
4. 优化vnpy_rohon接口的委托成交相关细节功能
5. 更新vnpy_xtp到2.2.32.2.0版本XTP API,支持上交所新债系统
6. 优化vnpy_mongodb的数据写入速度,基于pymongo 4.0版本的批量写入功能
7. 增加vnpy_ctp对于委托函数返回值为非0(请求发送失败)状态的处理
8. 对vnpy_ctastrategy和vnpy_ctabacktester的策略模板下拉框中内容,改为基于首字母排序
## 修复
1. 修复vnpy_optionmaster模块希腊值监控组件的数据刷新问题
2. 修复vnpy_mongodb由于时间戳的时区信息确实,导致的数据加载范围问题
3. 修复vnpy_tts的sdist源代码打包缺失lib文件的问题
4. 修复vnpy_rqdata由于查询返回数据为NaN导致的解析问题
# 3.0.0版本
## 调整
1. 移除api、gateway、app子模块的目录
2. 移除requirements.txt对于插件的默认依赖
3. 简化重构rpc子模块,定位于可靠环境下跨进程通讯(本机、局域网)
4. 移除rpc子模块对于鉴权的支持
5. 调整rpc子模块中的心跳机制的实现方式
6. 移除基于QScintilla开发的代码编辑器,改用VSCode打开代码
7. 优化MainWindow主窗口中,对于QAction按钮图标的加载逻辑
8. MainEngine添加交易接口时,支持自定义接口名称
## 修复
1. 使用非原生窗口菜单栏,修复Linux/Mac下【配置】按钮不显示的问题
# 2.9.0版本
## 新增
1. 新增顶点HTS柜台交易接口vnpy_hts
## 调整
1. 移除恒生期权hsoption接口
2. vnpy_webtrader增加对于自定义监听地址和端口的支持
3. vnpy_mongodb锁定pymongo的依赖版本为3.12.3
4. vnpy_udata安装脚本中添加hs_udata库的依赖
5. vnpy_uft升级使用3.7.2.4版本的恒生API接口
## 剥离
2. 将国泰君安证券统一接入网关交易接口剥离到vnpy_hft项目中
3. 将顶点飞创交易接口剥离到vnpy_sec项目中
4. 将RPC服务和接口剥离到vnpy_rpcservice项目中
## 修复
1. 修复vnpy_tora撤单时,由于撤单编号和委托编号冲突导致的撤单失败问题
2. 修复vnpy_tora股票委托状态中【未成交】状态的错误映射问题
3. 修复vnpy_ctabacktester中,回测开始日期编辑框的数据缓存问题
4. 修复vnpy_udata中,分段下载数据时,可能进入死循环的问题
5. 修复vnpy_udata中,修复下载的数据量为空时,出现的异常报错问题
6. 修复vnpy_dolphindb中,合约名带有符号时数据无法读取问题
# 2.8.0版本
## 新增
1. 新增东证OST柜台交易接口vnpy_ost
2. 增加投资组合策略模块的策略参数优化功能
## 修复
1. 修复部分C++接口模块剥离后,遗留的安装脚本编译代码导致的报错问题
2. 修复vnpy_xtp订阅深交所行情后,可能出现的闪退问题
3. 修复vnpy_tushare部分数据字段为None时,导致的数据错误
4. 修复vnpy_mini,在夜盘换日时上期所行情时间戳的日期字段误差问题
5. 修复vnpy_uft的ETF期权合约信息解析缺失的问题
6. 修复vnpy_wind下载数据存在缺失时的N/A解析问题
7. 修复vnpy_webtrader的html静态文件缺失的问题
8. 修复vnpy_dolphindb存储Tick数据时的数据类型问题
9. 修复vnpy_dolphindb读取数据为空时的BUG
10. 修复vnpy_esunny查询黄金TD合约的合约乘数为0的问题
11. 修复vnpy_ctastrategy策略初始化读取布尔值false失败的问题
12. 修复vnpy_rohon的期权合约字段赋值错误的问题
13. 修复vnpy_leveldb的Linux安装依赖库问题
## 调整
1. 移除老版本基于requests库的RestClient客户端
2. 移除老版本基于websocket-client库的WebsocketClient客户端
3. vnpy_tts增加对上交所和深交所股票模拟交易的支持
4. 移除vnpy_ctp的期权询价指令支持
5. 增加vnpy_ctp的授权码验证失败后,避免重复操作的功能
6. 优化vnpy_uft的断线重连行情订阅逻辑
7. 增加vnpy_arctic对于用户名和密码的鉴权功能
8. 增加vnpy_mini对于股指期权的支持
## 剥离
1. 将华鑫奇点交易接口剥离到vnpy_tora项目中,并升级到4.0版本
2. 将飞马交易接口剥离到vnpy_femas项目中
3. 将金仕达黄金接口剥离到vnpy_ksgold项目中
4. 将投资组合策略模块剥离到vnpy_portfoliostrategy项目中
5. 将Excel RTD模块剥离到vnpy_excelrtd项目中
6. 将本地仿真模拟交易模块剥离到vnpy_paperaccount项目中
# 2.7.0版本
## 新增
1. 新增天软数据服务项目vnpy_tinysoft
2. 新增同花顺iFinD数据服务项目vnpy_ifind
3. 新增dYdx交易接口vnpy_dydx
4. 新增万得Wind数据服务项目vnpy_wind
5. 新增PortfolioStrategy专用的PortfolioBarGenerator
## 调整
1. 移除KasiaGateway
4. 移除MarketRadarApp
5. 算法交易模块中移除套利和网格两个非执行类算法
6. vnpy_tushare数据服务,增加持仓量和成交额字段
8. vnpy_datamanager数据管理器,查询的K线信息按合约代码排序显示
13. vnpy_dolphindb优化数据的加载解析速度
14. vnpy_influxdb采用pandas解析CSV数据,提高整体速度
## 修复
1. 修复vnpy_ctp的CtpGateway,在夜盘换日时上期所行情时间戳的日期字段误差问题
2. 修复vnpy_arctic的数据重复写入时出现的错误覆盖问题
## 剥离
1. 将InteractiveBrokers交易接口剥离到vnpy_ib项目中
2. 将飞鼠交易接口剥离到vnpy_sgit项目中
3. 将易盛外盘交易接口剥离到vnpy_tap项目中
4. 将直达期货交易接口剥离到vnpy_da项目中
5. 将算法交易模块剥离到vnpy_algotrading项目中
6. 将脚本交易模块剥离到vnpy_scripttrader项目中
7. 将交易组合管理模块剥离到vnpy_portfoliomanager项目中
# 2.6.0版本
## 新增
1. 增加双边报价业务的发送和撤销函数功能
2. 增加双边报价监控UI组件
3. 增加用于对接数据库的抽象接口vnpy.trader.database
4. 新增基于Arctic的MongoDB数据库接口项目vnpy_arctic
5. 新增LevelDB数据库接口项目vnpy_leveldb
6. 新增DolphinDB数据库接口项目vnpy_dolphindb
7. 增加用于对接数据服务的抽象接口vnpy.trader.datafeed
8. 新增TuShare数据服务项目vnpy_tushare
8. 新增恒生UData数据服务项目vnpy_udata
8. 新增天勤TQSDK数据服务项目vnpy_tqsdk
8. 新增CoinAPI数据服务项目vnpy_coinapi
## 调整
1. 移除批量委托和批量撤单相关的函数功能
2. 移除老虎证券交易接口TigerGateway
3. 移除鑫管家交易接口XgjGateway
4. 移除AlgoTrading算法交易模块对于金纳算法服务的支持
5. RestClient增加对操作系统代理配置的支持
6. RestClient和WebsocketClient的默认异常处理逻辑由抛出异常修改为打印输出
7. 价差交易模块移除对反向合约、线性价差、开平字段的支持
8. 价差交易模块优化对灵活价差的支持,优化价差行情推送过滤判断
9. 价差交易算法停止时,等待全部委托结束、各条腿平衡后,再结束算法
## 修复
1. 修复在Linux/Mac系统上,运行多进程优化时的进程启动错误
2. 修复WebsocketClient由于心跳机制不完善,导致的频繁断线问题
## 剥离
1. 将米筐数据接口剥离到vnpy_rqdata项目中,并升级到2.9.38版本
2. 将行情录制模块剥离到vnpy_datarecorder项目中
3. 将K线图表模块剥离到vnpy_chartwizard项目中
4. 将SQLite数据库接口剥离到vnpy_sqlite项目中
5. 将MySQL数据库接口剥离到vnpy_mysql项目中
6. 将PostgreSQL数据库接口剥离到vnpy_postgresql项目中
7. 将MongoDB数据库接口剥离到vnpy_mongodb项目中
8. 将InfluxDB数据库接口剥离到vnpy_influxdb项目中
13. 将期权波动率交易模块剥离到vnpy_optionmaster项目中
# 2.5.0版本
## 新增
1. 新增TTS交易系统(兼容CTP的仿真交易环境)的接口vnpy_tts(6.5.1)
2. 新增易盛启明星/北斗星兼容交易API的接口vnpy_esunny(1.0.2.2)
3. 新增BarData和TickData的成交额turnover字段
## 调整
1. 将SpreadTrading模块策略初始化时的K线价差数据加载,改为优先通过RQData查询数据
2. 在MainWindow的AboutDialog中,基于importlib_metadata模块来获取版本信息
3. 隐藏所有对话框右上角的【?】按钮
4. 将易盛外盘TapGateway的合约信息,从行情接口获取改为交易接口获取(避免外盘合约size为0的问题)
5. 改进VeighNa Trader的异常捕捉对话框弹出方式,避免多次重复报错情况下的程序卡死崩溃
## 修复
1. 修复Linux下安装时,对于已经剥离的XTP API的自动编译操作
2. 修复PortfolioManager的UI组件,对于成交事件监听类型错误的BUG
3. 修复vnpy_rest下的Response对象缺乏text字段导致的BUG
4. 修复RestClient,代理端口信息传空时,导致底层连接出错的BUG
6. 修复ArrayManager的Aroon指标计算输出结果顺序错误的BUG
7. 修复数据库管理器读写TickData时,由于缺少对localtime字段处理导致的BUG
## 剥离
1. 将融航接口剥离到vnpy_rohon项目中,并升级到6.5.1版本
2. 将CTP MINI接口剥离到vnpy_mini项目中,并升级到1.5.6版本
3. 将CTP期权接口剥离到vnpy_sopt项目中
4. 将恒生UFT柜台极速API接口剥离到vnpy_uft项目中
# 2.4.0版本
## 新增
1. 新增TickData的本地时间戳字段local_time(不带时区信息)
2. 新增基于asyncio和aiohttp实现的协程异步REST API客户端vnpy_rest项目
3. 新增基于asyncio和aiohttp实现的协程异步Websocket API客户端vnpy_websocket项目
4. 新增基于多进程模式的遗传算法优化功能
5. 新增XTP的API封装中,行情登录函数对于本地网卡地址的参数支持
## 调整
2. 剥离CTA策略模块下的穷举和遗传优化算法到vnpy.trader.optimize模块下
3. 遗传算法优化完成后,输出所有回测过的参数对应结果(而不只是最优结果)
4. CTA策略引擎加载策略文件时,增加模块重载的操作,使得任何策略文件修改可以立即生效
5. CTA策略引擎扫描特定目录下的策略文件时,使用glob函数(替换原有的os.walk),避免对子目录中文件的错误加载
6. 将CTA策略模块剥离到vnpy_ctastrategy项目中
7. 将CTA回测模块剥离到vnpy_ctabacktester项目中
8. 将XTP接口剥离到vnpy_xtp项目中,并升级到2.2.27.4版本
9. 将事前风控模块剥离到vnpy_riskmanager项目中
10. 将数据管理模块剥离到vnpy_datamanager项目中
## 修复
2. 修复MySQL和PostgreSQL数据库管理器删除K线数据时出错的问题
3. 修复基于aiohttp的RestClient和WebsocketClient,事件循环停止后重新启动失败的问题
7. 修复CtaBacktester基于Tick级别数据进行参数优化时,启动优化失败的问题
8. 修复ToraStockGateway和ToraOptionGateway,调用下单函数时没有返回委托号的问题
9. 修复InfluxDB数据管理器,导入数据时时间字段解析错误的问题
# 2.3.0版本
## 修复
1. 修复IbGateway断线重连后,没有自动订阅之前已订阅的合约行情问题
2. 修复CTA模块的净仓交易模式中,部分平仓部分开仓时,开仓部分下单错误的问题
6. 修复CtpGateway对于FAK和FOK委托指令的处理错误问题
10. 修复IbGateway,查询历史数据由于传参错误导致的查询失败问题
11. 修复IbGateway,当要查询的合约历史数据不存在时卡死的问题
12. 修复IbGateway,查询返回的合约乘数(字符串)未作转换导致的上层应用问题
14. 修复BarGenerator,在合成小时K线时部分情况下遗漏分钟K线收盘价更新的问题
15. 修复UftGateway,在连接ETF期权服务器时无法订阅行情的问题
16. 修复UftGateway,在连接ETF期权服务器时,对于包含毫秒的委托时间戳处理错误的问题
## 调整
1. 修改CTA模块的净仓交易模式,支持上期所和能交所的今昨仓拆分下单
2. 调整组合策略模块的回测引擎K线回放逻辑,当某个时间点K线数据缺失时,推送给策略的K线字典中不对其进行向前补齐
3. 将CTP接口和API封装,剥离到vnpy_ctp项目中
4. 将CTP穿透式测试接口和API封装,剥离到vnpy_ctptest项目中
## 新增
1. 新增DataManager在导入CSV文件时,对于时间戳时区的选择功能
2. 新增CtaStrategy模块的策略移仓助手功能,实现一键式期货换月移仓支持
# 2.2.0版本
## 修复
1. 修复DataManager查询数据库中K线数据范围时,开始和结束日期相反的问题
6. 修复PostgreSQL数据库对接层中,save_tick_data函数由于访问interval导致保存出错的问题
7. 修复DataRecorder模块中add_bar_recording下保存录制用合约配置错误的问题
8. 修复PostgreSQL数据库对接层中,由于事务执行失败导致的后续报错问题,创建数据库对象时设置自动回滚模式(autorollback=True)
9. 修复DataManager自动更新数据时,查询数据范围由于调用老版本函数导致的错误
10. 修复RQData下载获取的历史数据浮点数精度问题
11. 修复BarGenerator在合成N小时K线时,收盘价、成交量、持仓量字段缺失的问题
12. 修复K线图表底层组件ChartWidget当绘制数据较少时,坐标轴时间点显示重复的问题
13. 修复SpreadTrading模块生成的价差盘口数据的时区信息缺失问题
14. 修复IbGateway的现货贵金属行情数据缺失最新价和时间戳的问题
15. 修复BarGenerator在合成小时级别K线时,成交量字段部分缺失的问题
16. 修复vnpy.rpc模块启用非对称加密后无法正常退出的问题
## 调整
1. 修改vnpy.chart下ChartItem为按需绘制,大幅缩短图表第一次显示出来的耗时
2. 修改IbGateway的历史数据查询功能,包括所有可用时间(即欧美晚上的电子交易时段)
3. 修改DataRecorder的数据入库为定时批量写入,提高录制大量合约数据时的写入性能
## 新增
1. 新增IbGateway连接断开后的自动重连功能(每10秒检查)
2. 新增双边报价业务相关的底层数据结构和功能函数
3. 新增开平转换器OffsetConverter的净仓交易模式
4. 新增CtaStrategy模块策略模板的委托时的净仓交易可选参数
5. 新增CtaStrategy模块回测引擎中的全年交易日可选参数
6. 新增ChartWizard模块对于价差行情图表的显示支持
7. 新增MarketRadar模块的雷达信号条件提醒功能
# 2.1.9.1版本
## 修复
1. 修复RestClient中,因为pyopenssl.extract_from_urllib3引起的兼容性问题
## 调整
1. 调整OptionMaster模块中,期权链数据结构搜索平值行权价的算法,不再依赖标的物合约
## 新增
1. 新增OptionMaster模块使用合成期货作为定价标的合约的功能
# 2.1.9版本
## 修复
1. 修复BarGenerator的小时线合成时,出现同一个小时的K线重复推送两次的问题
2. 修复遗传算法优化时,因为lru_cache缓存导致的新一轮优化结果不变的问题
3. 修复RestClient发起请求时,由于requests库底层使用OpenSSL导致的WinError 10054 WSAECONNRESET的问题
5. 修复程序中频繁捕捉到异常时,异常捕捉对话框反复执行导致卡死的问题
7. 修复活动委托监控组件ActiveOrderMonitor,保存CSV时会将所有委托数据一起保存的问题
8. 修复XtpGateway重复发起登录操作时,出现的系统崩溃问题
9. 修复XtpGateway的股票市价委托类型映射错误问题
## 调整
1. 对XTP接口的行情价格数据基于合约最小价格跳动进行取整,资金保留2位小数
2. BaseMonitor保存CSV文件时,表头改为图形界面显示的中文(之前是数据的字段名英文)
3. 初始化TWAP算法时,对每轮委托数量取整到合约最小交易数量
4. 将原vnpy.trader.database中的数据库客户端拆分到独立的vnpy.database模块下
5. 对SQLite/MySQL/PostgreSQL/MongoDB/InfluxDB客户端进行代码重构优化,增加K线数据整体情况BarOverview查询功能
## 新增
1. 新增BaseMonitor数据监控UI组件(以及其子类),自动保存列宽的功能
2. 增加华鑫奇点ToraGateway对于FENS服务器连接和资金账户登录的支持,之前只支持前置机连接和用户代码登录
4. 增加InfluxDB数据库客户端vnpy.database.influx对于Tick数据储存和加载的支持
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015-present, Xiaoyou Chen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# VeighNa - By Traders, For Traders, AI-Powered.
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/veighna-logo.png"/>
</p>
💬 Want to read this in **english** ? Go [**here**](README_ENG.md)
<p align="center">
<img src ="https://img.shields.io/badge/version-4.3.0-blueviolet.svg"/>
<img src ="https://img.shields.io/badge/platform-windows|linux|macos-yellow.svg"/>
<img src ="https://img.shields.io/badge/python-3.10|3.11|3.12|3.13-blue.svg" />
<img src ="https://img.shields.io/github/actions/workflow/status/vnpy/vnpy/pythonapp.yml?branch=master"/>
<img src ="https://img.shields.io/github/license/vnpy/vnpy.svg?color=orange"/>
</p>
VeighNa是一套基于Python的开源量化交易系统开发框架,在开源社区持续不断的贡献下一步步成长为多功能量化交易平台,自发布以来已经积累了众多来自金融机构或相关领域的用户,包括私募基金、证券公司、期货公司等。
在使用VeighNa进行二次开发(策略、模块等)的过程中有任何疑问,请查看[**VeighNa项目文档**](https://www.vnpy.com/docs/cn/index.html),如果无法解决请前往[**官方社区论坛**](https://www.vnpy.com/forum/)的【提问求助】板块寻求帮助,也欢迎在【经验分享】板块分享你的使用心得!
**想要获取更多关于VeighNa的资讯信息?** 请扫描下方二维码添加小助手加入【VeighNa社区交流微信群】:
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/github_wx.png"/, width=250>
</p>
## AI-Powered
VeighNa发布十周年之际正式推出4.0版本,重磅新增面向AI量化策略的[vnpy.alpha](./vnpy/alpha)模块,为专业量化交易员提供**一站式多因子机器学习(ML)策略开发、投研和实盘交易解决方案**:
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/alpha_demo.jpg"/, width=500>
</p>
* :bar_chart: **[dataset](./vnpy/alpha/dataset)**:因子特征工程
* 专为ML算法训练优化设计,支持高效批量特征计算与处理
* 内置丰富的因子特征表达式计算引擎,实现快速一键生成训练数据
* [Alpha 158](./vnpy/alpha/dataset/datasets/alpha_158.py):源于微软Qlib项目的股票市场特征集合,涵盖K线形态、价格趋势、时序波动等多维度量化因子
* :bulb: **[model](./vnpy/alpha/model)**:预测模型训练
* 提供标准化的ML模型开发模板,大幅简化模型构建与训练流程
* 统一API接口设计,支持无缝切换不同算法进行性能对比测试
* 集成多种主流机器学习算法:
* [Lasso](./vnpy/alpha/model/models/lasso_model.py):经典Lasso回归模型,通过L1正则化实现特征选择
* [LightGBM](./vnpy/alpha/model/models/lgb_model.py):高效梯度提升决策树,针对大规模数据集优化的训练引擎
* [MLP](./vnpy/alpha/model/models/mlp_model.py):多层感知机神经网络,适用于复杂非线性关系建模
* :robot: **[strategy](./vnpy/alpha/strategy)**:策略投研开发
* 基于ML信号预测模型快速构建量化交易策略
* 支持截面多标的和时序单标的两种策略类型
* :microscope: **[lab](./vnpy/alpha/lab.py)**:投研流程管理
* 集成数据管理、模型训练、信号生成和策略回测等完整工作流程
* 简洁API设计,内置可视化分析工具,直观评估策略表现和模型效果
* :book: **[notebook](./examples/alpha_research)**:量化投研Demo
* [download_data_rq](./examples/alpha_research/download_data_rq.ipynb):基于RQData下载A股指数成分股数据,包含指数成分变化跟踪及历史行情获取
* [download_data_xt](./examples/alpha_research/download_data_xt.ipynb):基于迅投研数据服务,下载获取A股指数成分历史变化和股票K线数据
* [research_workflow_lasso](./examples/alpha_research/research_workflow_lasso.ipynb):基于Lasso回归模型的量化投研工作流,展示线性模型特征选择与预测能力
* [research_workflow_lgb](./examples/alpha_research/research_workflow_lgb.ipynb):基于LightGBM梯度提升树的量化投研工作流,利用高效集成学习方法进行预测
* [research_workflow_mlp](./examples/alpha_research/research_workflow_mlp.ipynb):基于多层感知机神经网络的量化投研工作流,展示深度学习在量化交易中的应用
vnpy.alpha模块的设计理念受到[Qlib](https://github.com/microsoft/qlib)项目的启发,在保持易用性的同时提供强大的AI量化能力,特此向Qlib开发团队致以诚挚感谢!
## 功能特点
带有 :arrow_up: 的模块代表已经完成4.0版本的升级适配测试,同时4.0核心框架采用了优先保证兼容性的升级方式,因此大多数模块也都可以直接使用(涉及到C++ API封装的接口必须升级后才能使用)。
1. :arrow_up: 多功能量化交易平台(trader),整合了多种交易接口,并针对具体策略算法和功能开发提供了简洁易用的API,用于快速构建交易员所需的量化交易应用。
2. 覆盖国内外所拥有的下述交易品种的交易接口(gateway):
* 国内市场
* :arrow_up: CTP([ctp](https://www.github.com/vnpy/vnpy_ctp)):国内期货、期权
* :arrow_up: CTP Mini([mini](https://www.github.com/vnpy/vnpy_mini)):国内期货、期权
* :arrow_up: CTP证券([sopt](https://www.github.com/vnpy/vnpy_sopt)):ETF期权
* :arrow_up: 飞马([femas](https://www.github.com/vnpy/vnpy_femas)):国内期货
* :arrow_up: 恒生UFT([uft](https://www.github.com/vnpy/vnpy_uft)):国内期货、ETF期权
* :arrow_up: 易盛([esunny](https://www.github.com/vnpy/vnpy_esunny)):国内期货、黄金TD
* :arrow_up: 顶点HTS([hts](https://www.github.com/vnpy/vnpy_hts)):ETF期权
* :arrow_up: 顶点飞创([sec](https://www.github.com/vnpy/vnpy_sec)):ETF期权
* :arrow_up: 中泰XTP([xtp](https://www.github.com/vnpy/vnpy_xtp)):国内证券(A股)、ETF期权
* :arrow_up: 华鑫奇点([tora](https://www.github.com/vnpy/vnpy_tora)):国内证券(A股)、ETF期权
* 东证OST([ost](https://www.github.com/vnpy/vnpy_ost)):国内证券(A股)
* 东方财富EMT([emt](https://www.github.com/vnpy/vnpy_emt)):国内证券(A股)
* 飞鼠([sgit](https://www.github.com/vnpy/vnpy_sgit)):黄金TD、国内期货
* :arrow_up: 金仕达黄金([ksgold](https://www.github.com/vnpy/vnpy_ksgold)):黄金TD
* :arrow_up: 利星资管([lstar](https://www.github.com/vnpy/vnpy_lstar)):期货资管
* :arrow_up: 融航([rohon](https://www.github.com/vnpy/vnpy_rohon)):期货资管
* :arrow_up: 杰宜斯([jees](https://www.github.com/vnpy/vnpy_jees)):期货资管
* 中汇亿达([comstar](https://www.github.com/vnpy/vnpy_comstar)):银行间市场
* :arrow_up: TTS([tts](https://www.github.com/vnpy/vnpy_tts)):国内期货(仿真)
* 海外市场
* :arrow_up: Interactive Brokers([ib](https://www.github.com/vnpy/vnpy_ib)):海外证券、期货、期权、贵金属等
* :arrow_up: 易盛9.0外盘([tap](https://www.github.com/vnpy/vnpy_tap)):海外期货
* :arrow_up: 直达期货([da](https://www.github.com/vnpy/vnpy_da)):海外期货
* 特殊应用
* :arrow_up: RQData行情([rqdata](https://www.github.com/vnpy/vnpy_rqdata)):跨市场(股票、指数、ETF、期货)实时行情
* :arrow_up: 迅投研行情([xt](https://www.github.com/vnpy/vnpy_xt)):跨市场(股票、指数、可转债、ETF、期货、期权)实时行情
* :arrow_up: RPC服务([rpc](https://www.github.com/vnpy/vnpy_rpcservice)):跨进程通讯接口,用于分布式架构
3. 覆盖下述各类量化策略的交易应用(app):
* :arrow_up: [cta_strategy](https://www.github.com/vnpy/vnpy_ctastrategy):CTA策略引擎模块,在保持易用性的同时,允许用户针对CTA类策略运行过程中委托的报撤行为进行细粒度控制(降低交易滑点、实现高频策略)
* :arrow_up: [cta_backtester](https://www.github.com/vnpy/vnpy_ctabacktester):CTA策略回测模块,无需使用Jupyter Notebook,直接使用图形界面进行策略回测分析、参数优化等相关工作
* :arrow_up: [spread_trading](https://www.github.com/vnpy/vnpy_spreadtrading):价差交易模块,支持自定义价差,实时计算价差行情和持仓,支持价差算法交易以及自动价差策略两种模式
* :arrow_up: [option_master](https://www.github.com/vnpy/vnpy_optionmaster):期权交易模块,针对国内期权市场设计,支持多种期权定价模型、隐含波动率曲面计算、希腊值风险跟踪等功能
* :arrow_up: [portfolio_strategy](https://www.github.com/vnpy/vnpy_portfoliostrategy):组合策略模块,面向同时交易多合约的量化策略(Alpha、期权套利等),提供历史数据回测和实盘自动交易功能
* :arrow_up: [algo_trading](https://www.github.com/vnpy/vnpy_algotrading):算法交易模块,提供多种常用的智能交易算法:TWAP、Sniper、Iceberg、BestLimit等
* :arrow_up: [script_trader](https://www.github.com/vnpy/vnpy_scripttrader):脚本策略模块,面向多标的类量化策略和计算任务设计,同时也可以在命令行中实现REPL指令形式的交易,不支持回测功能
* :arrow_up: [paper_account](https://www.github.com/vnpy/vnpy_paperaccount):本地仿真模块,纯本地化实现的仿真模拟交易功能,基于交易接口获取的实时行情进行委托撮合,提供委托成交推送以及持仓记录
* :arrow_up: [chart_wizard](https://www.github.com/vnpy/vnpy_chartwizard):K线图表模块,基于RQData数据服务(期货)或者交易接口获取历史数据,并结合Tick推送显示实时行情变化
* :arrow_up: [portfolio_manager](https://www.github.com/vnpy/vnpy_portfoliomanager):交易组合管理模块,以独立的策略交易组合(子账户)为基础,提供委托成交记录管理、交易仓位自动跟踪以及每日盈亏实时统计功能
* :arrow_up: [rpc_service](https://www.github.com/vnpy/vnpy_rpcservice):RPC服务模块,允许将某一进程启动为服务端,作为统一的行情和交易路由通道,允许多客户端同时连接,实现多进程分布式系统
* :arrow_up: [data_manager](https://www.github.com/vnpy/vnpy_datamanager):历史数据管理模块,通过树形目录查看数据库中已有的数据概况,选择任意时间段数据查看字段细节,支持CSV文件的数据导入和导出
* :arrow_up: [data_recorder](https://www.github.com/vnpy/vnpy_datarecorder):行情记录模块,基于图形界面进行配置,根据需求实时录制Tick或者K线行情到数据库中,用于策略回测或者实盘初始化
* :arrow_up: [excel_rtd](https://www.github.com/vnpy/vnpy_excelrtd):Excel RTD(Real Time Data)实时数据服务,基于pyxll模块实现在Excel中获取各类数据(行情、合约、持仓等)的实时推送更新
* :arrow_up: [risk_manager](https://www.github.com/vnpy/vnpy_riskmanager):风险管理模块,提供包括交易流控、下单数量、活动委托、撤单总数等规则的统计和限制,有效实现前端风控功能
* :arrow_up: [web_trader](https://www.github.com/vnpy/vnpy_webtrader):Web服务模块,针对B-S架构需求设计,实现了提供主动函数调用(REST)和被动数据推送(Websocket)的Web服务器
4. Python交易API接口封装(api),提供上述交易接口的底层对接实现。
* :arrow_up: REST Client([rest](https://www.github.com/vnpy/vnpy_rest)):基于协程异步IO的高性能REST API客户端,采用事件消息循环的编程模型,支持高并发实时交易请求发送
* :arrow_up: Websocket Client([websocket](https://www.github.com/vnpy/vnpy_websocket)):基于协程异步IO的高性能Websocket API客户端,支持和REST Client共用事件循环并发运行
5. :arrow_up: 简洁易用的事件驱动引擎(event),作为事件驱动型交易程序的核心。
6. 对接各类数据库的适配器接口(database):
* SQL类
* :arrow_up: SQLite([sqlite](https://www.github.com/vnpy/vnpy_sqlite)):轻量级单文件数据库,无需安装和配置数据服务程序,VeighNa的默认选项,适合入门新手用户
* :arrow_up: MySQL([mysql](https://www.github.com/vnpy/vnpy_mysql)):主流的开源关系型数据库,文档资料极为丰富,且可替换其他NewSQL兼容实现(如TiDB)
* :arrow_up: PostgreSQL([postgresql](https://www.github.com/vnpy/vnpy_postgresql)):特性更为丰富的开源关系型数据库,支持通过扩展插件来新增功能,只推荐熟手使用
* NoSQL类
* DolphinDB([dolphindb](https://www.github.com/vnpy/vnpy_dolphindb)):一款高性能分布式时序数据库,适用于对速度要求极高的低延时或实时性任务
* :arrow_up: TDengine([taos](https://www.github.com/vnpy/vnpy_taos)):分布式、高性能、支持SQL的时序数据库,带有内建的缓存、流式计算、数据订阅等系统功能,能大幅减少研发和运维的复杂度
* :arrow_up: MongoDB([mongodb](https://www.github.com/vnpy/vnpy_mongodb)):基于分布式文件储存(bson格式)的文档式数据库,内置的热数据内存缓存提供更快读写速度
7. 对接下述各类数据服务的适配器接口(datafeed):
* :arrow_up: 迅投研([xt](https://www.github.com/vnpy/vnpy_xt)):股票、期货、期权、基金、债券
* :arrow_up: 米筐RQData([rqdata](https://www.github.com/vnpy/vnpy_rqdata)):股票、期货、期权、基金、债券、黄金TD
* :arrow_up: MultiCharts([mcdata](https://www.github.com/vnpy/vnpy_mcdata)):期货、期货期权
* :arrow_up: TuShare([tushare](https://www.github.com/vnpy/vnpy_tushare)):股票、期货、期权、基金
* :arrow_up: 万得Wind([wind](https://www.github.com/vnpy/vnpy_wind)):股票、期货、基金、债券
* :arrow_up: 同花顺iFinD([ifind](https://www.github.com/vnpy/vnpy_ifind)):股票、期货、基金、债券
* :arrow_up: 天勤TQSDK([tqsdk](https://www.github.com/vnpy/vnpy_tqsdk)):期货
* :arrow_up: 掘金([gm](https://www.github.com/vnpy/vnpy_gm)):股票
* :arrow_up: polygon([polygon](https://www.github.com/vnpy/vnpy_polygon)):股票、期货、期权
8. :arrow_up: 跨进程通讯标准组件(rpc),用于实现分布式部署的复杂交易系统。
9. :arrow_up: Python高性能K线图表(chart),支持大数据量图表显示以及实时数据更新功能。
10. [社区论坛](http://www.vnpy.com/forum)和[知乎专栏](http://zhuanlan.zhihu.com/vn-py),内容包括VeighNa项目的开发教程和Python在量化交易领域的应用研究等内容。
11. 官方交流群262656087(QQ),管理严格(定期清除长期潜水的成员),入群费将捐赠给VeighNa社区基金。
注:以上关于功能特点的说明为根据说明文档发布时情况罗列,后续可能存在更新或调整。若功能描述同实际存在出入,欢迎通过Issue联系进行调整。
## 环境准备
* 推荐使用VeighNa团队为量化交易专门打造的Python发行版[VeighNa Studio-4.3.0](https://download.vnpy.com/veighna_studio-4.3.0.exe),集成内置了VeighNa框架以及VeighNa Station量化管理平台,无需手动安装
* 支持的系统版本:Windows 11以上 / Windows Server 2022以上 / Ubuntu 22.04 LTS以上
* 支持的Python版本:Python 3.10以上(64位),**推荐使用Python 3.13**
## 安装步骤
在[这里](https://github.com/vnpy/vnpy/releases)下载Release发布版本,解压后运行以下命令安装:
**Windows**
```
install.bat
```
**Ubuntu**
```
bash install.sh
```
**Macos**
```
bash install_osx.sh
```
## 使用指南
1. 在[SimNow](http://www.simnow.com.cn/)注册CTP仿真账号,并在[该页面](http://www.simnow.com.cn/product.action)获取经纪商代码以及交易行情服务器地址。
2. 在[VeighNa社区论坛](https://www.vnpy.com/forum/)注册获得VeighNa Station账号密码(论坛账号密码即是)
3. 启动VeighNa Station(安装VeighNa Studio后会在桌面自动创建快捷方式),输入上一步的账号密码登录
4. 点击底部的**VeighNa Trader**按钮,开始你的交易!!!
注意:
* 在VeighNa Trader的运行过程中请勿关闭VeighNa Station(会自动退出)
## 脚本运行
除了基于VeighNa Station的图形化启动方式外,也可以在任意目录下创建run.py,写入以下示例代码:
```Python
from vnpy.event import EventEngine
from vnpy.trader.engine import MainEngine
from vnpy.trader.ui import MainWindow, create_qapp
from vnpy_ctp import CtpGateway
from vnpy_ctastrategy import CtaStrategyApp
from vnpy_ctabacktester import CtaBacktesterApp
def main():
"""Start VeighNa Trader"""
qapp = create_qapp()
event_engine = EventEngine()
main_engine = MainEngine(event_engine)
main_engine.add_gateway(CtpGateway)
main_engine.add_app(CtaStrategyApp)
main_engine.add_app(CtaBacktesterApp)
main_window = MainWindow(main_engine, event_engine)
main_window.showMaximized()
qapp.exec()
if __name__ == "__main__":
main()
```
在该目录下打开CMD(按住Shift->点击鼠标右键->在此处打开命令窗口/PowerShell)后运行下列命令启动VeighNa Trader:
python run.py
## 贡献代码
VeighNa使用Github托管其源代码,如果希望贡献代码请使用github的PR(Pull Request)的流程:
1. [创建 Issue](https://github.com/vnpy/vnpy/issues/new) - 对于较大的改动(如新功能,大型重构等)建议先开issue讨论一下,较小的improvement(如文档改进,bugfix等)直接发PR即可
2. Fork [VeighNa](https://github.com/vnpy/vnpy) - 点击右上角**Fork**按钮
3. Clone你自己的fork: ```git clone https://github.com/$userid/vnpy.git```
* 如果你的fork已经过时,需要手动sync:[同步方法](https://help.github.com/articles/syncing-a-fork/)
4. 从**dev**创建你自己的feature branch: ```git checkout -b $my_feature_branch dev```
5. 在$my_feature_branch上修改并将修改push到你的fork上
6. 创建从你的fork的$my_feature_branch分支到主项目的**dev**分支的[Pull Request] - [在此](https://github.com/vnpy/vnpy/compare?expand=1)点击**compare across forks**,选择需要的fork和branch创建PR
7. 等待review, 需要继续改进,或者被Merge!
在提交代码的时候,请遵守以下规则,以提高代码质量:
* 使用[ruff](https://github.com/astral-sh/ruff)检查你的代码样式,确保没有error和warning。在项目根目录下运行```ruff check .```即可。
* 使用[mypy](https://github.com/python/mypy)进行静态类型检查,确保类型注解正确。在项目根目录下运行```mypy vnpy```即可。
## 其他内容
* [获取帮助](https://github.com/vnpy/vnpy/blob/dev/.github/SUPPORT.md)
* [社区行为准则](https://github.com/vnpy/vnpy/blob/dev/.github/CODE_OF_CONDUCT.md)
* [Issue模板](https://github.com/vnpy/vnpy/blob/dev/.github/ISSUE_TEMPLATE.md)
* [PR模板](https://github.com/vnpy/vnpy/blob/dev/.github/PULL_REQUEST_TEMPLATE.md)
## 版权说明
MIT
================================================
FILE: README_ENG.md
================================================
# VeighNa - By Traders, For Traders, AI-Powered.
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/veighna-logo.png"/>
</p>
💬 Want to read this in **chinese** ? Go [**here**](README.md)
<p align="center">
<img src ="https://img.shields.io/badge/version-4.3.0-blueviolet.svg"/>
<img src ="https://img.shields.io/badge/platform-windows|linux|macos-yellow.svg"/>
<img src ="https://img.shields.io/badge/python-3.10|3.11|3.12|3.13-blue.svg" />
<img src ="https://img.shields.io/github/actions/workflow/status/vnpy/vnpy/pythonapp.yml?branch=master"/>
<img src ="https://img.shields.io/github/license/vnpy/vnpy.svg?color=orange"/>
</p>
VeighNa is a Python-based open source quantitative trading system development framework that has grown step by step into a fully-featured quantitative trading platform with continuous contributions from the open source community. It currently has many users from domestic and international financial institutions, including hedge funds, investment banks, futures brokers, university research institutions, proprietary trading companies, etc.
If you have any questions about using VeighNa for secondary development (strategies, modules, etc.), please check the [**VeighNa Project Documentation**](https://www.vnpy.com/docs/cn/index.html). If you can't solve it, please go to the [Questions and Help] section of the [**Official Community Forum**](https://www.vnpy.com/forum/) for help, or share your experience in the [Experience Sharing] section!
**Want to get more information about VeighNa?** Please scan the QR code below to add the assistant and join the [VeighNa Community Exchange WeChat Group]:
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/github_wx.png"/, width=250>
</p>
## AI-Powered
On the tenth anniversary of VeighNa's release, version 4.0 officially introduces the [vnpy.alpha](./vnpy/alpha) module targeting AI quantitative strategies, providing professional quantitative traders with **an all-in-one multi-factor machine learning (ML) strategy development, research, and live trading solution**:
<p align="center">
<img src ="https://vnpy.oss-cn-shanghai.aliyuncs.com/alpha_demo.jpg"/, width=500>
</p>
* :bar_chart: **[dataset](./vnpy/alpha/dataset)**: Factor Feature Engineering
* Designed specifically for ML algorithm training optimization, supporting efficient batch feature calculation and processing
* Built-in rich factor feature expression calculation engine, enabling rapid one-click generation of training data
* [Alpha 158](./vnpy/alpha/dataset/datasets/alpha_158.py): A collection of stock market features from Microsoft's Qlib project, covering multiple dimensions of quantitative factors including K-line patterns, price trends, and time-series volatility
* :bulb: **[model](./vnpy/alpha/model)**: Prediction Model Training
* Provides standardized ML model development templates, greatly simplifying model building and training processes
* Unified API interface design, supporting seamless switching between different algorithms for performance comparison testing
* Integrates multiple mainstream machine learning algorithms:
* [Lasso](./vnpy/alpha/model/models/lasso_model.py): Classic Lasso regression model, implementing feature selection through L1 regularization
* [LightGBM](./vnpy/alpha/model/models/lgb_model.py): Efficient gradient boosting decision tree with a training engine optimized for large-scale datasets
* [MLP](./vnpy/alpha/model/models/mlp_model.py): Multi-layer perceptron neural network, suitable for modeling complex non-linear relationships
* :robot: **[strategy](./vnpy/alpha/strategy)**: Strategy Research and Development
* Quickly build quantitative trading strategies based on ML signal prediction models
* Support for both cross-sectional multi-asset and time-series single-asset strategy types
* :microscope: **[lab](./vnpy/alpha/lab.py)**: Research Process Management
* Integrates complete workflow including data management, model training, signal generation, and strategy backtesting
* Simple API design with built-in visualization analysis tools for intuitive evaluation of strategy performance and model effectiveness
* :book: **[notebook](./examples/alpha_research)**: Quantitative Research Demo
* [download_data_rq](./examples/alpha_research/download_data_rq.ipynb): Download A-share index constituent stock data based on RQData, including index constituent tracking and historical market data retrieval
* [download_data_xt](./examples/alpha_research/download_data_xt.ipynb): Download A-share index constituent historical changes and stock K-line data based on XtQuant data service
* [research_workflow_lasso](./examples/alpha_research/research_workflow_lasso.ipynb): Quantitative research workflow based on Lasso regression model, demonstrating feature selection and prediction capability of linear models
* [research_workflow_lgb](./examples/alpha_research/research_workflow_lgb.ipynb): Quantitative research workflow based on LightGBM gradient boosting tree, utilizing efficient ensemble learning methods for prediction
* [research_workflow_mlp](./examples/alpha_research/research_workflow_mlp.ipynb): Quantitative research workflow based on multilayer perceptron neural network, demonstrating the application of deep learning in quantitative trading
The design concept of the vnpy.alpha module was inspired by the [Qlib](https://github.com/microsoft/qlib) project, providing powerful AI quantitative capabilities while maintaining ease of use. We would like to express our sincere gratitude to the Qlib development team!
## Functional Features
Modules marked with :arrow_up: have completed the upgrade compatibility testing for version 4.0. Additionally, the 4.0 core framework uses an upgrade approach that prioritizes compatibility, so most modules can also be used directly (interfaces involving C++ API encapsulation must be upgraded before use).
1. :arrow_up: Multi-functional quantitative trading platform (vnpy.trader) that integrates various trading interfaces and provides simple and easy-to-use APIs for specific strategy algorithm and function development, for quickly building quantitative trading applications required by traders.
2. Trading interfaces (vnpy.gateway) covering all domestic and international trading varieties:
* Domestic market
* :arrow_up: CTP ([ctp](https://www.github.com/vnpy/vnpy_ctp)): Domestic futures and options
* :arrow_up: CTP Mini ([mini](https://www.github.com/vnpy/vnpy_mini)): Domestic futures, options
* :arrow_up: CTP Securities ([sopt](https://www.github.com/vnpy/vnpy_sopt)): ETF options
* :arrow_up: FEMAS ([femas](https://www.github.com/vnpy/vnpy_femas)): Domestic futures
* :arrow_up: UFT ([uft](https://www.github.com/vnpy/vnpy_uft)): Domestic futures, ETF options
* :arrow_up: Esunny ([esunny](https://www.github.com/vnpy/vnpy_esunny)): Domestic futures, Gold TD
* :arrow_up: APEX HTS ([hts](https://www.github.com/vnpy/vnpy_hts)): ETF options
* :arrow_up: XTP ([xtp](https://www.github.com/vnpy/vnpy_xtp)): Domestic securities (A shares), ETF options
* :arrow_up: TORA ([tora](https://www.github.com/vnpy/vnpy_tora)): Domestic securities (A shares), ETF options
* OST ([ost](https://www.github.com/vnpy/vnpy_ost)): Domestic securities (A shares)
* EMT ([emt](https://www.github.com/vnpy/vnpy_emt)): Domestic securities (A shares)
* SGIT ([sgit](https://www.github.com/vnpy/vnpy_sgit)): Gold TD, domestic futures
* :arrow_up: KsGold ([ksgold](https://www.github.com/vnpy/vnpy_ksgold)): Gold TD
* :arrow_up: LStar ([lstar](https://www.github.com/vnpy/vnpy_lstar)): Futures asset management
* :arrow_up: Rohon ([rohon](https://www.github.com/vnpy/vnpy_rohon)): Futures asset management
* :arrow_up: Jees ([jees](https://www.github.com/vnpy/vnpy_jees)): Futures asset management
* ComStar ([comstar](https://www.github.com/vnpy/vnpy_comstar)): Interbank market
* :arrow_up: TTS ([tts](https://www.github.com/vnpy/vnpy_tts)): Domestic futures (simulation)
* Overseas market
* :arrow_up: Interactive Brokers ([ib](https://www.github.com/vnpy/vnpy_ib)): Global securities, futures, options, forex, etc.
* :arrow_up: Esunny 9.0 ([tap](https://www.github.com/vnpy/vnpy_tap)): Global futures
* :arrow_up: Direct Futures ([da](https://www.github.com/vnpy/vnpy_da)): Global futures
* Special Applications
* :arrow_up: RQData Market Data ([rqdata](https://www.github.com/vnpy/vnpy_rqdata)): Cross-market (stocks, indices, ETFs, futures) real-time market data
* :arrow_up: XtQuant Market Data ([xt](https://www.github.com/vnpy/vnpy_xt)): Cross-market (stocks, indices, convertible bonds, ETFs, futures, options) real-time market data
* :arrow_up: RPC service ([rpc](https://www.github.com/vnpy/vnpy_rpcservice)): Inter-process communication interface for distributed architecture
3. Out-of-the-box trading applications for various quantitative strategies (vnpy.app):
* :arrow_up: [cta_strategy](https://www.github.com/vnpy/vnpy_ctastrategy): CTA strategy engine module, which allows users to perform fine-grained control over the order management during the operation of CTA-type strategies while maintaining ease of use (reducing trading slippage, implementing high-frequency strategies)
* :arrow_up: [cta_backtester](https://www.github.com/vnpy/vnpy_ctabacktester): CTA strategy backtester module, no need to use Jupyter Notebook, directly use the graphical interface to carry out strategy backtesting analysis, parameter optimization and other related work
* :arrow_up: [spread_trading](https://www.github.com/vnpy/vnpy_spreadtrading): Spread trading module, supports custom spreads, real-time calculation of spread quotes and positions, supports semi-automatic spread algorithm trading and fully automatic spread strategy trading modes
* :arrow_up: [option_master](https://www.github.com/vnpy/vnpy_optionmaster): Option trading module, designed for the domestic options market, supports various option pricing models, implied volatility surface calculation, Greek value risk tracking and other functions
* :arrow_up: [portfolio_strategy](https://www.github.com/vnpy/vnpy_portfoliostrategy): Portfolio strategy module, designed for trading multi-contract quantitative strategies (Alpha, option arbitrage, etc.) simultaneously, providing historical data backtesting and live automatic trading functions
* :arrow_up: [algo_trading](https://www.github.com/vnpy/vnpy_algotrading): Algorithm trading module, providing various commonly used intelligent trading algorithms: TWAP, Sniper, Iceberg, BestLimit, etc.
* :arrow_up: [script_trader](https://www.github.com/vnpy/vnpy_scripttrader): Script strategy module, designed for multi-asset portfolio trading strategies and computational tasks, also can directly achieve REPL instruction trading in the command line, does not support backtesting functions
* :arrow_up: [paper_account](https://www.github.com/vnpy/vnpy_paperaccount): Simulation trading module, pure localized implementation of simulation trading functions, based on real-time quotes obtained from the trading interface for order matching, providing order execution pushing and position records
* :arrow_up: [chart_wizard](https://www.github.com/vnpy/vnpy_chartwizard): K-line chart module, based on RQData data service (futures) or trading interface to obtain historical data, and combined with Tick push to display real-time market changes
* :arrow_up: [portfolio_manager](https://www.github.com/vnpy/vnpy_portfoliomanager): Portfolio module, for various fundamental trading strategies, based on separate strategy sub-accounts, providing automatic tracking of trading positions and real-time profit and loss statistics
* :arrow_up: [rpc_service](https://www.github.com/vnpy/vnpy_rpcservice): RPC service module, allowing a VeighNa Trader process to be started as a server, serving as a unified routing channel for quotes and trades, allowing multiple clients to connect simultaneously, realizing a multi-process distributed system
* :arrow_up: [data_manager](https://www.github.com/vnpy/vnpy_datamanager): Historical data management module, view existing data in the database through a tree directory, select any time period data to view field details, supports CSV file data import and export
* :arrow_up: [data_recorder](https://www.github.com/vnpy/vnpy_datarecorder): Market data recording module, based on the graphical interface for configuration, records Tick or K-line data to the database in real-time according to demand, for strategy backtesting or live initialization
* :arrow_up: [excel_rtd](https://www.github.com/vnpy/vnpy_excelrtd): Excel RTD (Real Time Data) real-time data service, based on pyxll module to achieve real-time push updates of various data (quotes, contracts, positions, etc.) in Excel
* :arrow_up: [risk_manager](https://www.github.com/vnpy/vnpy_riskmanager): Risk management module, providing statistics and restrictions on rules including trade flow control, number of orders placed, active orders, total number of cancelled orders, etc., effectively implementing front-end risk control functions
* :arrow_up: [web_trader](https://www.github.com/vnpy/vnpy_webtrader): Web service module, designed according to the requirements of B-S architecture, implementing a web server that provides active function calls (REST) and passive data push (WebSocket)
4. Python trading API interface package (vnpy.api), providing the underlying implementation of the above trading interfaces:
* :arrow_up: REST Client ([rest](https://www.github.com/vnpy/vnpy_rest)): High-performance REST API client based on coroutine process asynchronous IO which adopts the programming model of event message cycle to support sending high concurrent real-time transaction requests
* :arrow_up: Websocket Client ([websocket](https://www.github.com/vnpy/vnpy_websocket)): High-performance Websocket API client based on coroutine process asynchronous IO, supports sharing event loops with REST Client to avoid multi-threaded performance loss caused by GIL
5. :arrow_up: Simple and easy-to-use event-driven engine (vnpy.event), which is the core of event-driven trading programs
6. Standardized management client (vnpy.database) interfacing with various databases:
* SQL class
* :arrow_up: SQLite ([sqlite](https://www.github.com/vnpy/vnpy_sqlite)): Lightweight single file database, no need to install and configure data service programs, default option of VeighNa, suitable for novice users
* :arrow_up: MySQL ([mysql](https://www.github.com/vnpy/vnpy_mysql)): The world's most popular open source relational database, extremely rich documentation, and can replace other high NewSQL compatible implementations (such as TiDB)
* :arrow_up: PostgreSQL ([postgresql](https://www.github.com/vnpy/vnpy_postgresql)): More feature-rich open source relational database, support for new features through extension plug-ins, only recommended for skilled users
* NoSQL classes
* DolphinDB ([dolphindb](https://www.github.com/vnpy/vnpy_dolphindb)): A high-performance distributed temporal database especially suitable for low latency or real-time tasks with high speed requirements
* :arrow_up: TDengine ([taos](https://www.github.com/vnpy/vnpy_taos)): Distributed, high-performance, SQL-supporting time-series database with built-in caching, stream computing, data subscription and other system functions that greatly reduce development and maintenance complexity
* :arrow_up: MongoDB ([mongodb](https://www.github.com/vnpy/vnpy_mongodb)): Non-relational database based on distributed file storage (bson format), built-in memory cache of hot data provides faster read and write speeds
7. Adapter interfaces for various data services (datafeed):
* :arrow_up: XtQuant ([xt](https://www.github.com/vnpy/vnpy_xt)): Stocks, futures, options, funds, bonds
* :arrow_up: RQData ([rqdata](https://www.github.com/vnpy/vnpy_rqdata)): Stocks, futures, options, funds, bonds, Gold TD
* :arrow_up: MultiCharts ([mcdata](https://www.github.com/vnpy/vnpy_mcdata)): Futures, futures options
* :arrow_up: TuShare ([tushare](https://www.github.com/vnpy/vnpy_tushare)): Stocks, futures, options, funds
* :arrow_up: Wind ([wind](https://www.github.com/vnpy/vnpy_wind)): Stocks, futures, funds, bonds
* :arrow_up: iFinD ([ifind](https://www.github.com/vnpy/vnpy_ifind)): Stocks, futures, funds, bonds
* :arrow_up: TQSDK ([tqsdk](https://www.github.com/vnpy/vnpy_tqsdk)): Futures
* :arrow_up: GoldMiner ([gm](https://www.github.com/vnpy/vnpy_gm)): Stocks
* :arrow_up: polygon ([polygon](https://www.github.com/vnpy/vnpy_polygon)): Stocks, futures, options
8. :arrow_up: Standard component for inter-process communication (vnpy.rpc) for implementing complex trading systems in distributed deployments
9. :arrow_up: Python high-performance K-line charts (vnpy.chart), supporting large data volume chart display and real-time data update functions
10. [Community Forum](http://www.vnpy.com/forum) and [Zhihu Blog](http://zhuanlan.zhihu.com/vn-py), which include the development tutorial of VeighNa project and the research on the application of Python in the field of quantitative trading, etc.
11. The official communication group 262656087 (QQ), with strict management (regular purging of long-term inactive members), and the membership fee will be donated to the VeighNa community fund.
Note: The above description of functional features is based on the documentation at the time of publication, and subsequent updates or adjustments may exist. If there are discrepancies between the function description and the actual situation, please contact us through Issue for adjustments.
## Environment preparation
* We recommend using the Python distribution [VeighNa Studio-4.3.0](https://download.vnpy.com/veighna_studio-4.3.0.exe), which is built with the latest version of VeighNa framework and VeighNa Station quantitative management platform, specifically created by the VeighNa team for quantitative trading. No manual installation required.
* Supported system versions: Windows 11 or above / Windows Server 2022 or above / Ubuntu 22.04 LTS or above
* Supported Python version: Python 3.10 or above (64-bit), **Python 3.13 recommended**
## Installation steps
Download the latest version from [here](https://github.com/vnpy/vnpy/releases), unzip it and run the following command to install it.
**Windows**
```
install.bat
```
**Ubuntu**
```
bash install.sh
```
**Macos**
```
bash install_osx.sh
```
## User's Guide
1. Register a CTP Demo account at [SimNow](http://www.simnow.com.cn/) and get the broker code and the trading quotes server address at [this page](http://www.simnow.com.cn/product.action).
2. Register at [VeighNa community forum](https://www.vnpy.com/forum/) to get the VeighNa Station account password (the forum account password is used)
3. Launch VeighNa Station (a shortcut will be created automatically on your desktop after installing VeighNa Studio), enter the account password from the previous step and login
4. Click on the **VeighNa Trader** button at the bottom and start your trading!
Attention:
* Please do not close VeighNa Station during the running of VeighNa Trader (it will exit automatically)
## Script Run
In addition to the graphical start-up method based on VeighNa Station, you can also create run.py in any directory and write the following sample code:
```Python
from vnpy.event import EventEngine
from vnpy.trader.engine import MainEngine
from vnpy.trader.ui import MainWindow, create_qapp
from vnpy_ctp import CtpGateway
from vnpy_ctastrategy import CtaStrategyApp
from vnpy_ctabacktester import CtaBacktesterApp
def main():
"""Start VeighNa Trader"""
qapp = create_qapp()
event_engine = EventEngine()
main_engine = MainEngine(event_engine)
main_engine.add_gateway(CtpGateway)
main_engine.add_app(CtaStrategyApp)
main_engine.add_app(CtaBacktesterApp)
main_window = MainWindow(main_engine, event_engine)
main_window.showMaximized()
qapp.exec()
if __name__ == "__main__":
main()
```
Open CMD in that directory (hold Shift->click right mouse button->open command window/PowerShell here) and then run the following command to start VeighNa Trader:
python run.py
## Contributing code
VeighNa uses Github to host its source code, if you wish to contribute code please use the PR (Pull Request) process of github:
1. [Create Issue](https://github.com/vnpy/vnpy/issues/new) - For larger changes (such as new features, large refactoring, etc.) it is best to first open an issue to discuss, and smaller improvements (such as document improvements, bugfixes, etc.) can be sent directly to PR
2. Fork [VeighNa](https://github.com/vnpy/vnpy) - Click the **Fork** button in the upper right corner
3. Clone your own fork: ```git clone https://github.com/$userid/vnpy.git```
* If your fork is out of date, you need to manually sync: [Synchronization method](https://help.github.com/articles/syncing-a-fork/)
4. Create your own feature branch from **dev**: ```git checkout -b $my_feature_branch dev```
5. Make changes on $my_feature_branch and push the changes to your fork
6. Create a [Pull Request] from your fork's $my_feature_branch branch to the main project's **dev** branch - [here](https://github.com/vnpy/vnpy/compare?expand=1) Click on **compare across forks** and select the required fork and branch to create the PR
7. Waiting for review, need to continue to improve, or be Merge!
When submitting code, please observe the following rules to improve the quality of the code:
* Use [ruff](https://github.com/astral-sh/ruff) to check your code style, ensuring there are no errors and warnings. Just run ``ruff check .`` in the project root directory.
* Use [mypy](https://github.com/python/mypy) for static type checking, ensuring type annotations are correct. Just run ``mypy vnpy`` in the project root directory.
## Other content
* [Getting Help](https://github.com/vnpy/vnpy/blob/dev/.github/SUPPORT.md)
* [Community Conduct Guidelines](https://github.com/vnpy/vnpy/blob/dev/.github/CODE_OF_CONDUCT.md)
* [Issue templates](https://github.com/vnpy/vnpy/blob/dev/.github/ISSUE_TEMPLATE.md)
* [PR templates](https://github.com/vnpy/vnpy/blob/dev/.github/PULL_REQUEST_TEMPLATE.md)
## Copyright statement
MIT
================================================
FILE: docs/community/app/algo_trading.md
================================================
# AlgoTrading - 算法委托执行交易模块
## 功能简介
AlgoTrading是用于**算法委托执行交易**的模块,用户可以通过其UI界面操作来便捷完成启动算法、保存配置、停止算法等任务。
算法交易负责委托订单的具体执行过程。目前,AlgoTrading提供了多种示例算法,用户可以通过把大笔订单自动拆分成合适的小单分批委托,有效降低交易成本和冲击成本(如冰山算法、狙击手算法),也可以在设定的阈值内进行高抛低吸操作(如网格算法、套利算法)。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【AlgoTrading】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_algotrading import AlgoTradingApp
# 写在创建main_engine对象后
main_engine.add_app(AlgoTradingApp)
```
## 启动模块
对于用户搭建的算法,需要放到algo_trading.algos目录中,才能被识别加载。
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【算法交易】,或者点击左侧按钮栏的图标:

即可进入算法委托执行交易模块的UI界面,如下图所示:

## 配置算法
配置参数要求如下:
- 算法:在下拉框中选择要执行的交易算法;
- 本地代码:格式为vt_symbol(合约代码 + 交易所名称);
- 方向:多、空;
- 价格:委托下单的价格;
- 数量:委托的总数量,需要拆分成小批订单进行交易;
- 执行时间(秒):运行该算法交易的总时间,以秒为单位;
- 每轮间隔(秒):每隔多少时间进行委托下单操作,以秒为单位;
- 开平:开、平、平今、平昨。
## 启动算法
目前VeighNa一共提供了五种常用的示例算法。本文档以时间加权平均算法(TWAP)为例,介绍算法启动过程。

参数配置完成后(已保存的算法信息,通过在【配置】栏对应的算法下点击【使用】,可切换界面左侧配置的信息内容),点击【启动算法】按钮,即可立刻执行算法交易。
若启动成功,则可在右上角【执行中】界面观测到该算法的执行状态。
图中算法执行的任务具体为:使用时间加权平均算法,买入10000手豆油2109合约(y2409),执行价格为7420元,执行时间为600秒,每轮间隔为6秒;即每隔6秒钟,当合约卖一价小于等于7420时,以7420的价格买入100手豆油2409合约,将买入操作分割成100次。
## CSV启动
当有较多算法需要启动时,可以通过CSV文件来一次性批量启动。点击图形界面左侧的【CSV启动】按钮,在弹出的对话框中找到要导入的CSV文件后打开即可快速启动算法。
请注意,CSV文件的格式应如下图所示,和左侧编辑区的各字段一致:

结合Excel的表格快速编辑功能,批量添加算法较为方便。启动成功后,CSV文件中所有算法的执行情况均会显示在【执行中】界面下。
## 停止算法
当用户需要暂停正在执行的交易算法时,可以在【执行中】界面点击【暂停】按钮,暂停某个正在执行的算法交易,如下图所示:

当用户需要恢复已经暂停的交易算法时,可以在【执行中】界面点击【恢复】按钮,恢复某个已经暂停的算法交易,如下图所示:

当用户需要停止正在执行的交易算法时,可以在【执行中】界面点击【停止】按钮,停止某个正在执行的算法交易,如下图所示:

用户也可以在委托交易界面点击最下方的【全部停止】按钮,一键停止所有执行中的算法交易,如下图所示:

## 数据监控
数据监控界面由四个部分构成:
执行中组件:显示正在执行的算法交易,包括:算法、参数、变量和状态。成功启动算法之后,切换到右上角【执行中】界面,会显示该算法的执行状态,如下图所示:

已结束组件:显示已完成的算法交易,同样包括:算法、参数、变量和状态。算法结束或者停止之后,切换到右上角【已结束】界面,会显示该算法的执行状态,如下图所示:

日志组件:显示启动、停止、完成算法的相关日志信息。在打开算法交易模块后,会进行初始化,故【日志】组件会首先输出“算法交易引擎启动”,如下图所示:

## 示例算法
示例算法路径位于vnpy_algotrading.algos文件夹下(请注意,个别算法是没有写开平方向的,若有需要,可基于自身需求进行个性化修改)。目前,算法交易模块提供了以下五种内置算法:
### TWAP - 时间加权平均算法
时间加权平均算法(TWAP)具体执行步骤如下:
- 将委托数量平均分布在某个时间区域内,每隔一段时间用指定的价格挂出买单(或者卖单)。
- 买入情况:卖一价低于目标价格时,发出委托,委托数量在剩余委托量与委托分割量中取最小值。
- 卖出情况:买一价高于目标价格时,发出委托,委托数量在剩余委托量与委托分割量中取最小值。
### Iceberg - 冰山算法
冰山算法(Iceberg)具体执行步骤如下:
- 在某个价位挂单,但是只挂一部分,直到全部成交。
- 买入情况:先检查撤单,最新Tick卖一价低于目标价格,执行撤单;若无活动委托,发出委托,委托数量在剩余委托量与挂出委托量中取最小值。
- 卖出情况:先检查撤单,最新Tick买一价高于目标价格,执行撤单;若无活动委托,发出委托,委托数量在剩余委托量与挂出委托量中取最小值。
### Sniper - 狙击手算法
狙击手算法(Sniper)具体执行步骤如下:
- 监控最新Tick推送的行情,发现好的价格立刻报价成交。
- 买入情况:最新Tick卖一价低于目标价格时,发出委托,委托数量在剩余委托量与卖一量中取最小值。
- 卖出情况:最新Tick买一价高于目标价格时,发出委托,委托数量在剩余委托量与买一量中取最小值。
### Stop - 条件委托算法
条件委托算法(Stop)具体执行步骤如下:
- 监控最新Tick推送的行情,发现行情突破立刻报价成交。
- 买入情况:Tick最新价高于目标价格时,发出委托,委托价为目标价格加上超价。
- 卖出情况:Tick最新价低于目标价格时,发出委托,委托价为目标价格减去超价。
### BestLimit - 最优限价算法
最优限价算法(BestLimit)具体执行步骤如下:
- 监控最新Tick推送的行情,发现好的价格立刻报价成交。
- 买入情况:先检查撤单:最新Tick买一价不等于目标价格时,执行撤单;若无活动委托,发出委托,委托价格为最新Tick买一价,委托数量为剩余委托量。
- 卖出情况:先检查撤单:最新Tick买一价不等于目标价格时,执行撤单;若无活动委托,发出委托,委托价格为最新Tick卖一价,委托数量为剩余委托量。
================================================
FILE: docs/community/app/chart_wizard.md
================================================
# ChartWizard - 实时K线图表模块
## 功能简介
ChartWizard是用于**实时K线图表展示**的功能模块,用户可以通过其UI界面查看实时和历史K线行情,目前只支持显示1分钟级别的K线数据,实时K线(最新的一根K线)为Tick级刷新。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【ChartWizard】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_chartwizard import ChartWizardApp
# 写在创建main_engine对象后
main_engine.add_app(ChartWizardApp)
```
## 启动模块
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
由于VeighNa本身并不提供任何数据服务,对于K线图表绘制过程中用到的历史数据,国内期货历史数据由数据服务提供,用户需要准备和配置数据服务账号(配置方法详见基本使用篇的全局配置部分)。
成功连接交易接口后,在菜单栏中点击【功能】-> 【K线图表】,或者点击左侧按钮栏的图标:

即可进入实时K线图表模块的UI界面,如下图所示:

## 新建图表
打开图表窗口后,在【本地代码】编辑框中输入合约代码(注意本地代码由代码前缀和交易所后缀两部分组成,如rb2112.SHFE)。
点击【新建图表】的按钮,即可创建对应合约的K线图表,如下图所示:

用户可以新建多个合约的K线图表,通过切换窗口来实现快速切换:

## 查看图表
每个合约的图表分为上下两块子图区域:
- 上面的子图为行情K线;
- 下面的子图为成交量数据。
图表上的十字光标可用于定位和显示特定时间点的具体数据,在X轴和Y轴上均会对应数据点的标签,同时在左上角也会显示此根K线的OHLCV等信息。
其他快捷操作:
- 可以通过鼠标左键的拖拽,左右平移K线图显示的时间范围;
- 可以通过鼠标滚轮的滚动,放大和缩小K线图显示的时间范围。
================================================
FILE: docs/community/app/cta_backtester.md
================================================
# CtaBacktester - CTA回测研究模块
## 功能简介
CtaBacktester是用于**CTA回测研究**的功能模块,用户可以通过其UI界面操作来便捷完成数据下载、历史回测、结果分析和参数优化等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【CtaBacktester】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_ctabacktester import CtaBacktesterApp
# 写在创建main_engine对象后
main_engine.add_app(CtaBacktesterApp)
```
## 启动模块
对于用户自行开发的策略,需要放到VeighNa Trader运行时目录下的**strategies**目录中,才能被识别加载。具体的运行时目录路径,可以在VeighNa Trader主界面顶部的标题栏查看。
对于在Windows上默认安装的用户来说,放置策略的strategies目录路径通常为:
```
C:\Users\Administrator\strategies
```
其中Administrator为当前登录Windows的系统用户名。
启动VeighNa Trader后,在菜单栏中点击【功能】-> 【CTA回测】,或者点击左侧按钮栏的图标:

即可打开图形化的回测界面,如下图所示:

## 下载数据
在开始策略回测之前,首先需要保证数据库内有足够的历史数据,CtaBacktester模块也提供了一键下载历史数据的功能。
下载数据需要填写本地代码、K线周期、开始日期以及结束日期四个字段信息:
<span id="jump">
- 本地代码
- 格式为合约代码 + 交易所名称
- 如IF888.CFFEX、rb2105.SHFE
- K线周期:
- 1m(1分钟K线)
- 1h(1小时K线)
- d(日K线)
- w(周K线)
- tick(一个Tick)
- 开始和结束日期
- 格式为yyyy/mm/dd
- 如2018/2/25、2021/2/28
</span>
填写完成后,点击下方【下载数据】按钮启动下载任务,成功后如下图所示:

注意下载完成后的历史数据会保存在本地数据库中,后续回测时可以直接使用,无需每次都重复下载。
### 数据来源:数据服务(期货、股票、期权)
以RQData为例,[RQData](https://www.ricequant.com/welcome/purchase?utm_source=vnpy)提供国内期货、股票以及期权的历史数据。在使用前需要保证数据服务已经正确配置(配置方法详见基本使用篇的全局配置部分)。打开CtaBacktester时会自动执行数据服务登录初始化,若成功则会输出“数据服务初始化成功”的日志,如下图所示:

### 数据来源:IB(外盘期货、股票、现货等)
Interactive Brokers盈透证券(IB)提供丰富的外盘市场历史数据下载(包括股票、期货、期权、现货等),注意下载前需要先启动IB TWS交易软件,并在VeighNa Trader主界面连接好IB接口,并订阅所需合约行情。下载成功如下图所示:

## 执行回测
准备好数据后即可开始使用历史数据对策略进行回测研究,回测时需要配置好相关的参数:
- 策略品种
- 交易策略:在下拉框中选择要回测的策略名称;
- 本地代码:注意不要漏掉交易所后缀;
- 数据范围
- 格式详见本章[下载数据](#jump)部分的介绍;
- 交易成本
- 滑点:下单交易点位与实际交易点位的差别;
- 百分比手续费:填写数字即可,不要填写百分数;
- 固定比手续费:可以手续费填0,然后把手续费除以合约乘数后,加在滑点中;
- 合约属性
- 合约乘数:合约的交易单位;
- 价格跳动:合约价格的最小变动价位;
- 回测资金:账户资金;
- 合约模式:正向。
配置完成后,点击下方的【开始回测】按钮,会弹出策略参数配置对话框,用于设置策略参数,如下图所示:

点击【确定】按钮后开始执行回测任务,同时日志界面会输出相关信息,如下图所示:

回测完成后,会自动在右侧区域显示策略回测业绩的统计指标以及相关图表,如下图所示:

若数据库没有准备好所需的历史数据就点击【开始回测】,则日志界面会输出“历史数据不足,回测终止”的日志,如下图所示:

## 结果分析
### 业绩图表
右侧的业绩图表由以下四张子图构成:

【账户净值】图的横轴是时间,纵轴是资金,体现了账户净值在交易时段内随着交易日变化的情况。

【净值回撤】图的横轴是时间,纵轴是回撤,体现了净值从最近高点回撤程度随着交易日变化的情况。

【每日盈亏】图的横轴是时间,纵轴是日盈亏的金额(采用逐日盯市规则以收盘价结算),体现了整个回测周期内策略的每日盈亏变化情况。

【盈亏分布】图的横轴是每日盈亏的数值,纵轴是该盈亏数值的出现概率,体现了整体每日盈亏的概率分布情况。
### 统计指标
统计指标区域用于显示策略历史回测业绩的相关统计数值,如下图所示:


根据数据类型,指标可以分类为:
- 日期信息
- 首个交易日
- 最后交易日
- 总交易日
- 盈利交易日
- 亏损交易日
- 资金盈亏
- 起始资金
- 结束资金
- 总收益率
- 年化收益
- 最大回撤
- 百分比最大回撤
- 总盈亏
- 交易成本
- 总手续费
- 总滑点
- 总成交额
- 总成交笔数
- 日均数据
- 日均盈亏
- 日均手续费
- 日均滑点
- 日均成交额
- 日均成交笔数
- 日均收益率
- 收益标准差(日均)
- 绩效评价
- 夏普比率
- 收益回撤比
### 详细信息
回测完成后,可点击左侧区域的【委托记录】按钮,查看回测过程中策略逐笔委托的细节信息:

如果发现表格内容显示不完整,可以单击鼠标右键弹出菜单后,选择【调整列宽】按钮,即可进行自动列宽缩放:

表格也支持一键将表内数据保存为CSV文件,在上一步右键弹出的菜单中,点击【保存数据】按钮,即可弹出如下图所示选择保存文件名的对话框:

回测过程中策略发出委托的**成交价**不一定是原始下单的价格,而要由回测引擎基于当时的行情数据和下单价格进行撮合后算出,每笔委托对应的具体成交细节可以点击【成交记录】按钮后查看:

点击【每日盈亏】按钮后,可以看到如下图所示的策略每日盈亏细节:

这里每日盈亏的统计采用期货市场普遍使用的逐日盯市(Marking-to-Market)规则进行计算:
- 持仓盈亏:今日开盘持仓的部分,以昨收盘价开仓,今收盘价平仓,计算出的盈亏金额;
- 交易盈亏:今日日内成交的部分,以成交价格开仓,今收盘价平仓,计算出的盈亏金额;
- 总盈亏:汇总持仓盈亏和交易盈亏后的金额;
- 净盈亏:总盈亏扣除手续费和滑点后的金额,也是最终计算显示四张图表时用到的每日盈亏金额。
### K线图表
点击【K线图表】按钮,即可打开用于显示回测K线数据,以及策略具体买卖点位置的图表,如下图所示:

注意绘图耗时可能需要一定时间(通常在数十秒到几分钟),请耐心等待。
K线图表中的图例说明可以在窗口底部看到,整体上采用了国内市场标准的配色和风格。开平仓之间的连线采用的是逐笔配对(First-in, First-out)规则进行绘制,每一笔成交会根据其数量自动和其他成交进行匹配,即使策略有复杂的加减仓操作也能正确绘制。
## 参数优化
对于开发好的策略,可以使用CtaBacktester内置的优化算法快速进行参数寻优,目前支持穷举和遗传两种优化算法。
### 设置优化参数
点击【参数优化】按钮,会弹出“优化参数配置”的窗口:

点击【目标】下拉框,选择优化过程中要使用的目标函数(即以该数值最大化为目标进行优化):

对于要进行优化的策略参数,需要配置:
- 【开始】和【结束】:用于给定参数优化的范围;
- 【步进】:用于给定参数每次变化的数值;
举例:如一个参数的【开始】设为10,【结束】设为20,【步进】设为2,则该参数在优化过程中的寻优空间为:10、12、14、16、18、20。
对于要设置固定数值的策略参数,请将【开始】和【结束】都同样设为该数值即可。
### 穷举算法优化
设置好需要优化的参数后,点击窗口底部的【多进程优化】按钮,此时CtaBacktester会调用Python的multiprocessing模块,根据当前电脑CPU的核心数量,启动对应数量的进程来并行执行穷举优化任务。
在优化的过程中,穷举算法会遍历参数寻优空间中的每一个组合。遍历的过程即使用该组合作为策略参数运行一次历史回测,并返回优化目标函数的数值。完成遍历后,根据所有目标函数的数值进行排序,从而选出最优的参数组合结果。
穷举算法优化的效率和CPU核心数量直接相关:若用户计算机是2核,则优化时间为单核的1/2;若计算机是10核,则优化时间会大幅降低到单核的1/10。
### 遗传算法优化
设置好需要优化的参数后,点击窗口底部的【遗传算法优化】按钮,此时CtaBacktester会调用Python的multiprocessing模块和deap模块,来执行高效智能化的多进程遗传算法优化任务。
附上遗传算法的简要工作原理:
1. 定义优化方向,如总收益率最大化;
2. 随机从全局寻优空间中,选择出部分参数组合形成初始族群;
3. 对族群内所有个体进行评估,即运行回测获取目标函数结果;
4. 基于目标函数结果进行排序,剔除表现不好的个体(参数组合);
5. 对剩下的个体进行交叉或者变异,通过评估和筛选后形成新的族群;
6. 以上3-5步为一次完整的种群迭代,在整个优化过程中需要多次重复;
7. 多次迭代后,种群内差异性减少,参数收敛向最优解,最终输出结果。
### 优化结果分析
优化完成后,会在日志区域输出信息提示:

此时点击【优化结果】按钮即可查看相关结果:

上图中的参数优化结果,基于启动优化任务时所选的目标函数【总收益率】的数值,由高到低进行了排序。
最后,点击右下角的【保存】按钮即可将优化结果保存到本地CSV文件中,便于后续分析使用。
## 策略代码
### 代码编辑
如果需要对策略进行修改,在CtaBacktester界面左上角的下拉框中选择策略后,点击左下角的【代码编辑】按钮,即可自动打开Visual Studio Code进行代码编辑。若找不到Visual Studio Code,则会弹出启动代码编辑器失败对话框,如下图所示:

### 策略重载
当用户通过CtaBacktester对策略源代码进行修改后,此时的修改尚停留在硬盘上的代码文件层面,内存中依然是修改前的策略代码。
想让修改内容在内存中立即生效,需要点击左下角的【策略重载】按钮,此时CtaBacktester会自动扫描并重新加载所有策略文件中的策略代码,同时会有相关日志输出,如下图所示:

重载刷新完成后,再运行回测或者优化时,使用的就是修改后的策略代码了。
================================================
FILE: docs/community/app/cta_strategy.md
================================================
# CtaStrategy - CTA自动交易模块
## 功能简介
CtaStrategy是用于**CTA自动交易**的功能模块,用户可以通过其UI界面操作来便捷完成策略初始化、策略启动、策略停止、策略参数编辑以及策略移除等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【CtaStrategy】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_ctastrategy import CtaStrategyApp
# 写在创建main_engine对象后
main_engine.add_app(CtaStrategyApp)
```
## 启动模块
<span id="jump">
对于用户自行开发的策略,需要放到VeighNa Trader运行时目录下的**strategies**目录中,才能被识别加载。具体的运行时目录路径,可以在VeighNa Trader主界面顶部的标题栏查看。
对于在Windows上默认安装的用户来说,放置策略的strategies目录路径通常为:
```
C:\Users\Administrator\strategies
```
其中Administrator为当前登录Windows的系统用户名。
</span>
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【CTA策略】,或者点击左侧按钮栏的图标:

即可进入CTA策略模块的UI界面,如下图所示:

如果配置了数据服务(配置方法详见基本使用篇的全局配置部分),打开CTA策略模块时会自动执行数据服务登录初始化。若成功登录,则会输出“数据服务初始化成功”的日志,如下图所示:

## 添加策略
用户可以基于编写好的CTA策略模板(类)来创建不同的策略实例(对象)。策略实例的好处在于,同一个策略可以同时去交易多个品种合约,并且每个实例的参数可以是不同的。
在左上角的下拉框中选择要交易的策略名称,如下图所示:

请注意,显示的策略名称是**策略类**(驼峰式命名)的名字,而不是策略文件(下划线模式命名)的名字。
选择好策略类之后,点击【添加策略】,会弹出添加策略对话框,如下图所示:

在创建策略实例时,需要配置相关参数,各参数要求如下:
- 实例名称
- 实例名称不能重名;
- 合约品种
- 格式为vt_symbol(合约代码 + 交易所名称);
- 一定要是实盘交易系统中可以查到的合约名称;
- 一般选择该期货品种当前流动性最好的月份;
- 参数设置
- 显示的参数名是策略里写在parameters列表中的参数名;
- 默认数值为策略里的参数的默认值;
- 由上图可观察到,参数名后面<>括号中显示的是该参数的数据类型,在填写参数时应遵循相应的数据类型。其中,<class 'str'>是字符串、<class 'int'>是整数、<class 'float'>是浮点数;
- 请注意,如果某个参数可能会调整至有小数位的数值,而默认参数值是整数(比如1)。请在编写策略时,把默认参数值设为浮点数(比如1.0)。否则策略会默认该项参数为整数,在后续【编辑】策略实例参数时,会只允许填进整数。
参数配置完成后,点击【添加】按钮,则开始创建策略实例。创建成功后可在左侧的策略监控组件中看到该策略实例,如下图所示:

策略监控组件顶部显示的是策略实例名、合约品种名、策略类名以及策略作者名(在策略里定义的author)。顶部按钮用于控制和管理策略实例,第一行表格显示了策略内部的参数信息(参数名需要写在策略的parameters列表中图形界面才会显示),第二行表格则显示了策略运行过程中的变量信息(变量名需要写在策略的variables列表中图形界面才会显示)。【inited】字段表示当前策略的初始化状态(是否已经完成了历史数据回放),【trading】字段表示策略当前是否能够开始交易。
从上图可观察到,此时该策略实例的【inited】和【trading】状态都为【False】。说明该策略实例还没有初始化,也还不能发出交易信号。
策略实例创建成功后,该策略实例的配置信息会被保存到.vntrader文件夹下的cta_strategy_setting.json文件中。
### 创建失败
以下为创建策略实例失败的几种可能情况:
- 如果添加了同名的策略实例,则会创建失败,图形界面输出“创建策略失败,存在重名”的日志信息,如下图所示:


- 如果合约品种没有填写交易所名称,则会创建失败,图形界面输出“创建策略失败,本地代码缺失交易所后缀”的日志信息,如下图所示:


- 如果合约品种的交易所名称填错,则会创建失败,图形界面输出“创建策略失败,本地代码的交易所后缀不正确”的信息,如下图所示:


## 管理策略
### 初始化
策略实例创建成功后,就可以对该实例进行初始化了。点击该策略实例下的【初始化】按钮,若初始化成功,则如下图所示:

初始化过程中,主要按顺序完成了以下三步任务:
1. 获取历史数据
为了确保策略内指标数值的准确性,每个策略实例都需要一定的历史数据来进行策略初始化。
因此,在策略初始化时,策略实例内部的load_bar函数会先去接口获取最新历史数据。如果接口不提供历史数据,则通过配置的数据服务获取(以RQData为例,[RQData](https://www.ricequant.com/welcome/purchase?utm_source=vnpy)提供国内期货、股票以及期权的历史数据。RQData的数据服务提供盘中K线更新,即使在9点45分才启动策略,也能获取到之前从9点30开盘到9点45分之间的K线数据,提供给策略进行初始化计算,而不用担心数据缺失的问题)。如果没有配置数据服务,则通过访问本地数据库查询。这种情况下,用户需要保证数据库中的数据完整性(满足初始化需求),可以通过DataRecorder录制,或者使用DataManager从CSV文件导入。
具体载入数据的长度,取决于load_bar函数的参数控制(策略模板默认是10天)。数据载入后会以逐根K线(或者Tick)的方式推送给策略,实现内部变量的初始化计算,比如缓存K线序列、计算技术指标等。
2. 载入缓存变量
在每天实盘运行的过程中,量化策略中的有些变量只和历史行情数据相关,这类变量通过加载历史数据回放就能得到正确的数值。另一类变量则可能和交易状态相关,如策略的持仓、移动止损的最高价跟踪等,这类变量需要缓存在硬盘上(退出程序时),第二天回放完历史数据后再读取还原,才能保证和之前交易状态的一致性。
每次停止策略时,会自动将策略的variables列表对应的变量以及策略持仓缓存进.vntrader目录下的cta_strategy_data.json文件中,以便在下一次策略初始化时自动载入。
请注意,在某些情况下(比如手动平仓了),缓存的数据可能会出现偏差(因为策略持仓维护的是运行策略实例的逻辑持仓,不是特定品种的持仓),那么可以通过手动修改json文件来调整。
3. 订阅行情推送
最后基于vt_symbol参数获取该策略所交易合约的信息,并订阅该合约的实时行情推送。如果实盘交易系统找不到该合约的信息,比如没有连接登录接口或者vt_symbol填写错误,则会在日志模块中输出相应的报错信息。
以上三个步骤完成后,可观察到此时该策略实例的【inited】状态已经为【True】,且变量也都显示对应的数值(不再为0)。说明该策略实例已经调用过load_bar函数加载历史数据并完成初始化了。【trading】状态还是为【False】,说明此时该策略实例还不能开始自动交易。
### 初始化失败
以下为创建策略实例失败的几种可能情况:
- 即使交易所填的是VeighNa支持的交易所的名字,成功创建了策略实例。但是如果该合约名字输入错误(比如大小写错误,合约与交易所对不上或者已经退市),导致实盘交易系统找不到该合约,则会初始化失败。此时图形界面输出“行情订阅失败,找不到合约”的日志。如下图所示:

- 即使合约代码填写正确,成功创建了策略实例。但是如果此时还没有连接接口,或者接口合约信息查询合约操作还没有完成,导致实盘交易系统找不到该合约,也会初始化失败。此时图形界面输出“行情订阅失败,找不到合约”的日志。如下图所示:

如果出现了“行情订阅失败,找不到合约”这类问题,可以通过VeighNa Trader的主界面点击【帮助】-【查询合约】进行查询,找到正确的合约信息。如下图所示:

- 如果策略内用到了K线时间序列管理模块(ArrayManager)来计算变量指标的值,那么请确保历史数据的长度足够ArrayManager进行初始化(默认的ArrayManager需要100条数据才能初始化成功)。如果历史数据的长度不够ArrayManager初始化,即使图形界面上输出了日志“初始化完成”,该策略实例的初始化也是失败的。
- 如果策略逻辑是基于示例策略中的,一但ArrayManager没有初始化成功(if not am.inited)就返回了逻辑写的话,那么由下图可观察到,图形界面左侧的策略实例中基于ArrayManager计算的策略指标的值都是0。说明此时该策略实例虽然启动之后就可以开始自动交易了,但是因为ArrayManager没有初始化成功,策略内的逻辑每次走到ArrayManager初始化状态判断时就返回了,走不到计算指标进而发出交易信号的逻辑。进而该策略实例需要一直等到推进策略实例的数据足够ArrayManager初始化之后,满足ArrayManager初始化的判断条件,才能真正发出交易信号。

- 如果策略逻辑不是基于示例策略中的,一但ArrayManager没有初始化成功(if not am.inited)就返回的逻辑写的话,那么虽然图形界面左侧的策略实例中的策略指标有具体数值,而且此时启动可以发出交易信号,无需等待ArrayManager初始化完成。但是因为ArrayManager没有初始化成功,该策略实例计算出来的变量指标值是不准确的,进而可能会发出不符合策略预期的交易信号。
### 启动
策略实例初始化成功,【inited】状态为【True】时,才能启动自动交易功能。点击策略实例下的【启动】按钮,即可启动该策略实例。成功后如下图所示:

可观察到此时该策略实例的【inited】和【trading】状态都为【True】。说明此时该策略实例已经调用过load_bar函数,完成了历史数据回放,而且此时策略内部的交易请求类函数(buy/sell/short/cover/cancel_order等),以及信息输出类函数(send_email/put_event等),才会真正执行并发出对应的请求指令到底层接口中(真正执行交易)。
在上一步策略初始化的过程中,尽管策略同样在接收(历史)数据,并调用对应的功能函数,但因为【trading】状态为【False】,所以并不会有任何真正的委托下单操作或者交易相关的日志信息输出。
如果启动之后,策略发出了限价单,可以去VeighNa Trader主界面【委托】栏查看委托订单细节。如果策略发出了本地停止单,可以在CTA策略UI界面右上方区域的停止单监控组件查看委托订单细节。
### 停止
如果启动策略之后,由于某些情况(如到了市场收盘时间,或盘中遇到紧急情况)想要停止、编辑或者移除策略,可以点击策略实例下的【停止】按钮,即可停止该策略实例的自动交易。成功后如下图所示:

CTA策略引擎会自动将该策略之前发出的所有活动委托全部撤销,以保证在策略停止后不会有失去控制的委托存在。同时该策略实例最新的变量信息会被保存到.vntrader文件夹下的cta_strategy_data.json文件中。
此时可观察到该策略实例的【trading】状态已变为【False】,说明此时该策略实例已经停止自动交易了。
在CTA策略的实盘交易过程中,正常情况应该让策略在整个交易时段中都自动运行,尽量不要有额外的暂停重启类操作。对于国内期货市场来说,应该在交易时段开始前,启动策略的自动交易,然后直到收盘后,再关闭自动交易。因为现在CTP夜盘收盘后也会关闭系统,早上开盘前重启,所以夜盘收盘后也需要停止策略,关闭VeighNa Trader了。
### 编辑
如果创建策略实例之后,想要编辑某个策略实例的参数(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【编辑】按钮,会弹出参数编辑对话框,以供修改策略参数。如下图所示:

编辑完策略参数之后,点击下方的【确定】按钮,相应的修改会立即更新在参数表格中,如下图所示:

但是策略实例的交易合约代码无法修改,同时修改完后也不会重新执行初始化操作。也请注意,此时修改的只是.vntrader文件夹下cta_strategy_setting.json文件中该策略实例的参数值,并没有修改原策略文件下的参数。
修改前,json文件如下图所示:

修改后,json文件如下图所示:

若盘中编辑后想要再次启动策略,点击策略实例下的【启动】按钮即可再次启动该策略实例,如下图所示:

### 移除
如果创建策略实例之后,想要移除某个策略实例(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【移除】按钮。移除成功后,图形界面左侧的策略监控组件中将不会再显示该策略实例的信息。如下图所示:

此时.vntrader文件夹下的cta_strategy_setting.json文件也移除了该策略实例的配置信息。
### 状态跟踪
如果想要通过图形界面跟踪策略的状态,有两种方式:
1. 调用put_event函数
策略实例中所有的的变量信息,都需要把变量名写在策略的variables列表中,才能在图形界面显示。如果想跟踪变量的状态变化,则需要在策略中调用put_event函数,界面上才会进行数据刷新。
有时用户会发现自己写的策略无论跑多久,变量信息都不发生变化,这种情况请检查策略中是否漏掉了对put_event函数的调用。
2. 调用write_log函数
如果不仅想观察到变量信息的状态变化,还想根据策略的状态输出基于自己需求的个性化的日志,可以在策略中调用write_log函数,进行日志输出。
## 运行日志
### 日志内容
CTA策略模块UI界面上输出的日志有两个来源,分别是CTA策略引擎和策略实例。
**引擎日志**
CTA策略引擎一般输出的是全局信息。下图中除了以带中括号的策略实例名开头的内容之外,都是CTA策略引擎输出的日志。

**策略日志**
如果在策略中调用了write_log函数,那么日志内容就会通过策略日志输出。下图红框里的内容分别是两个不同的策略实例输出的策略日志。中括号里是策略实例的名称,中括号后是write_log函数输出的内容。

### 清空操作
如果想要清空CTA策略UI界面上的日志输出,可以点击右上角的【清空日志】按钮,则可一键清空该界面上已输出的日志。
点击【清空日志】前,如下图所示:

点击【清空日志】后,如下图所示:

## 停止单
图形界面右上方区域的停止单监控组件,是用来跟踪所有CTA引擎内本地停止单的状态变化的。
因为不是所有接口都支持停止单,所以VeighNa提供了本地停止单的功能。在交易接口不支持交易所停止单的前提下,用户依然可以通过策略的下单函数(buy/sell/short/cover),把stop参数设置为True,启用本地停止单功能。
VeighNa的本地停止单有三个特点:
1. 保存在本地电脑上,关机后则失效;
2. 只有交易员本人能够看到,不必担心泄露底牌;
3. 停止单触发有延时,导致一定的滑点。
**停止单信息**
在发出本地停止单后,图形界面右上方的监控组件就会显示停止单的委托细节。
本地停止单一共有【等待中】、【已触发】和【已撤销】三个状态,如下图所示:

停止单刚发出时是处于【等待中】的状态。因为停止单的信息记录在本地,没有发往交易所,所以此时主界面上【委托】栏不会有变化。
一旦该停止单的委托价格被触发,为了实现立即成交的目的,CTA策略引擎会立即以**涨跌停价**或者**盘口五档**的价格,去发出**限价**委托(所以建议本地停止单只用于流动性较好的合约)。限价委托发出后,VeighNa Trader主界面上【委托】栏将更新该订单的状态,此时停止单状态会变为【已触发】,【限价委托号】栏下也会填入该订单的限价委托号。
请注意,**停止单界面显示的价格是本地停止单的触发价格,而不是发出限价单的价格**。
如果停止单在被触发前就被策略取消了,那么该订单的状态就会变为【已撤销】。
## 批量操作
在策略经过充分测试,实盘运行较为稳定,不需要经常进行调整的情况下,如果有多个需要运行的CTA策略实例,可以使用界面右上角的【全部初始化】、【全部启动】和【全部停止】功能来执行盘前批量初始化、启动策略实例以及盘后批量停止策略实例的操作。
### 全部初始化
在所有策略实例创建成功后,点击右上角的【全部初始化】按钮,则可批量初始化策略实例。
点击【全部初始化】前,如下图所示:

点击【全部初始化】后,如下图所示:

### 全部启动
在所有策略实例初始化成功后,点击右上角的【全部启动】按钮,则可批量启动策略实例,如下图所示:

### 全部停止
在所有策略实例启动成功后,点击右上角的【全部停止】按钮,则可批量停止策略实例,如下图所示:

## 移仓助手
如需使用自动移仓助手,请在完成策略初始化之后,对要执行移仓的策略先点击【移仓助手】按钮,则会弹出移仓助手对话框,如下图所示:

首先请在在左侧区域配置要执行的移仓任务,其中:
- 移仓合约:该下拉框中,显示当前CTA策略模块下所有策略实例所交易的合约本地代码,选择要平仓掉的老合约;
- 目标合约:要将老的仓位和策略,移仓过去的的合约本地代码(vt_symbol),输入要开仓的新合约;
- 委托超价:执行移仓交易时,委托价格相对于当时盘口对价超出的pricetick。
完成配置确认无误后,点击【移仓】按钮开始执行,移仓过程中会有下图所示的日志输出,完成后该对话框会被设为锁死(变灰无法再点击):

可以看到几乎1秒内就完成了移仓合约对应的全部仓位和策略的移仓操作,同时CTA策略模块界面上的策略交易代码已经变为目标合约。
移仓过程中具体执行的任务步骤如下:
- 仓位移仓:
- 对当前账户内,移仓合约的【所有仓位】进行平仓(注意这里不会区分策略持仓还是手动交易持仓),并记录对应的仓位(多空分别记录);
- 对目标合约执行开仓交易,开仓的价格为当时的盘口对价加上超价pricetick,数量为上一步中记录的原有移仓合约持仓量。
- 策略移仓:
- 记录当前CTA策略模块中,所有交易对象为移仓合约的策略的【逻辑持仓】(注意这里的逻辑持仓和账户实际持仓不一定完全对应);
- 将上述交易对象为移仓合约的老策略实例删除,并创建以目标合约为交易标的同名新策略实例;
- 初始化新策略实例,并将之前记录的老策略实例的【逻辑持仓】,更新到新策略的状态上。
回到VeighNa Trader主界面,也可以查看到详细的移仓委托和成交记录。如下图所示:

## CTA策略模板(CtaTemplate)
CTA策略模板提供了信号生成和委托管理功能,用户可以基于该模板(位于site-packages\vnpy_ctastrategy\template中)自行开发CTA策略。
用户自行开发的策略可以放在用户运行文件夹下的[strategies](#jump)文件夹内。
请注意:
1. 策略文件命名采用下划线模式,如boll_channel_strategy.py,而策略类命名采用驼峰式,如BollChannelStrategy。
2. 自建策略的类名不要与示例策略的类名重合。如果重合了,图形界面上只会显示一个策略类名。
下面通过BollChannelStrategy策略示例,来展示策略开发的具体步骤:
在基于CTA策略模板编写策略逻辑之前,需要在策略文件的顶部载入需要用到的内部组件,如下方代码所示:
```python3
from vnpy_ctastrategy import (
CtaTemplate,
StopOrder,
TickData,
BarData,
TradeData,
OrderData,
BarGenerator,
ArrayManager
)
```
其中,CtaTemplate是CTA策略模板,StopOrder、TickData、BarData、TradeData和OrderData都是储存对应信息的数据容器,BarGenerator是K线生成模块,ArrayManager是K线时间序列管理模块。
### 策略参数与变量
在策略类的下方,可以设置策略的作者(author),参数(parameters)以及变量(variables),如下方代码所示:
```python3
author = "用Python的交易员"
boll_window = 18
boll_dev = 3.4
cci_window = 10
atr_window = 30
sl_multiplier = 5.2
fixed_size = 1
boll_up = 0
boll_down = 0
cci_value = 0
atr_value = 0
intra_trade_high = 0
intra_trade_low = 0
long_stop = 0
short_stop = 0
parameters = [
"boll_window",
"boll_dev",
"cci_window",
"atr_window",
"sl_multiplier",
"fixed_size"
]
variables = [
"boll_up",
"boll_down",
"cci_value",
"atr_value",
"intra_trade_high",
"intra_trade_low",
"long_stop",
"short_stop"
]
```
虽然策略的参数和变量都从属于策略类,但策略参数是固定的(由交易员从外部指定),而策略变量则在交易的过程中随着策略的状态而变化,所以策略变量一开始只需要初始化为对应的基础类型。例如:整数设为0,浮点数设为0.0,而字符串则设为""。
如果需要CTA引擎在运行过程中,将策略参数和变量显示在UI界面上,并在数据刷新、停止策略时保存其数值,则需把参数和变量的名字(以字符串的数据类型)添加进parameters和variables列表里。
请注意,该列表只能接受参数或变量以str、int、float和bool四种数据类型传入。如果策略里需要用到其他数据类型的参数与变量,请把该参数或变量的定义放到__init__函数下。
### 类的初始化
入参:cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict
出参:无
__init__函数是策略类的构造函数,需要与继承的CtaTemplate保持一致。
在这个继承的策略类里,初始化一般分三步,如下方代码所示:
```python3
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
""""""
super().__init__(cta_engine, strategy_name, vt_symbol, setting)
self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
self.am = ArrayManager()
```
1 . 通过super( )的方法继承CTA策略模板,在__init__( )函数中传入CTA引擎、策略名称、vt_symbol以及参数设置。注意其中的CTA引擎,可以是实盘引擎或者回测引擎,这样可以方便地**实现同一套代码同时跑回测和实盘**(以上参数均由策略引擎在使用策略类创建策略实例时自动传入,用户无需进行设置)。
2 . 调用K线生成模块(BarGenerator):通过时间切片将Tick数据合成1分钟K线数据。如有需求,还可合成更长的时间周期数据,如15分钟K线。
如果只基于on_bar进行交易,这里代码可以写成:
```python3
self.bg = BarGenerator(self.on_bar)
```
而不用给bg实例传入需要基于on_bar周期合成的更长K线周期,以及接收更长K线周期的函数名。
请注意,合成X分钟线时,X必须设为能被60整除的数(60除外)。对于小时线的合成没有这个限制。
BarGenerator默认的基于on_bar函数合成长周期K线的数据频率是分钟级别,如果需要基于合成的小时线或者更长周期的K线交易,请在策略文件顶部导入Interval,并传入对应的数据频率给bg实例。如下方代码所示:
文件顶部导入Interval:
```python3
from vnpy.trader.constant import Interval
```
__init__函数创建bg实例时传入数据频率:
```python3
self.bg = BarGenerator(self.on_bar, 2, self.on_2hour_bar, Interval.HOUR)
```
3 . 调用K线时间序列管理模块(ArrayManager):基于K线数据,如1分钟、15分钟,
将其转化为便于向量化计算的时间序列数据结构,并在内部支持使用talib库来计算相应的技术指标。
ArrayManager的默认长度为100,如需调整ArrayManager的长度,可传入size参数进行调整(size不能小于计算指标的周期长度)。
### CTA策略引擎调用的函数
CtaTemplate中的update_setting函数和该函数后面四个以get开头的函数,都是CTA策略引擎去负责调用的函数,一般在策略编写的时候是不需要调用的。
### 策略的回调函数
CtaTemplate中以on开头的函数称为回调函数,在编写策略的过程中能够用来接收数据或者接收状态更新。回调函数的作用是当某一个事件发生的时候,策略里的这类函数会被CTA策略引擎自动调用(无需在策略中主动操作)。回调函数按其功能可分为以下三类:
#### 策略实例状态控制(所有策略都需要)
**on_init**
* 入参:无
* 出参:无
初始化策略时on_init函数会被调用,默认写法是先调用write_log函数输出“策略初始化”日志,再调用load_bar函数加载历史数据,如下方代码所示:
```python3
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bar(10)
```
请注意,如果是基于Tick数据回测,请在此处调用load_tick函数。
策略初始化时,策略的inited和trading状态都为【False】,此时只是调用ArrayManager计算并缓存相关的计算指标,不能发出交易信号。调用完on_init函数之后,策略的inited状态才变为【True】,策略初始化才完成。
**on_start**
* 入参:无
* 出参:无
启动策略时on_start函数会被调用,默认写法是调用write_log函数输出“策略启动”日志,如下方代码所示:
```python3
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
```
调用策略的on_start函数启动策略后,策略的trading状态变为【True】,此时策略才能够发出交易信号。
**on_stop**
* 入参:无
* 出参:无
停止策略时on_stop函数会被调用,默认写法是调用write_log函数输出“策略停止”日志,如下方代码所示:
```python3
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
```
调用策略的on_stop函数停止策略后,策略的trading状态变为【False】,此时策略就不会发出交易信号了。
#### 接收数据、计算指标、发出交易信号
**on_tick**
* 入参:tick: TickData
* 出参:无
绝大部分交易系统都只提供Tick数据的推送。即使一部分平台可以提供K线数据的推送,但是这些数据到达本地电脑的速度也会慢于Tick数据的推送,因为也需要平台合成之后才能推送过来。所以实盘的时候,VeighNa里所有的策略的K线都是由收到的Tick数据合成的。
当策略收到最新的Tick数据的行情推送时,on_tick函数会被调用。默认写法是通过BarGenerator的update_tick函数把收到的Tick数据推进前面创建的bg实例中以便合成1分钟的K线,如下方代码所示:
```python3
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
self.bg.update_tick(tick)
```
**on_bar**
* 入参:bar: BarData
* 出参:无
当策略收到最新的K线数据时(实盘时默认推进来的是基于Tick合成的一分钟的K线,回测时则取决于选择参数时填入的K线数据频率),on_bar函数就会被调用。示例策略里出现过的写法有两种:
1 . 如果策略基于on_bar推进来的K线交易,那么请把交易请求类函数都写在on_bar函数下(因本次示例策略类BollChannelStrategy不是基于on_bar交易,故不作示例讲解。基于on_bar交易的示例代码可参考其他示例策略);
2 . 如果策略需要基于on_bar推进来的K线数据通过BarGenerator合成更长时间周期的K线来交易,那么请在on_bar中调用BarGenerator的update_bar函数,把收到的这个bar推进前面创建的bg实例中即可,如下方代码所示:
```python3
def on_bar(self, bar: BarData):
"""
Callback of new bar data update.
"""
self.bg.update_bar(bar)
```
示例策略类BollChannelStrategy是通过15分钟K线数据回报来生成CTA信号的。一共有三部分,如下方代码所示:
```python3
def on_15min_bar(self, bar: BarData):
""""""
self.cancel_all()
am = self.am
am.update_bar(bar)
if not am.inited:
return
self.boll_up, self.boll_down = am.boll(self.boll_window, self.boll_dev)
self.cci_value = am.cci(self.cci_window)
self.atr_value = am.atr(self.atr_window)
if self.pos == 0:
self.intra_trade_high = bar.high_price
self.intra_trade_low = bar.low_price
if self.cci_value > 0:
self.buy(self.boll_up, self.fixed_size, True)
elif self.cci_value < 0:
self.short(self.boll_down, self.fixed_size, True)
elif self.pos > 0:
self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
self.intra_trade_low = bar.low_price
self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
self.sell(self.long_stop, abs(self.pos), True)
elif self.pos < 0:
self.intra_trade_high = bar.high_price
self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
self.cover(self.short_stop, abs(self.pos), True)
self.put_event()
```
- 清空未成交委托:为了防止之前下的单子在上一个15分钟没有成交,但是下一个15分钟可能已经调整了价格,就用cancel_all()方法立刻撤销之前未成交的所有委托,保证策略在当前这15分钟开始时的整个状态是清晰和唯一的;
- 调用K线时间序列管理模块:基于最新的15分钟K线数据来计算相应的技术指标,如布林带通道上下轨、CCI指标、ATR指标等。首先获取ArrayManager对象,然后将收到的K线推送进去,检查ArrayManager的初始化状态,如果还没初始化成功就直接返回,没有必要去进行后续的交易相关的逻辑判断。因为很多技术指标计算对最少K线数量有要求,如果数量不够的话计算出来的指标会出现错误或无意义。反之,如果没有return,就可以开始计算技术指标了;
- 信号计算:通过持仓的判断以及结合CCI指标、布林带通道、ATR指标在通道突破点挂出停止单委托(buy/sell),同时设置离场点(short/cover)。
请注意,如果需要在图形界面刷新指标数值,请不要忘记调用put_event()函数。
#### 委托状态更新
以下函数在策略中可以直接pass,其具体逻辑应用交给回测/实盘引擎负责。
**on_trade**
* 入参:trade: TradeData
* 出参:无
收到策略成交回报时on_trade函数会被调用。
**on_order**
* 入参:order: OrderData
* 出参:无
收到策略委托回报时on_order函数会被调用。
**on_stop_order**
* 入参:stop_order: StopOrder
* 出参:无
收到策略停止单回报时on_stop_order函数会被调用。
### 主动函数
**buy**:买入开仓(Direction:LONG,Offset:OPEN)
**sell**:卖出平仓(Direction:SHORT,Offset:CLOSE)
**short**:卖出开仓(Direction:SHORT,Offset:OPEN)
**cover**:买入平仓(Direction:LONG,Offset:CLOSE)
* 入参:price: float, volume: float, stop: bool = False, lock: bool = False, net: bool = False
* 出参:vt_orderids: List[vt_orderid] / 无
buy/sell/short/cover都是策略内部的负责发单的交易请求类函数。策略可以通过这些函数给CTA策略引擎发送交易信号来达到下单的目的。
以下方buy函数的代码为例,可以看到,价格和数量是必填的参数,停止单转换、锁仓转换和净仓转换则默认为False。也可以看到,函数内部收到传进来的参数之后就调用了CtaTemplate里的send_order函数来发单(因为是buy指令,则自动把方向填成了LONG,开平填成了OPEN)
如果stop设置为True,那么该笔订单则会自动转成停止单,如果接口支持交易所停止单则会转成交易所停止单,如果接口不支持交易所停止单则会转换成VeighNa的本地停止单。
如果lock设置为True,那么该笔订单则会进行锁仓委托转换(在有今仓的情况下,且交易的交易所不是指定平今平昨的交易所,会直接反向开仓。在有昨仓的情况下,如果想平仓,则会先平掉所有的昨仓,然后剩下的部分都进行反向开仓来代替平今仓,以避免平今的手续费惩罚)。
如果net设置为True,那么该笔订单则会进行净仓委托转换(基于整体账户的所有仓位,根据净仓持有方式来对策略下单的开平方向进行转换)。但是净仓交易模式与锁仓交易模式互斥,因此net设置为True时,lock必须设置为False。
请注意,如果向上期所发出平仓委托,因为该交易所必须指定平今、平昨,底层会对其平仓指令自动进行转换。因为上期所部分品种有平今优惠,所以默认是以平今优先的方式发出委托的(如果交易的标的在上期所平昨更优惠的话,可以自行在vnpy.trader.converter的convert_order_request_shfe函数中做适当的修改)。
```python3
def buy(self, price: float, volume: float, stop: bool = False, lock: bool = False, net: bool = False):
"""
Send buy order to open a long position.
"""
return self.send_order(Direction.LONG, Offset.OPEN, price, volume, stop, lock, net)
```
请注意,国内期货有开平仓的概念,例如买入操作要区分为买入开仓和买入平仓;但对于股票、外盘期货都是净持仓模式,没有开仓和平仓概念,所以只需使用买入(buy)和卖出(sell)这两个指令就可以了。
**send_order**
* 入参:direction: Direction, offset: Offset, price: float, volume: float, stop: bool = False, lock: bool = False, net: bool = False
* 出参:vt_orderids / 无
send_order函数是CTA策略引擎调用的发送委托的函数。一般在策略编写的时候不需要单独调用,通过buy/sell/short/cover函数发送委托即可。
实盘的时候,收到传进来的参数后,会调用round_to函数基于合约的pricetick和min_volume对委托的价格和数量进行处理。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能发出交易委托。如果策略的Trading状态为【False】时调用了该函数,只会返回[]。
**cancel_order**
* 入参:vt_orderid: str
* 出参:无
**cancel_all**
* 入参:无
* 出参:无
cancel_order和cancel_all都是负责撤单的交易请求类函数。cancel_order是撤掉策略内指定的活动委托,cancel_all是撤掉策略所有的活动委托。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能撤单。
### 功能函数
以下为策略以外的功能函数:
**write_log**
* 入参:msg: str
* 出参:无
在策略中调用write_log函数,可以进行指定内容的日志输出。
**get_engine_type**
* 入参:无
* 出参:engine_type: EngineType
如果策略对于回测和实盘时有不同的逻辑处理,可以调用get_engine_type函数获取当下使用的引擎类型来进行逻辑判断。
请注意,如果要调用该函数进行逻辑判断,请在策略文件顶部导入“EngineType”。
**get_pricetick**
* 入参:无
* 出参:pricetick: float / None
在策略中调用get_pricetick函数,可以获取交易合约的最小价格跳动。
**load_bar**
* 入参:days: int, interval: Interval = Interval.MINUTE, callback: Callable = None, use_database: bool = False
* 出参:无
在策略中调用load_bar函数,可以在策略初始化时加载K线数据。
如下方代码所示,调用load_bar函数时,默认加载的天数是10,频率是一分钟,对应也就是加载10天的1分钟K线数据。10天指的是10个自然日,建议加载的天数宁可多一些也不要太少。use_database参数默认为False,会先依次尝试通过交易接口、数据服务、数据库获取历史数据,直到获取历史数据或返回空。当use_database设置为True后,会跳过通过交易接口和数据服务获取历史数据,直接去数据库查询。
```python3
def load_bar(
self,
days: int,
interval: Interval = Interval.MINUTE,
callback: Callable = None,
use_database: bool = False
):
"""
Load historical bar data for initializing strategy.
"""
if not callback:
callback = self.on_bar
self.cta_engine.load_bar(
self.vt_symbol,
days,
interval,
callback,
use_database
)
```
**load_tick**
* 入参:days: int
* 出参:无
在策略中调用load_tick函数,可以在策略初始化时加载Tick数据。
**put_event**
* 入参:无
* 出参:无
在策略中调用put_event函数,可以通知图形界面刷新策略状态相关显示。
请注意,要策略初始化完成,inited状态变为【True】之后,才能刷新界面。
**send_email**
* 入参:msg: str
* 出参:无
配置好邮箱相关信息之后(配置方法详见基本使用篇的全局配置部分),在策略中调用send_email函数,可以发送指定内容的邮件到自己的邮箱。
请注意,要策略初始化完成,inited状态变为【True】之后,才能发送邮件。
**sync_data**
* 入参:无
* 出参:无
在策略中调用sync_data函数,可以在实盘交易的时候,每次停止或成交时都同步策略变量到对应json文件中进行本地缓存,方便第二天初始化时再进行读取还原(CTA策略引擎会去调用,在策略里无需主动调用)。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能同步策略信息。
================================================
FILE: docs/community/app/data_manager.md
================================================
# DataManager - 历史数据管理模块
## 功能简介
DataManager是用于**历史数据管理**的功能模块,用户可以通过其UI界面操作来便捷完成数据下载、数据查看、数据导入和数据导出等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【DataManager】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_datamanager import DataManagerApp
# 写在创建main_engine对象后
main_engine.add_app(DataManagerApp)
```
## 启动模块
启动VeighNa Trader后,在菜单栏中点击【功能】-> 【数据管理】,或者点击左侧按钮栏的图标:

即可进入历史数据管理UI界面,如下图所示:

## 下载数据
DataManager模块提供了一键下载历史数据的功能,点击右上角【下载数据】按钮,会弹出下载历史数据窗口,如下图所示:

需要填写代码、交易所、周期以及开始日期四个字段信息:
<span id="jump">
- 代码
- 代码格式为合约品种
- 如IF888、rb2105
- 交易所
- 合约交易的交易所(点击窗口右侧箭头按钮可选择VeighNa支持的交易所列表)
- 周期
- MINUTE(1分钟K线)
- HOUR(1小时K线)
- DAILY(日K线)
- WEEKLY(周K线)
- TICK(一个Tick)
- 开始日期
- 格式为yy/mm/dd
- 如2018/2/25
</span>
填写完成后,点击下方【下载】按钮启动下载程序,下载成功如下图所示:

注意下载完成后的历史数据会保存在本地数据库中,后续回测或实盘时可以直接使用,无需每次都重复下载。
### 数据来源:数据服务(期货、股票、期权)
以RQData为例,[RQData](https://www.ricequant.com/welcome/purchase?utm_source=vnpy)提供国内期货、股票以及期权的历史数据。在使用前需要保证数据服务已经正确配置(配置方法详见基本使用篇的全局配置部分)。
### 数据来源:IB(外盘期货、股票、现货等)
Interactive Brokers盈透证券(IB)提供丰富的外盘市场历史数据下载(包括股票、期货、期权、现货等),注意下载前需要先启动IB TWS交易软件,并在VeighNa Trader主界面连接好IB接口,并订阅所需合约行情。
## 导入数据
如果已经从其他渠道获取到了CSV格式的数据文件,可以通过DataManager的数据导入功能,将其快速导入VeighNa数据库。点击右上角的【导入数据】按钮,会弹出从如下图所示的对话框:

点击顶部的【选择文件】按钮,会弹出窗口选择要导入的CSV文件路径,如下图所示:

然后配置数据导入的相关细节:
- 合约信息
- 格式详见本章[下载数据](#jump)部分的介绍;
- 请注意,导入的合约代码(symbol)和交易所(exchange)两个字段组合起来,才能构成在CTA回测等模块中使用的本地代码(vt_symbol);
- 若合约代码为**IF2003**,交易所选择**CFFEX**(中金所),则在CtaBacktester中回测要用到的本地代码应为**IF2003.CFFEX**;
- 可以对时间戳时区进行选择;
- 表头信息
- 可查看CSV文件的表头信息,并将对应的表头字符串输入在表头信息中;
- 对于CSV文件中不存在的字段(如股票数据没有【持仓量】字段),请留空即可;
- 格式信息
- 采用Python内置库datetime模块的时间格式定义,来解析时间戳字符串;
- 默认时间格式为"%Y-%m-%d %H:%M:%S",对应的是"2017-1-3 0:00:00";
- 如果时间戳是"2017-1-3 0:00",那么时间格式应该是"%Y-%m-%d %H:%M"。
填写完毕,则如下图所示:

点击【确定】按钮,开始从CSV文件导入数据到数据库中。导入过程中界面会处于半卡住的情况,CSV文件越大(数据量越多),卡住的时间也会越长。成功载入之后,会弹出窗口显示载入成功,如下图所示:

## 查看数据
目前VeighNa Trader中获取数据的方式一共有三种:
- 通过数据服务或者交易接口下载
- 从CSV文件导入
- 使用DataRecorder模块录制
不管采用何种方法获取数据,点击左上角的【刷新】按钮,即可看到当前数据库中已有数据的统计情况(Tick数据除外)。刷新过程中界面可能会有偶尔的卡顿,通常对于越多的数据,卡顿的时间也会越长。刷新成功之后,如下图所示:

点击【查看】按钮,则会弹出选择数据要查看数据区间的对话框,如下图所示:

选择好要显示的数据范围后,点击【确定】按钮即可在右侧表格中看到每个时间点上具体的数据字段:

在数据库已有数据的前提下,点击表格最左侧【数据】列下的数据频率前的小箭头,则可展开或收起该数据频率下的合约信息显示。
若表格的右侧区域显示不完整,可拖动界面底端的横向滚动条进行调整。
## 导出数据
如果想导出数据库中的数据到本地CSV文件,则可选择要导出的合约,点击该合约所在行右侧的【导出】按钮后,会弹出选择数据区间对话框,如下图所示:

选择要导出的数据区间范围,点击【确定】后,会再次弹出对话框选择输出文件的位置,如下图所示:

选择好导出文件要放置的目录,填写完CSV文件名之后,点击【保存】按钮即可完成CSV文件的导出。
## 删除数据
若想删除特定合约数据,则可选择要删除的合约,点击该合约行数据右侧的【删除】按钮后,会弹出对话框,如下图所示:

点击【OK】按钮即可删除该合约数据,并弹出删除成功窗口,如下图所示:

此时再点击【刷新】按钮,图形界面上已经没有该合约的信息了,如下图所示:

## 更新数据
在用户**配置了数据服务**或者**交易接口(已连接)提供充足的历史数据**的情况下,点击右上角的【更新数据】按钮,即可基于图形界面上显示的所有合约数据,执行一键自动下载更新。
更新前图形界面显示如下图:

点击【更新数据】按钮,会弹出更新进度的信息提示对话框,如下图所示:

此时DataManager会自动**从数据库中已有数据的结束日期开始,下载截止到当前最新日期**的数据,并更新到数据库中。
如果需要更新的数据较少,则可能瞬间完成更新任务,此时没有观察到更新对话框也是正常的。
更新完成后,点击左上角【刷新】按钮,即可看到该合约数据已更新至当前最新日期。

## 数据范围
请注意,虽然界面上显示了数据库中已有数据的开始和结束时间,**但并不代表数据库中储存了从开始时间到结束时间之间所有的数据**。
如果依赖于交易接口提供的历史数据,一但开始时间和结束时间之间的时间跨度超过接口所能提供的数据范围,就可能导致数据之间出现缺失的情况。因此建议更新数据之后,点击【查看】按钮检查一下该合约数据是否连续。
================================================
FILE: docs/community/app/data_recorder.md
================================================
# DataRecorder - 实盘行情记录模块
DataRecorder是用于**实盘行情记录**的模块,用户可以利用该模块记录实时Tick数据和K线数据,并自动写入保存到数据库中。
记录的数据可以通过DataManager模块查看,也可以用于CtaBacktester的历史回测,以及CtaStrategy、PortfolioStrategy等策略的实盘初始化。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【DataRecorder】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_datarecorder import DataRecorderApp
# 写在创建main_engine对象后
main_engine.add_app(DataRecorderApp)
```
## 启动模块
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分),看到VeighNa Trader主界面【日志栏】输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【行情记录】,或者点击左侧按钮栏的图标:

即可启动DataRecorder,并弹出DataRecorder的UI界面,如下图所示:

## 添加记录
DataRecorder模块支持按需添加K线(1分钟)和Tick数据的记录任务:
1. 在【本地代码】编辑框中输入需要录制的合约本地代码(vt_symbol),如下图所示:

- 注意本地代码由代码前缀和交易所后缀两部分组成,如rb2112.SHFE;
- 编辑框对于接口连接后收到的合约信息,提供自动补全功能(大小写敏感);
2. 在【写入间隔】编辑框中选择定时批量写入频率,如下图所示:

这样可以每次从队列中先取出所有待记录数据,再一次性把队列中已有数据写入数据库,从而降低数据库压力和记录延迟;
3. 点击右侧【K线记录】或者【Tick记录】对应的【添加】按钮添加录制任务:
- 添加成功后,合约本地代码会出现在下方的【K线记录列表】或者【Tick记录列表】中,并在界面下方输出对应日志,如下图所示:

## 移除记录
当不再需要记录某一合约的行情时,可以移除其对应的录制任务:
1. 在【本地代码】编辑框中输入需要移除录制任务的合约本地代码(vt_symbol);
2. 点击右侧【K线记录】或者【Tick记录】对应的【移除】按钮移除相应录制任务。
移除成功,【K线记录列表】或者【Tick记录列表】下对应的录制任务信息会被移除,并在界面下方输出对应日志,如下图所示:

================================================
FILE: docs/community/app/excel_rtd.md
================================================
# ExcelRtd - EXCEL RTD模块
## 功能简介
ExcelRtd是用于**在Excel中访问VeighNa程序内任意数据信息**的功能模块,
RTD全称是RealTimeData,是微软提供的主要面向金融行业中实时数据需求设计的Excel数据对接方案。ExcelRtd依赖于PyXLLC模块(www.pyxll.com),该模块属于商业软件,需要购买才能使用(提供30天免费使用)。
## 安装PyXLL
为了使用ExcelRtd模块,需要安装PyXLL插件。步骤如下:
首先进入[PyXLL官网](https://www.pyxll.com/),点击DownloadPyXLL,如下图所示:

接着跳转到下载界面,如下图所示:

这时需要填写相应字段,其中**Python Version**选择Python3.10,而**Excel Version**则根据自己安装的Excel版本选择,一般为64bit(x64)。
填写完之后点击【Download PyXLL】,就会跳转到下载页面。将文件下载好之后,进入放置该文件的文件夹,按住shift键并且点击鼠标右键,选择【在此处打开PowerShell窗口】,运行以下命令:
```bash
pip install pyxll
pyxll install
```
接着按照软件要求就能成功安装了。
请注意,在执行到下图这一步时:

如果没有具体指定路径,会安装到图中的默认位置(因为后面还需要进入这个文件夹,所以请记住这个路径)。
接着进入该目录下的examples目录,并把路径~/veighna_studio/Lib/site-packages/vnpy_excelrtd/下的vnpy_rtd.py放入该目录,如下图所示:

如此就算正式安装完成了。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【ExcelRtd】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_excelrtd import ExcelRtdApp
# 写在创建main_engine对象后
main_engine.add_app(ExcelRtdApp)
```
## 启动模块
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】 -> 【Excel RTD】,或者点击左侧按钮栏的图表:

即可进入Excel RTD模块的UI界面,如下图所示:

## 功能和配置
### 基础应用
在启动Excel RTD模块后,即可在Excel表格中通过PyXll调用该模块提供的功能(主要是通过rtd_tick_data函数获取实时数据)。
首先打开一个excel表格,并且在每个单元格中调用rtd_tick_data函数并传入相应参数则可获取对应的数据,如下图所示:

上图是获取豆油2205四个字段实时数据(分别是bid_price_1、high_price、low_price以及last_price)的例子。
从图中可以看出rtd_tick_data函数需要两个参数:一个是vt_symbol,另一个是VeighNa中定义的TickData的属性(具体属性可参考源代码vnpy.trader.object.TickData)。这两个参数都是字符串,第一个参数可以通过单元格的具体位置指定,比如“A1”表示A列第1行的数据。
与此同时,在Excel RTD模块的图形界面中也能看到相应输出,如下图所示:

### 进阶应用
当然,上面只是简单的展示了ExcelRtd模块的功能。至于具体获取哪些数据,以什么样的方式展示在excel上,则由用户根据自己的实际需求编写。这里提供几个进阶的案例,包括期货市场报价跟踪、市场深度行情跟踪以及价差监控:
#### 期货市场报价跟踪

#### 市场深度行情跟踪

#### 价差监控

================================================
FILE: docs/community/app/index.rst
================================================
策略应用
~~~~~~~~~
.. toctree::
:maxdepth: 2
:caption: Elite版
cta_strategy.md
cta_backtester.md
spread_trading.md
option_master.md
portfolio_strategy.md
algo_trading.md
script_trader.md
paper_account.md
data_recorder.md
data_manager.md
risk_manager.md
rpc_service.md
chart_wizard.md
portfolio_manager.md
excel_rtd.md
web_trader.md
================================================
FILE: docs/community/app/option_master.md
================================================
# OptionMaster - 期权波动率交易模块
## 功能简介
OptionMaster是用于**期权波动率交易**的功能模块,用户可以通过OptionMaster完成期权实时定价、波动率曲面跟踪、持仓希腊值监控、组合压力测试、电子眼自动交易等功能。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【OptionMaster】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_optionmaster import OptionMasterApp
# 写在创建main_engine对象后
main_engine.add_app(OptionMasterApp)
```
## 启动模块
启动VeighNa Trader后,在菜单栏中点击【功能】-> 【期权交易】,或者点击左侧按钮栏的图标:

即可进入OptionMaster管理界面(下称管理界面),如下图所示:

## 配置组合
在管理界面上,选择要交易的期权产品,点击【配置】按钮打开如下图所示的组合配置对话框:

配置参数如下:
* 定价模型
* Black-76模型:针对欧式期货期权(股指期权);
* Black-Scholes模型:针对欧式股票期权(ETF期权);
* Binomial-Tree模型:针对美式期货期权(商品期权);
* 年化利率
* 定价模型中用到的无风险折现利率;
* 合约模式
* 正向:包括ETF期权、期货期权、股指期权等大多数产品;
* Greeks小数位
* 显示希腊值时保留的小数位数;
* 期权链对应的定价标的
* 注意只有选择了标的物的期权链,才会被加入交易组合;
* 定价标的物支持
* 期货合约:交易所本身提供的期货价格;
* 合成期货:基于期权价格算出的合成期货价格;
* OptionMaster在定价计算过程中会对标的物价格相对期权链的升贴水进行自动修正,因此推荐选择交易最活跃的合约作为标的物。
点击底部的【确认】按钮,完成期权组合的初始化,此时管理界面上的【配置】按钮会被锁定,而其他按钮则会被激活。
## 行情监控
点击管理界面的【T型报价】按钮,打开T型报价窗口:

窗口整体分为左右区域,中间白色列为行权价,左侧为看涨期权,右侧为看跌期权。
每行显示的为某一行权价期权对应的信息,从外向内显示的信息包括:
* 合约代码
* 期权的实时现金希腊值
* Vega
* Theta
* Gamma
* Delta
* 交易信息
* 持仓量
* 成交量
* 1档盘口信息
* 买隐波
* 买量
* 买价
* 卖价
* 卖量
* 卖隐波
* 净持仓
## 快速交易
点击管理界面的【快速交易】按钮,打开手动下单窗口:

整体使用方法和VeighNa Trader主界面的交易组件相似,输入合约代码、买卖方向、开平方向、交易价格和数量后,点击【委托】按钮即可发出限价委托,点击【全撤】按钮即可一键全撤当前的全部活动委托。
双击T型报价中某一期权的单元格,可以快速填充本窗口的【代码】编辑框。
## 持仓希腊值
点击管理界面的【持仓希腊值】按钮,打开希腊值风险监控窗口:

窗口中的监控信息分为四个维度:
* 交易组合(包括所有下属期权链和标的物汇总数据)
* 标的物合约
* 期权链(包括所有下属期权汇总数据)
* 期权合约
每个维度的监控信息包括:
* 持仓相关
* 多仓:当前的多头持仓
* 空仓:当前的空头持仓
* 净仓:多仓 - 空仓
* 总希腊值
* Delta:标的价格涨跌1%对应的该维度盈亏金额
* Gamma:标的价格涨跌1%对应的该维度的Delta变动
* Theta:每过去一个交易日,该维度的盈亏金额
* Vega:隐含波动率涨跌1%对应的该维度的盈亏金额
## 升贴水监控
点击管理界面的【升贴水监控】按钮,打开期权链定价升贴水校准幅度的监控窗口:

以上图为例,可以看到:
* IO2104,以对应月份期货IF2104定价,升贴水接近0;
* IO2105、IO2106、IO2109,以活跃合约IF2104定价,贴水依次增加;
* IO2112、IO2203,以对应月份的合成期货定价,升贴水为0。
## 波动率曲线
点击管理界面的【波动率曲线】按钮,打开当前的市场波动率曲线监控图表:

图表中每个期权链的波动率曲线采用不同颜色显示,具体颜色对应期权链的图例在左侧。
每个期权链会包括三条曲线:
* 向上箭头:该月份看涨期权的1档盘口隐含波动率中值,即买1价和卖1价盘口波动率的均值;
* 向下箭头:该月份看跌期权的1档盘口隐含波动率中值;
* 小圆点:该月份定价波动率的数值,定价波动率用于希腊值计算和电子眼交易,通过后面的【波动率管理】组件设置。
图表中显示的曲线通过窗口顶部每个期权链对应的勾选框来控制,可以根据需求进行调整,如下图中只显示了IO2109这一个期权链:

## Delta对冲
点击管理界面的【Delta对冲】按钮,打开交易组合的Delta自动对冲功能:

* 对冲标的:可以选择投资组合内的任意一个标的物合约;
* 执行频率:多久执行一次检查,判断是否要执行对冲;
* Delta目标:如果触发对冲,将Delta值对冲到多少;
* 选择0,即为保持整体组合的Delta中性;
* 选择正数,即为保持整体组合的Delta多头敞口;
* 选择负数,即为保持整体组合的Delta空头敞口;
* Delta范围:当仓位类型的Delta值偏离上述Delta目标超过多少时,触发对冲任务;
* 委托超价:发出对冲委托时,价格相对于对面盘口的超价;
点击【启动】按钮即可启动自动对冲功能,当读秒达到执行间隔时即会执行一次检查,如果满足条件则会启动TWAP算法执行对冲操作。
点击【停止】按钮即可停止自动对冲功能的运行。
## 情景分析
点击管理界面的【情景分析】按钮,打开交易组合整体持仓风险的压力测试和情景分析功能:

首先配置执行的分析任务:
* 目标数据:支持盈亏、Delta、Gamma、Theta、Vega;
* 时间衰减:交易日的衰减天数;
* 价格变动:
* 分析中价格的涨跌变动范围;
* 假设单前价格为100,变动为10%,则范围为90~110;
* 波动率变动:
* 分析中波动率的涨跌变动范围;
* 假设当前波动率为20%,变动为10%,则范围为10%~30%。
点击执行分析按钮后,压力测试引擎会根据当前的交易组合持仓,以及每个情景下的价格和隐含波动率情况,来计算对应的目标数据,并将结果绘制为3D曲面。
下图显示的是以Gamma值为计算目标,10%价格变动,15%波动率变动的结果:

该3D图中的垂直轴为计算目标的数值,水平的两轴分别为价格和波动率的变动数值。
## 波动率管理
点击管理界面的【波动率管理】按钮,打开定价波动率管理界面:

点击顶部的期权链标签切换对应期权链的定价波动率管理组件,第一次打开时下方表格中的【定价隐波】数值均为0。
首先进行定价曲线的初始化,点击顶部的【重置】按钮,将当前该行权价的虚值期权的中值隐波,映射到定价隐波上。
映射完成后可以在波动率图表中查看当前的定价波动率曲线形状,如果某一行权价的定价隐波和整体曲线相比存在不平滑的情况,则可以基于相对平滑的行权价的定价隐波对其进行拟合。
在组件表格中的【执行拟合】列,勾选要执行拟合的行权价勾选框,勾选完成后点击顶部的【拟合】按钮,即可基于OptionMaster内置的Cubic Spline(三项式差值)算法来执行波动率曲线的拟合。
拟合完成后如果还存在不满意的部分,则可以通过【定价隐波】列的滚动框来进行手动微调,点击上下箭头每次上升或者下跌0.1%,或者也可以直接输入想要修改的数值。
当因为对波动率曲线高低的整体观点,需要对曲线进行整体平移时,可以通过组件顶部的【+0.1%】和【-0.1%】按钮,来对所有行权价的定价波动率进行平移调整。
## 电子眼
点击管理界面的【电子眼】按钮,打开交易组合的电子眼自动套利算法功能:

电子眼算法可以基于交易员预设的定价波动率曲线,在允许的持仓范围内自动捕捉市场上出现的瞬时交易执行机会,同时结合Delta自动对冲功能来保证投资组合的整体Delta中性。
电子眼界面类似T型报价分为左右区域,中间的白色为行权价,左侧为看涨期权,右侧为看跌期权。每个期权上对应存在一个独立的电子眼交易算法,交易员可以同时启动数百个交易算法(具体数量取决于CPU性能)而互不干扰。
每个电子眼算法的配置参数包括:
* 交易价差相关
* 价格价差
* 隐波价差
* 仓位限制相关
* 持仓范围
* 目标持仓
* 最大委托
* 单笔最大的委托数量
* 方向
* 算法允许的交易方向
* 包括只允许做多、只允许做空、允许双向交易
电子眼算法的执行流程如下:
1. 基于定价波动率,计算期权的**理论价**
2. 计算目标买卖的价差:
1. 隐波价差的价格值 = 隐波价差 * 期权理论Vega值
2. 交易价差 = max(价格价差, 隐波价差的价格值)
3. 计算目标买卖价:
1. 目标买价 = 理论价 - 交易价差 / 2
2. 目标卖价 = 理论价 + 交易价差 / 2
4. 以做多交易为例,当盘口卖1价格低于目标买价时,触发买入信号
5. 计算本轮委托量:
1. 算法持仓上限 = 目标持仓 + 持仓范围
2. 剩余多头可交易量 = 算法多头持仓上限 - 当前净持仓
3. 本轮委托量 = min(剩余多头可交易量,卖1量,最大委托量)
6. 使用目标买价和本轮委托量,发出对应的交易委托
配置好算法参数后,点击该行的【定价】列的按钮启动算法的定价计算,如下图所示:

【定价】和【交易】按钮的状态显示:
* 为N时,代表算法当前未启动该任务
* 为Y时,代表算法已在执行对应的任务
启动定价的4个期权算法,会开始实时更新目标买卖价等相关数值。
此时点击【交易】列的按钮,即可启动算法的交易执行,当价格和持仓满足条件时就会自动发出交易委托,详细的算法运行状态日志信息可以通过右侧日志区域监控:

当需要对算法配置进行批量修改时,可以通过电子眼窗口的右上角的全局修改功能进行操作,更加方便快捷。
================================================
FILE: docs/community/app/paper_account.md
================================================
# PaperAccount - 本地仿真交易模块
## 功能简介
PaperAccount是用于**本地仿真交易**的功能模块,用户可以通过其UI界面基于实盘行情进行本地化的模拟交易。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【PaperAccount】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_paperaccount import PaperAccountApp
# 写在创建main_engine对象后
main_engine.add_app(PaperAccountApp)
```
## 启动模块
在启动模块之前,请先连接要进行模拟交易的接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
交易接口连接后,本地模拟交易模块自动启动。此时所有合约的交易委托和撤单请求均**被本地模拟交易模块接管**,不会再发往实盘服务器。
## 功能配置
在菜单栏中点击【功能】-> 【模拟交易】,或者点击左侧按钮栏的图标:

即可进入本地模拟交易模块的UI界面,如下图所示:

用户可以通过UI界面对以下功能进行配置:
- 市价委托和停止委托的成交滑点
- 用于影响市价单和停止单成交时,成交价格相对于盘口价格的**滑点跳数**;
- 模拟交易持仓盈亏的计算频率
- 多少秒执行一次持仓盈亏计算更新,如果持仓较多时发现程序卡顿,建议尝试调低频率;
- 下单后立即使用当前盘口撮合
- 默认情况下,用户发出的委托需要**等到下一个TICK盘口推送才会撮合**(模拟实盘情景),对于TICK推送频率较低的不活跃合约可以勾选该选项,委托后会**立即基于当前的最新TICK盘口撮合**;
- 清空所有持仓
- 一键清空本地所有持仓数据。
本地模拟交易模块同样可以和其他策略应用模块(如CtaStrategy模块、SpreadTrading模块等)一起使用,从而实现本地化的量化策略仿真交易测试。
## 数据监控
用户可以通过【查询合约】来查询确认合约的交易接口状态:
点击菜单栏的【帮助】->【合约查询】,在弹出的对话框中直接点击右上角的【查询】按钮,发现所有合约的【交易接口】列均显示为PAPER,如下图所示:

在对某一合约进行下单和撤单操作前,用户必须先**订阅**该合约的行情。
下图中【委托】、【成交】、【持仓】三个监控组件中显示的信息,其接口列均为PAPER(本地模拟数据):

请注意,本地模拟交易模块**没有提供资金计算功能**,所以【资金】组件显示的是实盘账号的资金,并不会因为在本地模拟交易模块产生的委托而改变。
## 业务逻辑
本地模拟交易模块的业务逻辑如下所示:
- 支持的委托类型(不支持的类型会被拒单):
- 限价单;
- 市价单;
- 停止单;
- 委托撮合规则采用**到价成交**模式,以买入委托为例:
- 限价单:当盘口卖1价ask_price_1小于等于委托价格,则成交;
- 停止单:当盘口卖1价ask_price_1大于等于委托价格,则成交;
- 委托成交时**不考虑盘口挂单量**,一次性全部成交;
- 委托成交后,先推送委托状态更新OrderData,再推送成交信息TradeData,**和实盘交易中的顺序一致**;
- 委托成交后,模块会自动记录相应的持仓信息PositionData:
- 根据合约本身的持仓模式(多空仓 vs 净仓位)信息,维护对应的持仓信息;
- **开仓成交时,采用加权平均计算更新持仓成本价;**
- **平仓成交时,持仓成本价不变;**
- 多空仓模式下,挂出平仓委托后会冻结相应的持仓数量,可用数量不足时会拒单;
- 持仓的盈亏会基于持仓成本价和最新成交价定时计算(默认频率1秒);
- 数据的持久化保存:
- 成交数据和委托数据不保存,关闭VeighNa Trader后即消失;
- 持仓数据会在有变化时**立即写入硬盘文件**,重启VeighNa Trader登录交易接口后即可看到(要收到相应的合约信息)。
================================================
FILE: docs/community/app/portfolio_manager.md
================================================
# PortfolioManager - 投资组合管理模块
## 功能简介
PortfolioManager是用于**投资组合管理**的功能模块,用户可以在盘中通过其UI界面对交易策略进行实时的业绩跟踪和盈亏分析。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【PortfolioManager】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_portfoliomanager import PortfolioManagerApp
# 写在创建main_engine对象后
main_engine.add_app(PortfolioManagerApp)
```
## 启动模块
在菜单栏中点击【功能】-> 【投资组合】,或者点击左侧按钮栏的图标:

即可进入投资组合管理模块的UI界面,如下图所示:

## 组合信息表
界面整体可以分为左右两部分,左边显示的是当前已有投资组合的信息表,如下图所示:

组合信息表每列的含义如下:
- 组合名称:委托来源标识(reference),所有从VeighNa发出的委托请求都可以直接通过该标识来区分其交易来源,如手动交易、算法执行、量化策略等,每个交易来源可以视作一个独立的投资组合。
- 手动交易:ManualTrading
- CTA策略:CtaStrategy_策略名
- 价差交易:SpreadTrading_价差名
- 期权交易:OptionMaster_ElectronicEye/DeltaHedging
- 算法交易:AlgoTrading_算法编号
- 脚本策略:ScriptTrader
- 组合策略:PortfolioStrategy_策略名
- 本地代码:带交易所后缀的合约代码(vt_symbol)
- 开盘仓位:昨日收盘时(今日开盘),投资组合内该合约的持仓
- 当前仓位:开盘仓位加上今日成交数量(多头成交 - 空头成交)的结果
- 交易盈亏:今日所有成交,以成交价格映射到当前最新价的盈亏
- 持仓盈亏:组合开盘仓位,以昨收盘价映射到当前最新价的盈亏
- 总盈亏:交易盈亏和持仓盈亏的和
- 多头成交:投资组合内该合约今日买开和买平成交数量
- 空头成交:投资组合内该合约今日卖开和卖平成交数量
其中,交易盈亏(TradingPnl)和持仓盈亏(HoldingPnl)的计算方式采用的是期货交易所每日结算时所用的逐日盯市(Marking to Market)算法,计算过程如下所示:
- 交易盈亏 = 持仓量 * (当日收盘价-昨日收盘价)* 合约规模
- 持仓盈亏 = 持仓变化量 * (当日收盘价 - 开仓成交价)* 合约规模
- 总盈亏 = 交易盈亏 + 持仓盈亏
- 净盈亏 = 总盈亏 - 总手续费 - 总滑点
用户可以通过展开和折叠投资组合,调整列宽来查看信息:
- 点击每个投资组合左侧的箭头可以展开和折叠各投资组合的信息;
- 点击顶部的【全部展开】和【全部折叠】按钮对所有投资组合进行批量操作;
- 点击【调整列宽】按钮可以自动调整表格每列的宽度。
## 成交记录表
界面右侧部分显示的是所有成交记录,点击右上角的下拉框可以根据投资组合进行筛选,如下图所示:

## 刷新频率
投资组合的盈亏基于定时逻辑自动计算,计算频率可以通过顶部中间的选项框进行调整,如下图所示:

请注意,所有组合的持仓数据会在关闭VeighNa Trader时写入缓存文件中,所以不要直接杀进程退出,会丢失数据。
在隔日加载时,程序会自动将昨天的总仓位结算到今天的昨仓数据字段中,该逻辑对于24小时交易的市场(外盘期货)不一定合适,后续考虑加入每日定时结算或者手动结算功能。
如果发现有仓位记录错误,或者策略已经移除的情况,可以手动修改缓存文件,再重新启动VeighNa Trader即可。
Windows系统上缓存文件的默认路径位于:
C:\Users\Administrator\.vntrader\portfolio_manager_data.json
其中Administrator是当前Windows系统的用户名。
================================================
FILE: docs/community/app/portfolio_strategy.md
================================================
# PortfolioStrategy - 多合约组合策略模块
## 功能简介
PortfolioStrategy是用于**多合约组合策略实盘**的功能模块,用户可以通过其UI界面操作来便捷完成策略初始化、策略启动、策略停止、策略参数编辑以及策略移除等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【PortfolioStrategy】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_portfoliostrategy import PortfolioStrategyApp
# 写在创建main_engine对象后
main_engine.add_app(PortfolioStrategyApp)
```
## 启动模块
<span id="jump">
对于用户自行开发的策略,需要放到VeighNa Trader运行时目录下的**strategies**目录中,才能被识别加载。具体的运行时目录路径,可以在VeighNa Trader主界面顶部的标题栏查看。
对于在Windows上默认安装的用户来说,放置策略的strategies目录路径通常为:
```
C:\Users\Administrator\strategies
```
其中Administrator为当前登录Windows的系统用户名。
</span>
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【组合策略】,或者点击左侧按钮栏的图标:

即可进入多合约组合策略模块的UI界面,如下图所示:

如果配置了数据服务(配置方法详见基本使用篇的全局配置部分),打开多合约组合策略模块时会自动执行数据服务登录初始化。若成功登录,则会输出“数据服务初始化成功”的日志,如下图所示:

## 添加策略
用户可以基于编写好的组合策略模板(类)来创建不同的策略实例(对象)。
在左上角的下拉框中选择要交易的策略名称,如下图所示:

请注意,显示的策略名称是**策略类**(驼峰式命名)的名字,而不是策略文件(下划线模式命名)的名字。
选择好策略类之后,点击【添加策略】,会弹出添加策略对话框,如下图所示:

在创建策略实例时,需要配置相关参数,各参数要求如下:
- 实例名称
- 实例名称不能重名;
- 合约品种
- 格式为vt_symbol(合约代码 + 交易所名称);
- 一定要是实盘交易系统中可以查到的合约名称;
- 合约名用“,”隔开,中间不加空格;
- 参数设置
- 显示的参数名是策略里写在parameters列表中的参数名;
- 默认数值为策略里的参数的默认值;
- 由上图可观察到,参数名后面<>括号中显示的是该参数的数据类型,在填写参数时应遵循相应的数据类型。其中,<class 'str'>是字符串、<class 'int'>是整数、<class 'float'>是浮点数;
- 请注意,如果某个参数可能会调整至有小数位的数值,而默认参数值是整数(比如1)。请在编写策略时,把默认参数值设为浮点数(比如1.0)。否则策略会默认该项参数为整数,在后续【编辑】策略实例参数时,会只允许填进整数。
参数配置完成后,点击【添加】按钮,则开始创建策略实例。创建成功后可在左侧的策略监控组件中看到该策略实例,如下图所示:

策略监控组件顶部显示的是策略实例名、策略类名以及策略作者名(在策略里定义的author)。顶部按钮用于控制和管理策略实例,第一行表格显示了策略内部的参数信息(参数名需要写在策略的parameters列表中图形界面才会显示),第二行表格则显示了策略运行过程中的变量信息(变量名需要写在策略的variables列表中图形界面才会显示)。【inited】字段表示当前策略的初始化状态(是否已经完成了历史数据回放),【trading】字段表示策略当前是否能够开始交易。
从上图可观察到,此时该策略实例的【inited】和【trading】状态都为【False】。说明该策略实例还没有初始化,也还不能发出交易信号。
策略实例创建成功后,该策略实例的配置信息会被保存到.vntrader文件夹下的portfolio_strategy_setting.json文件中。
请注意,如果添加了同名的策略实例,则会创建失败,图形界面输出“创建策略失败,存在重名”的日志信息,如下图所示:

## 管理策略
### 初始化
策略实例创建成功后,就可以对该实例进行初始化了。点击该策略实例下的【初始化】按钮,若初始化成功,则如下图所示:

初始化完成后,可观察到此时该策略实例的【inited】状态已经为【True】。说明该策略实例已经加载过历史数据并完成初始化了。【trading】状态还是为【False】,说明此时该策略实例还不能开始自动交易。
请注意,与CTA策略不同,如果创建实例时输入错误的vt_symbol,多合约组合策略模块会在初始化时报错,而不是在创建策略实例时报错,如下图所示:

### 启动
策略实例初始化成功,【inited】状态为【True】时,才能启动该策略的自动交易功能。点击该策略实例下的【启动】按钮,即可启动该策略实例。成功后如下图所示:

可观察到此时该策略实例的【inited】和【trading】状态都为【True】。说明此时该策略实例已经完成了历史数据回放,而且此时策略内部的交易请求类函数(buy/sell/short/cover/cancel_order等),以及信息输出类函数(send_email/put_event等),才会真正执行并发出对应的请求指令到底层接口中(真正执行交易)。
在上一步策略初始化的过程中,尽管策略同样在接收(历史)数据,并调用对应的功能函数,但因为【trading】状态为【False】,所以并不会有任何真正的委托下单操作或者交易相关的日志信息输出。
如果启动之后,策略发出了委托,可以去VeighNa Trader主界面【委托】栏查看委托订单细节,如下图所示:

请注意,与CTA策略模块不同,多合约组合策略**不提供本地停止单功能**,所以UI界面上不会有停止单的显示区域了。
### 停止
如果启动策略之后,由于某些情况(如到了市场收盘时间,或盘中遇到紧急情况)想要停止、编辑或者移除策略,可以点击策略实例下的【停止】按钮,即可停止该策略实例的自动交易。成功后如下图所示:

组合策略引擎会自动将该策略之前发出的所有活动委托全部撤销,以保证在策略停止后不会有失去控制的委托存在。同时该策略实例最新的变量信息会被保存到.vntrader文件夹下的portfolio_strategy_data.json文件中。
此时可观察到该策略实例的【trading】状态已变为【False】,说明此时该策略实例已经停止自动交易了。
在多合约组合策略的实盘交易过程中,正常情况应该让策略在整个交易时段中都自动运行,尽量不要有额外的暂停重启类操作。对于国内期货市场来说,应该在交易时段开始前,启动策略的自动交易,然后直到收盘后,再关闭自动交易。因为现在CTP夜盘收盘后也会关闭系统,早上开盘前重启,所以夜盘收盘后也需要停止策略,关闭VeighNa Trader了。
### 编辑
如果创建策略实例之后,想要编辑某个策略实例的参数(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【编辑】按钮,会弹出参数编辑对话框,以供修改策略参数。如下图所示:

编辑完策略参数之后,点击下方的【确定】按钮,相应的修改会立即更新在参数表格中。
但是策略实例的交易合约代码无法修改,同时修改完后也不会重新执行初始化操作。也请注意,此时修改的只是.vntrader文件夹下porfolio_strategy_setting.json文件中该策略实例的参数值,并没有修改原策略文件下的参数。
修改前,json文件如下图所示:

修改后,json文件如下图所示:

若盘中编辑后想要再次启动策略,点击策略实例下的【启动】按钮即可再次启动该策略实例。
### 移除
如果创建策略实例之后,想要移除某个策略实例(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【移除】按钮。移除成功后,图形界面左侧的策略监控组件中将不会再显示该策略实例的信息。如下图所示:

此时.vntrader文件夹下的portfolio_strategy_setting.json文件也移除了该策略实例的配置信息。
### 状态跟踪
如果想要通过图形界面跟踪策略的状态,有两种方式:
1. 调用put_event函数
策略实例中所有的的变量信息,都需要把变量名写在策略的variables列表中,才能在图形界面显示。如果想跟踪变量的状态变化,则需要在策略中调用put_event函数,界面上才会进行数据刷新。
有时用户会发现自己写的策略无论跑多久,变量信息都不发生变化,这种情况请检查策略中是否漏掉了对put_event函数的调用。
2. 调用write_log函数
如果不仅想观察到变量信息的状态变化,还想根据策略的状态输出基于自己需求的个性化的日志,可以在策略中调用write_log函数,进行日志输出。
## 运行日志
### 日志内容
多合约组合策略模块UI界面上输出的日志有两个来源,分别是策略引擎和策略实例。
**引擎日志**
策略引擎一般输出的是全局信息。下图中除了策略实例名后加冒号的内容之外,都是策略引擎输出的日志。

**策略日志**
如果在策略中调用了write_log函数,那么日志内容就会通过策略日志输出。下图红框里的内容是策略实例输出的策略日志。冒号前是策略实例的名称,冒号后是write_log函数输出的内容。

### 清空操作
如果想要清空多合约组合策略UI界面上的日志输出,可以点击右上角的【清空日志】按钮,则可一键清空该界面上已输出的日志。
点击【清空日志】后,如下图所示:

## 批量操作
在策略经过充分测试,实盘运行较为稳定,不需要经常进行调整的情况下,如果有多个需要运行的组合策略实例,可以使用界面右上角的【全部初始化】、【全部启动】和【全部停止】功能来执行盘前批量初始化、启动策略实例以及盘后批量停止策略实例的操作。
### 全部初始化
在所有策略实例创建成功后,点击右上角的【全部初始化】按钮,则可批量初始化策略实例,如下图所示:

### 全部启动
在所有策略实例初始化成功后,点击右上角的【全部启动】按钮,则可批量启动策略实例,如下图所示:

### 全部停止
在所有策略实例启动成功后,点击右上角的【全部停止】按钮,则可批量停止策略实例,如下图所示:

## 多合约组合策略模板(StrategyTemplate)-- 基础
多合约组合策略模板提供了信号生成和委托管理功能,用户可以基于该模板(位于site-packages\vnpy_portfoliostrategy\template中)自行开发多合约组合策略。
用户自行开发的策略可以放在用户运行文件夹下的[strategies](#jump)文件夹内。
请注意:
1. 策略文件命名采用下划线模式,如portfolio_boll_channel_strategy.py,而策略类命名采用驼峰式,如PortfolioBollChannelStrategy。
2. 自建策略的类名不要与示例策略的类名重合。如果重合了,图形界面上只会显示一个策略类名。
下面通过PortfolioBollChannelStrategy策略示例,来展示策略开发的具体步骤:
在基于策略模板编写策略逻辑之前,需要在策略文件的顶部载入需要用到的内部组件,如下方代码所示:
```python3
from typing import List, Dict
from datetime import datetime
from vnpy.trader.utility import ArrayManager, Interval
from vnpy.trader.object import TickData, BarData
from vnpy_portfoliostrategy import StrategyTemplate, StrategyEngine
from vnpy_portfoliostrategy.utility import PortfolioBarGenerator
```
其中,StrategyTemplate是策略模板,StrategyEngine是策略引擎,Interval是数据频率,TickData和BarData都是储存对应信息的数据容器,PortfolioBarGenerator是组合策略K线生成模块,ArrayManager是K线时间序列管理模块。
### 策略参数与变量
在策略类的下方,可以设置策略的作者(author),参数(parameters)以及变量(variables),如下方代码所示:
```python3
author = "用Python的交易员"
boll_window = 18
boll_dev = 3.4
cci_window = 10
atr_window = 30
sl_multiplier = 5.2
fixed_size = 1
price_add = 5
parameters = [
"boll_window",
"boll_dev",
"cci_window",
"atr_window",
"sl_multiplier",
"fixed_size",
"price_add"
]
variables = []
```
虽然策略的参数和变量都从属于策略类,但策略参数是固定的(由交易员从外部指定),而策略变量则在交易的过程中随着策略的状态而变化,所以策略变量一开始只需要初始化为对应的基础类型。例如:整数设为0,浮点数设为0.0,而字符串则设为""。
如果需要策略引擎在运行过程中,将策略参数和变量显示在UI界面上,并在数据刷新、停止策略时保存其数值,则需把参数和变量的名字(以字符串的数据类型)添加进parameters和variables列表里。
请注意,该列表只能接受参数或变量以str、int、float和bool四种数据类型传入。如果策略里需要用到其他数据类型的参数与变量,请把该参数或变量的定义放到__init__函数下。
### 类的初始化
入参:strategy_engine: StrategyEngine, strategy_name: str, vt_symbols: List[str], setting: dict
出参:无
__init__函数是策略类的构造函数,需要与继承的StrategyTemplate保持一致。
在这个继承的策略类里,初始化一般分四步,如下方代码所示:
```python3
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.boll_up: Dict[str, float] = {}
self.boll_down: Dict[str, float] = {}
self.cci_value: Dict[str, float] = {}
self.atr_value: Dict[str, float] = {}
self.intra_trade_high: Dict[str, float] = {}
self.intra_trade_low: Dict[str, float] = {}
self.targets: Dict[str, int] = {}
self.last_tick_time: datetime = None
self.ams: Dict[str, ArrayManager] = {}
for vt_symbol in self.vt_symbols:
self.ams[vt_symbol] = ArrayManager()
self.targets[vt_symbol] = 0
self.pbg = PortfolioBarGenerator(self.on_bars, 2, self.on_2hour_bars, Interval.HOUR)
```
1 . 通过super( )的方法继承策略模板,在__init__( )函数中传入策略引擎、策略名称、vt_symbols以及参数设置(以上参数均由策略引擎在使用策略类创建策略实例时自动传入,用户无需进行设置)。
2 . 创建策略所需的存放不同合约K线时间序列管理实例(ArrayManager)和策略变量的字典。
3 . 分别为策略交易的不同合约创建ArrayManager和目标仓位变量并放进字典里。
ArrayManager的默认长度为100,如需调整ArrayManager的长度,可传入size参数进行调整(size不能小于计算指标的周期长度)。
4 . 调用组合策略K线生成模块(PortfolioBarGenerator):通过时间切片将Tick数据合成1分钟K线数据。如有需求,还可合成更长的时间周期数据,如15分钟K线。
如果只基于on_bar进行交易,这里代码可以写成:
```python3
self.pbg = PortfolioBarGenerator(self.on_bars)
```
而不用给pbg实例传入需要基于on_bars周期合成的更长K线周期,以及接收更长K线周期的函数名。
请注意:
- 合成X分钟线时,X必须设为能被60整除的数(60除外)。对于小时线的合成没有这个限制。
- PortfolioBarGenerator默认的基于on_bar函数合成长周期K线的数据频率是分钟级别,如果需要基于合成的小时线或者更长周期的K线交易,请在策略文件顶部导入Interval,并传入对应的数据频率给bg实例。
- **self.on_hour_bars函数名在程序内部已使用**,如需合成1小时K线,请使用self.on_1_hour_bars或者其他命名。
### 策略引擎调用的函数
StrategyTemplate中的update_setting函数和该函数后面四个以get开头的函数以及update_trade和update_order函数,都是策略引擎去负责调用的函数,一般在策略编写的时候是不需要调用的。
### 策略的回调函数
StrategyTemplate中以on开头的函数称为回调函数,在编写策略的过程中能够用来接收数据或者接收状态更新。回调函数的作用是当某一个事件发生的时候,策略里的这类函数会被策略引擎自动调用(无需在策略中主动操作)。回调函数按其功能可分为以下两类:
#### 策略实例状态控制(所有策略都需要)
**on_init**
* 入参:无
* 出参:无
初始化策略时on_init函数会被调用,默认写法是先调用write_log函数输出“策略初始化”日志,再调用load_bars函数加载历史数据。如下方代码所示:
```python3
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(10)
```
与CTA策略不同,多合约组合策略只支持K线回测,所以多合约策略模板并没有load_ticks函数。
策略初始化时,策略的inited和trading状态都为【False】,此时只是调用ArrayManager计算并缓存相关的计算指标,不能发出交易信号。调用完on_init函数之后,策略的inited状态才变为【True】,策略初始化才完成。
**on_start**
* 入参:无
* 出参:无
启动策略时on_start函数会被调用,默认写法是调用write_log函数输出“策略启动”日志,如下方代码所示:
```python3
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
```
调用策略的on_start函数启动策略后,策略的trading状态变为【True】,此时策略才能够发出交易信号。
**on_stop**
* 入参:无
* 出参:无
停止策略时on_stop函数会被调用,默认写法是调用write_log函数输出“策略停止”日志,如下方代码所示:
```python3
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
```
调用策略的on_stop函数停止策略后,策略的trading状态变为【False】,此时策略就不会发出交易信号了。
#### 接收数据、计算指标、发出交易信号
**on_tick**
* 入参:tick: TickData
* 出参:无
绝大部分交易系统都只提供Tick数据的推送。即使一部分平台可以提供K线数据的推送,但是这些数据到达本地电脑的速度也会慢于Tick数据的推送,因为也需要平台合成之后才能推送过来。所以实盘的时候,VeighNa里所有的策略的K线都是由收到的Tick数据合成的。
当策略收到实盘中最新的Tick数据的行情推送时,on_tick函数会被调用。默认写法是通过PortfolioBarGenerator的update_tick函数把收到的Tick数据推进前面创建的pbg实例中以便合成1分钟的K线,如下方代码所示:
```python3
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
self.pbg.update_tick(tick)
```
请注意,on_tick函数只在实盘中会被调用,回测不支持。
**on_bars**
* 入参:bars: Dict[str, BarData]
* 出参:无
当策略收到最新的K线数据时(实盘时默认推进来的是基于Tick合成的一分钟的K线,回测时则取决于选择参数时填入的K线数据频率),on_bars函数就会被调用。
与CTA策略模块不同,多合约组合策略模块在接收K线推送时,是通过on_bars回调函数一次性接收该时间点上所有合约的K线数据,而不是通过on_bar函数一个个接收(无法判断当前时点的K线是否全部走完了 )。
示例策略里出现过的写法有两种:
1 . 如果策略基于on_bars推进来的K线交易,那么请把交易请求类函数都写在on_bars函数下(因本次示例策略类PortfolioBollChannelStrategy不是基于on_bars交易,故不作示例讲解。基于on_bars交易的示例代码可参考其他示例策略);
2 . 如果策略需要基于on_bars推进来的K线数据通过PortfolioBarGenerator合成更长时间周期的K线来交易,那么请在on_bars中调用PortfolioBarGenerator的update_bars函数,把收到的bars推进前面创建的pbg实例中即可,如下方代码所示:
```python3
def on_bars(self, bars: Dict[str, BarData]):
"""
Callback of new bars data update.
"""
self.pbg.update_bars(bars)
```
示例策略类PortfolioBollChannelStrategy是通过2小时K线数据回报来生成信号的。一共有三部分,如下方代码所示:
```python3
def on_2hour_bars(self, bars: Dict[str, BarData]):
""""""
self.cancel_all()
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
if not am.inited:
return
self.boll_up[vt_symbol], self.boll_down[vt_symbol] = am.boll(self.boll_window, self.boll_dev)
self.cci_value[vt_symbol] = am.cci(self.cci_window)
self.atr_value[vt_symbol] = am.atr(self.atr_window)
current_pos = self.get_pos(vt_symbol)
if current_pos == 0:
self.intra_trade_high[vt_symbol] = bar.high_price
self.intra_trade_low[vt_symbol] = bar.low_price
if self.cci_value[vt_symbol] > 0:
self.targets[vt_symbol] = self.fixed_size
elif self.cci_value[vt_symbol] < 0:
self.targets[vt_symbol] = -self.fixed_size
elif current_pos > 0:
self.intra_trade_high[vt_symbol] = max(self.intra_trade_high[vt_symbol], bar.high_price)
self.intra_trade_low[vt_symbol] = bar.low_price
long_stop = self.intra_trade_high[vt_symbol] - self.atr_value[vt_symbol] * self.sl_multiplier
if bar.close_price <= long_stop:
self.targets[vt_symbol] = 0
elif current_pos < 0:
self.intra_trade_low[vt_symbol] = min(self.intra_trade_low[vt_symbol], bar.low_price)
self.intra_trade_high[vt_symbol] = bar.high_price
short_stop = self.intra_trade_low[vt_symbol] + self.atr_value[vt_symbol] * self.sl_multiplier
if bar.close_price >= short_stop:
self.targets[vt_symbol] = 0
for vt_symbol in self.vt_symbols:
target_pos = self.targets[vt_symbol]
current_pos = self.get_pos(vt_symbol)
pos_diff = target_pos - current_pos
volume = abs(pos_diff)
bar = bars[vt_symbol]
boll_up = self.boll_up[vt_symbol]
boll_down = self.boll_down[vt_symbol]
if pos_diff > 0:
price = bar.close_price + self.price_add
if current_pos < 0:
self.cover(vt_symbol, price, volume)
else:
self.buy(vt_symbol, boll_up, volume)
elif pos_diff < 0:
price = bar.close_price - self.price_add
if current_pos > 0:
self.sell(vt_symbol, price, volume)
else:
self.short(vt_symbol, boll_down, volume)
self.put_event()
```
- 清空未成交委托:为了防止之前下的单子在上一个2小时没有成交,但是下一个2小时可能已经调整了价格,就用cancel_all()方法立刻撤销之前未成交的所有委托,保证策略在当前这2小时开始时的整个状态是清晰和唯一的;
- 调用K线时间序列管理模块:基于最新的2小时K线数据来计算相应的技术指标,如布林带上下轨、CCI指标、ATR指标等。首先获取ArrayManager对象,然后将收到的K线推送进去,检查ArrayManager的初始化状态,如果还没初始化成功就直接返回,没有必要去进行后续的交易相关的逻辑判断。因为很多技术指标计算对最少K线数量有要求,如果数量不够的话计算出来的指标会出现错误或无意义。反之,如果没有return,就可以开始计算技术指标了;
- 信号计算:通过持仓的判断以及结合CCI指标、ATR指标在通道突破点挂出**限价单委托**(buy/sell),同时设置离场点(short/cover)。
请注意:
1. 在CTA策略模块中,通常都是通过访问策略的变量pos获取策略持仓来进行持仓判断。但在多合约组合策略模块中,是通过调用get_pos函数获取某一合约现在的持仓来进行逻辑判断,然后设定该合约的目标仓位,最后通过目标仓位和实际仓位的差别来进行逻辑判断进而发出交易信号的;
2. 如果需要在图形界面刷新指标数值,请不要忘记调用put_event()函数。
#### 委托状态更新
因为组合策略中需要对多合约同时下单交易,在回测时无法判断某一段K线内部每个合约委托成交的先后时间顺序,因此无法提供on_order和on_trade函数来获取委托成交推送,而只能在每次on_bars回调时通过get_pos和get_order来进行相关的状态查询。
### 主动函数
**buy**:买入开仓(Direction:LONG,Offset:OPEN)
**sell**:卖出平仓(Direction:SHORT,Offset:CLOSE)
**short**:卖出开仓(Direction:SHORT,Offset:OPEN)
**cover**:买入平仓(Direction:LONG,Offset:CLOSE)
* 入参:vt_symbol: str, price: float, volume: float, lock: bool = False, net: bool = False
* 出参:vt_orderids: List[str] / 无
buy/sell/short/cover都是策略内部的负责发单的交易请求类函数。策略可以通过这些函数给策略引擎发送交易信号来达到下单的目的。
以下方buy函数的代码为例,可以看到,**具体要交易合约的代码**,价格和数量是必填的参数,锁仓转换和净仓转换则默认为False。也可以看到,函数内部收到传进来的参数之后就调用了StrategyTemplate里的send_order函数来发单(因为是buy指令,则自动把方向填成了LONG,开平填成了OPEN)。
与CTA策略模块不同,组合策略模块不提供本地停止单功能,所以委托函数中移除了stop参数。
如果lock设置为True,那么该笔订单则会进行锁仓委托转换(在有今仓的情况下,如果想平仓,则会先平掉所有的昨仓,然后剩下的部分都进行反向开仓来代替平今仓,以避免平今的手续费惩罚)。
如果net设置为True,那么该笔订单则会进行净仓委托转换(基于整体账户的所有仓位,根据净仓持有方式来对策略下单的开平方向进行转换)。但是净仓交易模式与锁仓交易模式互斥,因此net设置为True时,lock必须设置为False。
请注意,如果向上期所发出平仓委托,因为该交易所必须指定平今、平昨,底层会对其平仓指令自动进行转换。因为上期所部分品种有平今优惠,所以默认是以平今优先的方式发出委托的(如果交易的标的在上期所平昨更优惠的话,可以自行在vnpy.trader.converter的convert_order_request_shfe函数中做适当的修改)。
```python3
def buy(self, vt_symbol: str, price: float, volume: float, lock: bool = False, net: bool = False) -> List[str]:
"""
Send buy order to open a long position.
"""
return self.send_order(vt_symbol, Direction.LONG, Offset.OPEN, price, volume, lock, net)
```
请注意,国内期货有开平仓的概念,例如买入操作要区分为买入开仓和买入平仓;但对于股票、外盘期货都是净持仓模式,没有开仓和平仓概念,所以只需使用买入(buy)和卖出(sell)这两个指令就可以了。
**send_order**
* 入参:vt_symbol: str, direction: Direction, offset: Offset, price: float, volume: float, lock: bool = False, net: bool = False
* 出参:vt_orderids: List[str] / 无
send_order函数是策略引擎调用的发送委托的函数。一般在策略编写的时候不需要单独调用,通过buy/sell/short/cover函数发送限价委托即可。
实盘的时候,收到传进来的参数后,会调用round_to函数基于合约的pricetick和min_volume对委托的价格和数量进行处理。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能发出交易委托。如果策略的Trading状态为【False】时调用了该函数,只会返回[]。
**cancel_order**
* 入参:vt_orderid: str
* 出参:无
**cancel_all**
* 入参:无
* 出参:无
cancel_order和cancel_all都是负责撤单的交易请求类函数。cancel_order是撤掉策略内指定的活动委托,cancel_all是撤掉策略所有的活动委托。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能撤单。
### 功能函数
以下为策略以外的功能函数:
**get_pos**
* 入参:vt_symbol: str
* 出参:int / 0
在策略里调用get_pos函数,可以获取特定合约的持仓数据。
**get_order**
* 入参:vt_orderid
* 出参:OrderData / 无
在策略里调用get_order函数,可以获取特定合约的委托数据。
**get_all_active_orderids**
* 入参:无
* 出参:List[OrderData] / 无
在策略里调用get_all_active_orderids函数,可以获取当前全部活动委托号。
**get_pricetick**
* 入参:vt_symbol
* 出参:pricetick: float / None
在策略里调用get_price函数,可以获取特定合约的最小价格跳动。
**write_log**
* 入参:msg: str
* 出参:无
在策略中调用write_log函数,可以进行指定内容的日志输出。
**load_bars**
* 入参:days: int, interval: Interval = Interval.MINUTE
* 出参:无
在策略中调用load_bars函数,可以在策略初始化时加载K线数据。
如下方代码所示,load_bars函数调用时,默认加载的天数是10,频率是一分钟,对应也就是加载10天的1分钟K线数据。在回测时,10天指的是10个交易日,而在实盘时,10天则是指的是自然日,因此建议加载的天数宁可多一些也不要太少。加载时会先依次尝试通过交易接口、数据服务、数据库获取历史数据,直到获取历史数据或返回空。
```python3
def load_bars(self, days: int, interval: Interval = Interval.MINUTE) -> None:
"""
Load historical bar data for initializing strategy.
"""
self.strategy_engine.load_bars(self, days, interval)
```
**put_event**
* 入参:无
* 出参:无
在策略中调用put_event函数,可以通知图形界面刷新策略状态相关显示。
请注意,要策略初始化完成,inited状态变为【True】之后,才能刷新界面。
**send_email**
* 入参:msg: str
* 出参:无
配置好邮箱相关信息之后(配置方法详见基本使用篇的全局配置部分),在策略中调用send_email函数,可以发送指定内容的邮件到自己的邮箱。
请注意,要策略初始化完成,inited状态变为【True】之后,才能发送邮件。
**sync_data**
* 入参:无
* 出参:无
在策略中调用sync_data函数,可以在实盘的时候,每次停止或成交时都同步策略变量进json文件中进行本地缓存,方便第二天初始化时再进行读取还原(策略引擎会去调用,在策略里无需主动调用)。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能同步策略信息。
## 多合约组合策略模板(StrategyTemplate)-- 进阶
PortfolioStrategy模块针对的是多标的投资组合类的量化策略,这类策略在执行层面追求的是将策略投资组合的持仓调整到目标状态,而不去过多关注底层的委托交易细节。
首先介绍持仓目标调仓交易的功能函数,来展示持仓目标调仓交易的功能支持:
### 持仓目标调仓交易的功能函数介绍
以下为持仓目标调仓交易模式中策略调用的功能函数:
**set_target**
* 入参:vt_symbol: str, target: int
* 出参:无
在策略里调用set_target函数,可以设定特定合约的目标仓位。
请注意:目标仓位是一种持续性的状态,因此设置后在后续时间会持续保持下去,直到被再次设置修改。
**get_target**
* 入参:vt_symbol: str
* 出参:int
在策略里调用get_target函数,可以获取设定的特定合约目标仓位。
请注意:策略的目标仓位状态会在sync_data时(成交、停止等)自动持久化到硬盘文件,并在策略重启后恢复。
**rebalance_portfolio**
* 入参:bars: Dict[str, BarData]
* 出参:无
在策略里调用rebalance_portfolio函数,可以基于设定的特定合约的目标仓位执行调仓交易。
请注意:只有当前bars字典中有K线切片的合约,才会参与本次调仓交易的执行,从而保证非交易时段(没有行情推送)的合约不会错误发出委托。
**calculate_price**
* 入参:vt_symbol: str, direction: Direction, reference: float
* 出参:pricetick: float
在策略里重载calculate_price函数,可以按需设定特定合约的目标价格(如固定价格超价、固定pricetick超价、百分比超价等)。
如果不传则默认返回参考价格(如不在策略中重载,则在rebalance_portfolio函数中以K线的收盘价作为委托价发出)。
### 持仓目标调仓交易的功能函数使用示例
持仓目标调仓交易功能与StrategyTemplate基础用法最大的不同,就在于策略on_bars函数中的处理差异。下面通过TrendFollowingStrategy策略示例,来展示持仓目标调仓交易的具体步骤:
**on_bars**
* 入参:bars: Dict[str, BarData]
* 出参:无
当策略收到最新的K线数据时(实盘时默认推进来的是基于Tick合成的一分钟的K线,回测时则取决于选择参数时填入的K线数据频率),on_bars函数就会被调用。
示例策略类TrendFollowingStrategy是通过一分钟K线数据回报来生成信号的。一共有三部分,如下方代码所示:
```python3
def on_bars(self, bars: Dict[str, BarData]) -> None:
"""K线切片回调"""
# 更新K线计算RSI数值
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
am.update_bar(bar)
for vt_symbol, bar in bars.items():
am: ArrayManager = self.ams[vt_symbol]
if not am.inited:
return
atr_array = am.atr(self.atr_window, array=True)
self.atr_data[vt_symbol] = atr_array[-1]
self.atr_ma[vt_symbol] = atr_array[-self.atr_ma_window:].mean()
self.rsi_data[vt_symbol] = am.rsi(self.rsi_window)
current_pos = self.get_pos(vt_symbol)
if current_pos == 0:
self.intra_trade_high[vt_symbol] = bar.high_price
self.intra_trade_low[vt_symbol] = bar.low_price
if self.atr_data[vt_symbol] > self.atr_ma[vt_symbol]:
if self.rsi_data[vt_symbol] > self.rsi_buy:
self.set_target(vt_symbol, self.fixed_size)
elif self.rsi_data[vt_symbol] < self.rsi_sell:
self.set_target(vt_symbol, -self.fixed_size)
else:
self.set_target(vt_symbol, 0)
elif current_pos > 0:
self.intra_trade_high[vt_symbol] = max(self.intra_trade_high[vt_symbol], bar.high_price)
self.intra_trade_low[vt_symbol] = bar.low_price
long_stop = self.intra_trade_high[vt_symbol] * (1 - self.trailing_percent / 100)
if bar.close_price <= long_stop:
self.set_target(vt_symbol, 0)
elif current_pos < 0:
self.intra_trade_low[vt_symbol] = min(self.intra_trade_low[vt_symbol], bar.low_price)
self.intra_trade_high[vt_symbol] = bar.high_price
short_stop = self.intra_trade_low[vt_symbol] * (1 + self.trailing_percent / 100)
if bar.close_price >= short_stop:
self.set_target(vt_symbol, 0)
self.rebalance_portfolio(bars)
self.put_event()
```
- 调用K线时间序列管理模块:基于最新的分钟K线数据来计算相应的技术指标,如ATR指标、RSI指标等。首先获取ArrayManager对象,然后将收到的K线推送进去,检查ArrayManager的初始化状态,如果还没初始化成功就直接返回,没有必要去进行后续的交易相关的逻辑判断。因为很多技术指标计算对最少K线数量有要求,如果数量不够的话计算出来的指标会出现错误或无意义。反之,如果没有return,就可以开始计算技术指标了;
- 信号计算:通过持仓的判断(get_pos)以及结合指标计算结果在通道突破点**设定目标仓位**(set_target)
- 执行调仓交易(rebalance_portfolio)
**calculate_price**
* 入参:vt_symbol: str, direction: Direction, reference: float
* 出参:prcie: float
当rebalance_portfolio函数检测到目标仓位与实际仓位存在差别的时候,会调用calculate_price函数计算调仓委托价格。
策略内的默认写法是针对委托方向基于设置的price_add来计算委托价格,也可以参考示例策略PairTradingStrategy中的基于设置的tick_add来计算委托价格。
```python3
def calculate_price(self, vt_symbol: str, direction: Direction, reference: float) -> float:
"""计算调仓委托价格(支持按需重载实现)"""
if direction == Direction.LONG:
price: float = reference + self.price_add
else:
price: float = reference - self.price_add
return price
```
### 与StrategyTemplate基础用法的差别
**on_bars**
1 . 无需清空未成交委托:rebalance_portfolio中已经有调用cancel_all函数的逻辑,无需再在收到on_bars函数推送的时候调用cancel_all函数对未成交的委托进行撤单处理。
2 . 无需使用self.targets字典缓存合约目标仓位:直接调用set_target函数传入合约以及目标仓位(正数代表做多、负数代表做空)进行设置即可。
3 . 无需基于缓存的目标仓位在策略内手写委托逻辑:rebalance_portfolio函数已经自动接管调仓交易,会基于目标仓位进行委托。
**calculate_price**
持仓目标调仓交易需要调用calculate_price函数计算调仓委托价格。
================================================
FILE: docs/community/app/risk_manager.md
================================================
# RiskManager - 事前风控管理模块
## 功能简介
RiskManager模块是用于**事前风控管理**的功能模块,用户可以通过其UI界面操作来便捷完成启动风控,参数修改和停止风控等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【RiskManager】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_riskmanager import RiskManagerApp
# 写在创建main_engine对象后
main_engine.add_app(RiskManagerApp)
```
## 启动模块
在菜单栏中点击【功能】-> 【交易风控】,或者点击左侧按钮栏的图标:

即可进入事前风控模块的UI界面,如下图所示:

## 启动风控
事前风控模块负责在委托通过交易API接口发出前,检查其状态是否符合各种风控规则。风控规则包括交易流控、下单数量、活动委托、撤单总数等,具体如下:
- 委托流控相关:
- 委托流控上限:给定时间窗口内最多允许发出的委托笔数
- 委托流控清空:每隔多少秒清零上述统计的委托笔数
- 单笔委托上限:每一笔委托允许的最大下单量
- 总成交上限:今天日内允许的最大总成交笔数(注意不是委托笔数)
- 活动委托上限:允许的处于活动状态(提交中、未成交、部分成交)最大委托数量
- 合约撤单上限:今天日内允许的单合约撤单次数上限(每个合约独立统计)
推荐每天在运行自动交易前启动事前风控,以检查每一笔发出的委托是否符合风控要求:

1. 在【风控运行状态】一栏的下拉框中选择【启动】;
2. 设定各种风控规则的参数后,点击下方的【保存】按钮,即可开始运行风控;
3. 此时系统内的每一笔委托,都需要满足全部风控要求(不超过限制)后,才能通过底层接口发出。
## 参数修改
事前风控模块允许用户自定义风控参数:
* 用户可以点击输入框右侧的上下箭头来修改参数,也可以直接输入数字来修改,如下图所示。

* 修改后请点击【保存】按钮生效。
## 停止风控
不需要运行风控时,用户可以停止风控:
* 在【风控运行状态】的下拉框中选择【停止】,如下图所示:

* 点击下方的【保存】按钮即可停止对委托的风控检查。
================================================
FILE: docs/community/app/rpc_service.md
================================================
# RpcService - RPC服务器模块
## 功能简介
RpcService是用于**将VeighNa Trader进程转化为RPC服务器**的功能模块,对外提供交易路由、行情数据推送、持仓资金查询等功能。
关于RPC的具体应用场景请参考本文档结尾的【RPC的应用场景】版块。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【RpcService】。
### 脚本加载
在启动脚本中添加如下代码:
›
```python3
# 写在顶部
from vnpy_rpcservice import RpcServiceApp
# 写在创建main_engine对象后
main_engine.add_app(RpcServiceApp)
```
### 启动模块
在启动模块之前,请先连接登录交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

成功连接交易接口后,在菜单栏中点击【功能】-> 【RPC服务】,或者点击左侧按钮栏的图标:

即可进入RPC服务模块的UI界面,如下图所示:

## 配置和使用
### 配置RPC服务
RPC服务基于ZeroMQ开发,对外的通讯地址包括:
* **请求响应地址**
* 用于被动接收客户端发送过来的请求,执行对应任务后返回结果;
* 功能举例:
* 行情订阅;
* 委托下单;
* 委托撤单;
* 初始化信息查询(合约、持仓、资金等);
* **事件广播地址**
* 用于主动推送服务端收到的事件数据,到所有已连接的客户端;
* 功能举例:
* 行情推送;
* 委托推送;
* 成交推送。
以上地址均采用ZeroMQ的地址格式,由**通讯协议**(如tcp://)和**通讯地址**(如127.0.0.1:2014)两部分组成。
RPC服务支持的通讯协议包括:
* **TCP协议**
* 协议前缀:tcp://
* Windows和Linux系统均可使用
* 可用于本机通讯(127.0.0.1)或者网络通讯(网络IP地址)
* **IPC协议**
* 协议前缀:ipc://
* 只能在Linux系统上使用(POSIX本地端口通讯)
* 只能用于本机通讯,后缀为任意字符串内容
一般推荐直接使用TCP协议(以及默认地址),对于使用Ubuntu系统且希望追求更低通讯延时的用户可以使用IPC协议。
### 运行RPC服务
完成通讯地址的配置后,点击【启动】按钮即可启动RPC服务,日志区域会输出"RPC服务启动成功",如下图所示:

启动成功后,即可在另一VeighNa Trader进程中(客户端)使用RpcGateway来连接
如需停止RPC服务可以点击【停止】按钮,此时日志输出"RPC服务已停止"。
### 连接客户端
VeighNa提供了与RpcService配套使用的RpcGateway,作为客户端的标准接口来连接服务端并进行交易,对上层应用透明。
从客户端的视角看,RpcGateway是类似CTP的接口。因为已经在服务端统一完成外部交易账户的配置连接,客户端只需要和服务器端进行通讯即可,无需再次输入账户密码等信息。
在客户端加载RpcGateway接口后,进入VeighNa Trader主界面,点击菜单栏中【系统】->【连接RPC】,在弹出的窗口中点击【连接】即可连接使用,如下图所示。

【主动请求地址】和【推送订阅地址】,分别对应之前在服务端配置的【请求响应地址】和【事件广播地址】,注意不要写反。
## RPC简介
由于全局解释器锁GIL的存在,导致单一Python进程只能利用CPU单核的算力。远程过程调用(Remote Procedure Call Protocol, RPC)服务可以用于**跨进程或者跨网络的服务功能调用**,有效解决了上述问题。
由一个特定的进程连接交易接口充当**服务器**的角色,在本地物理机或者局域网内部向其他独立的**客户端**进程主动推送事件,并处理客户端相关请求,如下图所示:

## RPC服务(RpcService)的应用场景
- 针对运行策略数量较多的用户,只需本地一条行情和交易通道,可以支持多个客户端进程同时交易,且每个客户端中交易策略独立运行,互不影响;
- 针对中小型投资机构用户,可以通过在服务端加载各种交易接口以及RiskManagerApp,实现一个轻量级的资管交易系统,多个交易员共享统一的交易通道,并实现基金产品级别的风险管理。
================================================
FILE: docs/community/app/script_trader.md
================================================
# ScriptTrader - 脚本策略交易模块
## 功能简介
ScriptTrader是用于**脚本策略交易**的功能模块,提供了交互式的量化分析和程序化交易功能,又提供以整个策略连续运行的脚本策略功能。
故其可视为直接利用Python对交易客户端进行操作。它与CTA策略模块的区别在于:
- 突破了单交易所,单标的的限制;
- 可以较方便的实现如股指期货和一篮子股票之间的对冲策略、跨品种套利、股票市场扫描自动化选股等功能。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【ScriptTrader】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_scripttrader import ScriptTraderApp
# 写在创建main_engine对象后
main_engine.add_app(ScriptTraderApp)
```
## 启动模块
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【脚本策略】,或者点击左侧按钮栏的图标:

即可进入脚本交易模块的UI界面,如下图所示:

如果配置了数据服务(配置方法详见基本使用篇的全局配置部分),打开脚本交易模块时会自动执行数据服务登录初始化。若成功登录,则会输出“数据服务初始化成功”的日志,如下图所示:

用户可以通过UI界面使用以下功能:
### 启动
脚本策略需要事先编写好脚本策略文件,如test_strategy.py(脚本策略模板可参考[**脚本策略**](#jump)部分),因此点击【打开】按钮后需要用户指定该脚本策略文件的路径,如下图所示:

打开脚本策略之后,点击【启动】按钮则会启动脚本策略,并在下方界面输出相关信息,如下图所示:

### 停止
如果想停止脚本策略,直接点击【停止】按钮,之后策略会停止,通知会在下方界面输出“策略交易脚本停止”的日志,如下图所示:

### 清空
如果觉得下方显示界面的信息太多,或者想开启新的脚本策略,可以点击【清空】按钮,这时下方的所有信息就会被清空,如下图所示:

## 脚本策略模板
<span id="jump">
脚本策略文件编写需要遵循一定格式,下面提供使用模板,其作用为:
- 订阅两个品种的行情;
- 打印合约信息;
- 每隔3秒获取最新行情。
```python3
from time import sleep
from vnpy_scripttrader import ScriptEngine
def run(engine: ScriptEngine):
""""""
vt_symbols = ["sc2209.INE", "sc2203.INE"]
# 订阅行情
engine.subscribe(vt_symbols)
# 获取合约信息
for vt_symbol in vt_symbols:
contract = engine.get_contract(vt_symbol)
msg = f"合约信息,{contract}"
engine.write_log(msg)
# 持续运行,使用strategy_active来判断是否要退出程序
while engine.strategy_active:
# 轮询获取行情
for vt_symbol in vt_symbols:
tick = engine.get_tick(vt_symbol)
msg = f"最新行情, {tick}"
engine.write_log(msg)
# 等待3秒进入下一轮
sleep(3)
```
其中engine.strategy_active用于控制While循环,可视作是脚本策略的开关:
- 点击【启动】按钮,启动While循环,执行脚本策略;
- 点击【停止】按钮,退出While循环,停止脚本策略。
## 功能函数
Jupyter模式是基于脚本引擎(ScriptEngine)驱动的,下面通过jupyter notebook来说明ScriptEngine引擎的各功能函数。
首先打开Jupyter notebook,然后加载组件、初始化脚本引擎:
```python3
from vnpy_scripttrader import init_cli_trading
from vnpy_ctp import CtpGateway
engine = init_cli_trading([CtpGateway])
```
其中:
- 脚本引擎可以支持同时连接多个接口;
- init_cli_trading(gateways: Sequence[BaseGateway])可以将多个接口类,以列表的形式传递给init_cli_trading;
- init_cli_trading可视为vnpy封好的初始化启动函数,对主引擎、脚本引擎等各种对象进行了封装。
### 连接接口
**connect_gateway**
* 入参:setting: dict, gateway_name: str
* 出参:无
不同接口需要不同的配置参数,SimNow的配置如下:
```json
setting = {
"用户名": "xxxx",
"密码": "xxxx",
"经纪商代码": "9999",
"交易服务器":"180.168.146.187:10202",
"行情服务器":"180.168.146.187:10212",
"产品名称":"simnow_client_test",
"授权编码":"0000000000000000"
}
engine.connect_gateway(setting,"CTP")
```
其他接口配置可以参考site-packages目录下不同接口模块类(如vnpy_ctp.gateway.ctp_gateway)中的default_setting来填写。
### 订阅行情
**subscribe**
* 入参:vt_symbols: Sequence[str]
* 出参:无
subscribe()函数用于订阅行情信息,若需要订阅一篮子合约的行情,可以使用列表格式。
```python3
engine.subscribe(vt_symbols = ["rb2209.SHFE","rb2210.SHFE"])
```
### 查询数据
这里介绍一下连接上交易接口并成功订阅数据后的数据存储:
- 底层接口不停向主引擎推送新的数据;
- 主引擎里维护着一个ticks字典用于缓存不同标的的最新tick数据(仅能缓存最新数据);
- use_df的作用是转换成DataFrame格式,便于数据分析。
#### 单条查询
**get_tick**
* 入参:vt_symbol: str, use_df: bool = False
* 出参:TickData
查询单个标的最新tick,use_df为可选参数,用于把返回的类对象转化成DataFrame格式,便于数据分析。
```python3
tick = engine.get_tick(vt_symbol="rb2210.SHFE",use_df=False)
```
其中:
- vt_symbol:为本地合约代码,格式是合约品种+交易所,如rb2210.SHFE;
- use_df:为bool变量,默认False,返回TickData类对象,否则返回相应DataFrame,如下图所示:

**get_order**
* 入参:vt_orderid: str, use_df: bool = False
* 出参:OrderData
根据vt_orderid查询委托单的详细信息。
```python3
order = engine.get_order(vt_orderid="CTP.3_-1795780178_1",use_df=False)
```
其中,vt_orderid为本地委托号(在委托下单时,会自动返回该委托的vt_orderid)。

**get_contract**
* 入参:vt_symbol, use_df: bool = False
* 出参:ContractData
根据本地vt_symbol来查询对应合约对象的详细信息。
```python3
contract = engine.get_contract(vt_symbol="rb2210.SHFE",use_df=False)
```

**get_account**
* 入参:vt_accountid: str, use_df: bool = False
* 出参:AccountData
根据本地vt_accountid来查询对应资金信息。
```python3
account = engine.get_account(vt_accountid="CTP.189672",use_df=False)
```

**get_position**
* 入参:vt_positionid: str, use_df: bool = False
* 出参:PositionData
根据vt_positionid来查询持仓情况,返回对象包含接口名称、交易所、合约代码、数量、冻结数量等。
```python3
position = engine.get_position(vt_positionid='CTP.hc2305.SHFE.多')
```
注意,vt_positionid为vnpy内部对于一笔特定持仓的唯一持仓编号,格式为"gateway_name.vt_symbol.Direction.value",其中持仓方向可选“多”、“空”和“净”,如下图所示:

#### 多条查询
**get_ticks**
* 入参:vt_symbols: Sequence[str], use_df: bool = False
* 出参:Sequence[TickData]
查询多个合约最新tick。
```python3
ticks = engine.get_ticks(vt_symbols=['rb2209.SHFE','rb2210.SHFE'],use_df=True)
```
vt_symbols是列表格式,里面包含多个vt_symbol,如图。

**get_orders**
* 入参:vt_orderids: Sequence[str], use_df: bool = False
* 出参:Sequence[OrderData]
根据查询多个vt_orderid查询其详细信息。vt_orderids为列表,里面包含多个vt_orderid。
```python3
orders = engine.get_orders([orderid_one,orderid_two],use_df=True)
```
**get_trades**
* 入参:vt_orderid: str, use_df: bool = False
* 出参:Sequence[TradeData]
根据给定的一个vt_orderid返回这次报单过程中的所有TradeData对象。vt_orderid是本地委托号,每一个委托OrderData,由于部分成交关系,可以对应多笔成交TradeData。
```python3
trades = engine.get_trades(vt_orderid=your_vt_orderid,use_df=True)
```
**get_bars**
* 入参:vt_symbol: str, start_date: str, interval: Interval, use_df: bool = False
* 出参:Sequence[BarData]
通过配置的数据服务查询历史数据。
```python3
bars = engine.get_bars(vt_symbol="rb2210.SHFE",start_date="20211201",
interval=Interval.MINUTE,use_df=False)
```
其中:
- vt_symbol:本地合约代码,格式为合约代码 + 交易所名称;
- start_date:起始日期,格式为"%Y%m%d";
- interval:K线周期,包括:分钟、小时、日、周;
- bars:包含了一系列BarData数据的列表对象,其BarData的定义如下:
```python3
@dataclass
class BarData(BaseData):
symbol: str
exchange: Exchange
datetime: datetime
interval: Interval = None
volume: float = 0
turnover: float = 0
open_interest: float = 0
open_price: float = 0
high_price: float = 0
low_price: float = 0
close_price: float = 0
def __post_init__(self):
self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
```
#### 全量查询
在全量查询中,唯一参数是use_df,默认为False。返回的是一个包含相应数据的List对象,例如ContractData、AccountData和PositionData。
**get_all_contracts**
* 入参:use_df: bool = False
* 出参:Sequence[ContractData]
默认返回一个list,包含了全市场的ContractData,如果use_df=True则返回相应的DataFrame。
**get_all_active_orders**
* 入参:use_df: bool = False
* 出参:Sequence[OrderData]
活动委托指的是等待委托完全成交,故其状态包含“已提交、未成交、部分成交”;函数将返回包含一系列OrderData的列表对象。
**get_all_accounts**
* 入参:use_df: bool = False
* 出参:Sequence[AccountData]
默认返回包含AccountData的列表对象。
**get_all_positions**
* 入参:use_df: bool = False
* 出参:Sequence[PositionData]
默认返回包含PositionData的列表对象,如下图所示:

### 交易委托
**buy**:买入开仓(Direction:LONG,Offset:OPEN)
**sell**:卖出平仓(Direction:SHORT,Offset:CLOSE)
**short**:卖出开仓(Direction:SHORT,Offset:OPEN)
**cover**:买入平仓(Direction:LONG,Offset:CLOSE)
* 入参:vt_symbol: str, price: float, volume: float, order_type: OrderType = OrderType.LIMIT
* 出参:str
以委托买入为例,engine.buy()函数入参包括:
- vt_symbol:本地合约代码(字符串格式);
- price:报单价格(浮点数类型);
- volume:报单数量(浮点数类型);
- order_type:OrderType枚举常量,默认为限价单(OrderType.LIMIT),同时支持停止单(OrderType.STOP)、FAK(OrderType.FAK)、FOK(OrderType.FOK)、市价单(OrderType.MARKET),不同交易所支持报单方式不完全一致。
```python3
engine.buy(vt_symbol="rb2210.SHFE", price=4200, volume=1, order_type=OrderType.LIMIT)
```
执行交易委托后会返回本地委托号vt_orderid。
**send_order**
* 入参:vt_symbol: str, price: float, volume: float, direction: Direction, offset: Offset, order_type: OrderType
* 出参:str
send_order函数是脚本交易策略引擎调用的发送委托的函数。一般在策略编写的时候不需要单独调用,通过buy/sell/short/cover函数发送委托即可。
**cancel_order**
* 入参:vt_orderid: str
* 出参:无
基于本地委托号撤销委托。
```python3
engine.cancel_order(vt_orderid='CTP.3_-1795780178_1')
```
### 信息输出
**write_log**
* 入参:msg: str
* 出参:无
在策略中调用write_log函数,可以进行指定内容的日志输出。
**send_email**
* 入参:msg: str
* 出参:无
配置好邮箱相关信息之后(配置方法详见基本使用篇的全局配置部分),调用send_email函数可以发送标题为“脚本策略引擎通知”的邮件到自己的邮箱。
================================================
FILE: docs/community/app/spread_trading.md
================================================
# SpreadTrading - 多合约价差套利模块
## 功能简介
SpreadTrading是用于**多合约价差套利**的功能模块,用户可以通过其UI界面操作来便捷创建灵活的价差合约、完成手动交易和自动交易等任务。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【SpreadTrading】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_spreadtrading import SpreadTradingApp
# 写在创建main_engine对象后
main_engine.add_app(SpreadTradingApp)
```
## 启动模块
<span id="jump">
对于用户自行开发的策略,需要放到VeighNa Trader运行时目录下的**strategies**目录中,才能被识别加载。具体的运行时目录路径,可以在VeighNa Trader主界面顶部的标题栏查看。
对于在Windows上默认安装的用户来说,放置策略的strategies目录路径通常为:
```bash
C:\Users\Administrator\strategies
```
其中Administrator为当前登录Windows的系统用户名。
</span>
在启动模块之前,请先连接交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块(**如果在合约信息查询成功之前打开模块,可能会导致价差的价格跳动取值为零,进而在委托成交之后引发底层报错**),如下图所示:

请注意,IB接口因为登录时无法自动获取所有的合约信息,只有在用户手动订阅行情时才能获取。因此需要在主界面上先手动订阅合约行情,再启动模块。
成功连接交易接口后,在菜单栏中点击【功能】-> 【价差交易】,或者点击左侧按钮栏的图标:

即可进入价差交易模块的UI界面,如下图所示:

## 创建价差合约
### 查询合约
在创建价差合约前,用户可以通过【查询合约】功能,寻找可以组成价差的合约(**不支持交易所套利合约**):
- 在VeighNa Trader菜单栏中点击【帮助】-> 【查询合约】按钮,弹出合约查询界面,如下图所示:

- 在界面中找到可用于组成价差交易的合约;
- 本文档以豆油期货的跨期套利来展示,即交易y2205.DCE(豆油期货22年5月到期合约)和y2209.DCE(豆油期货22年9月到期合约)。
### 构建价差合约
在价差交易的界面左侧,点击【价差创建】按钮,弹出创建价差界面,如下图所示:

价差交易模块支持灵活的价差计算公式(例如A/B、A-B*C等),同时允许引入不参与交易的定价腿,满足复杂境内外套利价差需要考虑汇率和税率等因素的需求。在创建价差合约时,需要配置相关参数,各参数要求如下:
- 价差名称
- 用户定义的价差合约名称;
- 价差名称不能重名;
- 主动腿代码
- 价差盘口价格满足条件时,先发出的那条腿的本地代码。
- 格式为vt_symbol(合约代码 + 交易所名称);
- 必须是下面的腿选项中的一项;
- 最小交易量
- 最小交易手数;
- 价格公式
- 价差合约的计算公式;
- 支持任何Python内置数学函数;
- 注意其中的变量只能是A、B、C、D、E(不需要都用);
- 【A、B、C、D、E】
- 包含构建价差合约的主动腿与被动腿,也可以引入不参与交易的定价腿,由合约代码、交易方向、交易乘数组成:
- 合约代码为公式中的变量所对应的合约本地代码(vt_symbol);
- 一般来说,价差交易原则上是主动腿完成交易后,立刻用被动腿进行对冲,故主动腿一般选择较为不活跃的合约,价格乘数和交易乘数均为正;被动腿一般选择较为活跃的合约,价格乘数和交易乘数均为负;
- 不用的变量留空即可;
设置好价差合约的参数后,点击下方的【创建价差】按钮,即可成功创建价差合约。
在豆油期货跨期套利示例中,其价格乘数和交易乘数均为1:1,即价差 = y2205 - y2209;买入1手价差等于买入1手y2205,同时卖出1手y2209完成对冲。
请注意,在多条腿并且期货合约规模不等时,构建价差合约会相对困难一些,如构建虚拟钢厂套利所用到的价差合约时,计算公式如下:
- 螺纹钢生产技艺是16吨铁矿石加上5吨焦炭练成10吨螺纹钢。
- 基于价格乘数的价差spread = 1* RB - 1.6\*I - 0.5\*J。
- 但是由于螺纹是10吨/手,铁矿石和焦炭都是100吨/手,所以他们交易乘数是1:10:10;
- 故基于最大公约数规则,其实际交易手数关系是每买入100手螺纹钢(1000吨),需要卖出16手铁矿石(1600吨)和5手焦炭(500吨)完成对冲。
### 监控价差合约
价差合约创建完毕,监控界面中的【日志】栏会输出“价差创建成功”;【价差】栏也会展示价差合约的实时行情,如下图所示:

在豆油期货价差交易示例中,【价差】组件的各字段含义如下所示:
- 买价
- y2205买一价 - y2209卖一价
- 买量
- min(y2205买一量, y2209卖一量)
- 取最小值用于保证各合约能均能成交
- 卖价
- y2205卖一价 - y2209买一价
- 卖量
- min(y2205卖一量, y2209买一量)
### 移除价差合约
在价差交易的界面左侧,点击【移除价差】按钮,弹出移除价差界面,如下图所示:

选择好要移除的价差合约之后,点击【移除】按钮,即可成功移除价差合约。【日志】组件输出“价差移除成功”,如下图所示:

## 手动交易
假设当前豆油期货价差合约买价为408,卖价为420,并且在大周期上,价差围绕0上下波动。
价差交易的盈利在于高抛低吸,即在低位,如-300买入豆油期货价差合约,在高位,如+800卖出价差合约,平仓获利离场。由于不能立刻成交,所以其默认执行算法SpreadTaker(主动对价成交算法)会每隔一段时间进行委托操作,一般是以超价的限价单的形式发出委托。
下面通过2个例子,分别是发出委托立即成交和发出委托等待成交来具体介绍手动交易的操作情况:
### 发出委托立即成交
假设目标价差合约价格为420,我们以超价5跳的形式,即430的价位发出买入限价单,如下图所示:

由于限价单(430)价位高于当前卖价(410),所以委托立刻成交,如下图所示:

此时各监控组件状态如下所示:
- 日志组件
- 买入y_05_09价差合约的顺序是:发出y2205多头委托 -> y2205委托成交 -> 发出y2209空头委托 -> y2209委托成交。价差交易必须遵循的逻辑是主动腿成交后,才去用被动腿来对冲头寸,并且对冲必须尽可能及时。这也是为什么一般被动腿会选择较为活跃合约的原因。
- 价差组件
- 买入1手豆油期货价差合约成交后,【净仓】从0变成1。实际上,VeighNa Trader【持仓】组件显示,y2205合约多头持仓1手,y2209合约空头持仓1手。
- 算法组件
- 本次委托SpreadTaker算法执行情况:成交数量1手,委托状态是【全部成交】。
### 发出委托等待成交
以400的价位发出限价买入指令,由于当前买价卖价分别位于412和426,所以委托状态显示【未成交】,如下图所示:

此时各监控组件状态如下所示:
- 日志组件
- 本次算法即SpreadTaker_000002已经启动,但由于价格没有触发到目标价位,算法在循环读秒中处于等待状态;
- 算法组件
- 委托状态为【未成交】,要结束算法只需鼠标双击【SpreadTaker_000002】单元格即可。
仅当卖价低于-300时,才触发该限价单,已超价5跳,即-290去主动成交。
### 撤销委托
鼠标双击【SpreadTaker_000002】单元格,即可结束该算法。此时【日志】组件输出“算法已停止”,【算法】组件显示委托状态由【未成交】变成【已撤销】,如下图所示:

## 自动交易
### 添加策略
用户可以基于编写好的价差策略模板(类)来创建不同的策略实例(对象)。
在左侧的下拉框中选择要交易的策略名称(如BasicSpreadStrategy),如下图所示:

请注意,显示的策略名称是**策略类**(驼峰式命名)的名字,而不是策略文件(下划线模式命名)的名字。
选择好策略类之后,点击【添加策略】,会弹出添加策略对话框,如下图所示:

在创建策略实例时,需要配置相关参数,各参数要求如下:
- 实例名称
- 用户自定义的策略实例名称,这里是test;
- 策略实例名称不能重名;
- 价差名称
- 用于交易的价差合约,这里是y_05_09;
- 一定要是价差组件可以查询到的价差合约;
- 参数设置
- 显示的参数名是策略里写在parameters列表中的参数名;
- 默认数值为策略里的参数的默认值;
- 由上图可观察到,参数名后面<>括号中显示的是该参数的数据类型,在填写参数时应遵循相应的数据类型。其中,<class 'str'>是字符串、<class 'int'>是整数、<class 'float'>是浮点数;
- 请注意,如果某个参数可能会调整至有小数位的数值,而默认参数值是整数(比如1)。请在编写策略时,把默认参数值设为浮点数(比如1.0)。否则策略会默认该项参数为整数,在后续【编辑】策略实例参数时,会只允许填进整数。
- 以BasicSpreadStrategy为例,该策略的参数设置如下:
- buy_price
- 买入开仓阈值,图中是-300,即当价格跌破-300时,执行委托;
- sell_price
- 卖出平仓阈值,图中是400,即当价格回升到400时,执行委托;
- short_price
- 卖出开仓阈值,图中是800,即当价格上涨到800时,执行委托;
- cover_price
- 买入平仓阈值,图中是600,即当价格下跌到600时,执行委托;
- max_pos
- 主动腿委托数量;
- payup
- 超价的跳数;
- interval
- 时间间隔,即每隔一段时间,会发出委托。
参数配置完成后,点击【添加】按钮,则开始创建策略实例。创建成功后可在右下角的策略监控组件中看到该策略实例,如下图所示:

策略监控组件顶部显示的是策略实例名、价差名、策略类名以及策略作者名(在策略里定义的author)。顶部按钮用于控制和管理策略实例,第一行表格显示了策略内部的参数信息(参数名需要写在策略的parameters列表中图形界面才会显示),第二行表格则显示了策略运行过程中的变量信息(变量名需要写在策略的variables列表中图形界面才会显示)。【inited】字段表示当前策略的初始化状态(是否已经完成了历史数据回放),【trading】字段表示策略当前是否能够开始交易。
从上图可观察到,此时该策略实例的【inited】和【trading】状态都为【False】。说明该策略实例还没有初始化,也还不能发出交易信号。
策略实例创建成功后,该策略实例的配置信息会被保存到.vntrader文件夹下的spread_trading_strategy.json文件中。
### 管理策略
#### 初始化
策略实例创建成功后,就可以对该实例进行初始化了。点击该策略实例下的【初始化】按钮,若初始化成功,则如下图所示:

可观察到此时该策略实例的【inited】状态已经为【True】。说明该策略实例已经调用过load_bar函数加载历史数据并完成初始化了。【trading】状态还是为【False】,说明此时该策略实例还不能开始自动交易。
#### 启动
策略实例初始化成功,【inited】状态为【True】时,才能启动该策略的自动交易功能。点击该策略实例下的【启动】按钮,即可启动该策略实例。成功启动后,【日志】组件则会输出相应信息(请注意,策略启动并不代表算法启动,算法启动状态取决于策略逻辑),如下图所示:

此时,【算法】组件显示,test策略调用SpreadTaker算法,分别在-300和800的位子上挂上买入和卖出委托;由于实际价格没有达到这2个阈值,故委托一直挂着,其委托状态为【未成交】。

【策略】组件中【trading】字段从【False】变为【True】,如下图所示:

#### 停止
若要停止策略,点击策略实例下的【停止】按钮,即可停止该策略实例的自动交易。【日志】组件输出“算法已停止”,如下图所示:

【算法】组件中算法状态变为【已撤销】,如下图所示:

【策略】组件中【trading】字段从【True】变为【False】,如下图所示:

#### 编辑
如果创建策略实例之后,想要编辑某个策略实例的参数(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【编辑】按钮,会弹出参数编辑对话框,以供修改策略参数,如下图所示:

编辑完策略参数之后,点击下方的【确定】按钮,相应的修改会立即更新在参数表格中,如下图所示:

但是策略实例的交易合约代码无法修改,同时修改完后也不会重新执行初始化操作。也请注意,此时修改的只是.vntrader文件夹下spread_trading_strategy.json文件中该策略实例的参数值,并没有修改原策略文件下的参数。
修改前,json文件如下图所示:

修改后,json文件如下图所示:

若盘中编辑后想要再次启动策略,点击策略实例下的【启动】按钮即可再次启动该策略实例,如下图所示:

#### 移除
如果创建策略实例之后,想要移除某个策略实例(若已启动策略,需要先点击策略实例下的【停止】按钮,停止策略),可以点击该策略实例下的【移除】按钮。移除成功后,图形界面右下角的策略监控组件中将不会再显示该策略实例的信息。如下图所示:

此时.vntrader文件夹下的spread_trading_strategy.json文件也移除了该策略实例的配置信息。
### 批量操作
在策略经过充分测试,实盘运行较为稳定,不需要经常进行调整的情况下,如果有多个需要运行的价差策略实例,可以使用界面左下角的【全部初始化】、【全部启动】和【全部停止】功能来执行盘前批量初始化、启动策略实例以及盘后批量停止策略实例的操作。
#### 全部初始化
在所有策略实例创建成功后,点击左下角的【全部初始化】按钮,则可批量初始化策略实例,如下图所示:
点击【全部初始化】后,如下图所示:

#### 全部启动
在所有策略实例初始化成功后,点击左下角的【全部启动】按钮,则可批量启动策略实例,如下图所示:

#### 全部停止
在所有策略实例启动成功后,点击左下角的【全部停止】按钮,则可批量停止策略实例,如下图所示:

## 价差交易策略模板(SpreadStrategyTemplate)
价差交易策略模板提供了信号生成和委托管理功能,用户可以基于该模板(位于vnpy_spreadtrading.template中)自行开发策略。
用户自行开发的策略可以放在用户运行文件夹下的[strategies](#jump)文件夹内。
请注意:
1. 策略文件命名采用下划线模式,如statistical_arbitrage_strategy.py,而策略类命名采用驼峰式,如StatisticalArbitrageStrategy。
2. 自建策略的类名不要与示例策略的类名重合。如果重合了,图形界面上只会显示一个策略类名。
目前,VeighNa官方提供两个价差策略,即BasicSpreadStrategy和StatisticalArbitrageStrategy。下面通过StatisticalArbitrageStrategy示例,来展示策略开发的具体步骤:
在基于价差交易策略模板编写策略逻辑之前,需要在策略文件的顶部载入需要用到的内部组件,如下方代码所示:
```python3
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy_spreadtrading import (
SpreadStrategyTemplate,
SpreadAlgoTemplate,
SpreadData,
OrderData,
TradeData,
TickData,
BarData
)
```
其中,SpreadStrategyTemplate和SpreadAlgoTemplate是价差交易策略模板和价差算法模板,SpreadData、OrderData、TickData、TradeData和BarData是储存对应信息的数据容器,BarGenerator是K线生成模块,ArrayManager是K线时间序列管理模块。
### 策略参数与变量
在策略类的下方,可以设置策略的作者(author),参数(parameters)以及变量(variables),如下方代码所示:
```python3
author = "用Python的交易员"
boll_window = 20
boll_dev = 2
max_pos = 10
payup = 10
interval = 5
spread_pos = 0.0
boll_up = 0.0
boll_down = 0.0
boll_mid = 0.0
parameters = [
"boll_window",
"boll_dev",
"max_pos",
"payup",
"interval"
]
variables = [
"spread_pos",
"boll_up",
"boll_down",
"boll_mid"
]
```
虽然策略的参数和变量都从属于策略类,但策略参数是固定的(由交易员从外部指定),而策略变量则在交易的过程中随着策略的状态变化,所以策略变量一开始只需要初始化为对应的基础类型。例如:整数设为0,浮点数设为0.0,而字符串则设为""。
如果需要价差交易模块引擎在运行过程中,将策略参数和变量显示在UI界面上,并在数据刷新、停止策略时保存其数值,则需把参数和变量的名字(以字符串的数据类型)添加进parameters和variables列表里。
请注意,该列表只能接受参数和变量以str、int、float和bool四种数据类型传入。如果策略里需要用到其他数据类型的参数与变量,请把该参数或变量的定义放到__init__函数下。
### 类的初始化
入参:strategy_engine, strategy_name: str, spread: SpreadData, setting: dict
出参:无
__init__函数是策略类的构造函数,需要与继承的SpreadStrategyTemplate保持一致。
在这个继承的策略类里,初始化一般分三步,如下方代码所示:
```python3
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
""""""
super().__init__(
strategy_engine, strategy_name, spread, setting
)
self.bg = BarGenerator(self.on_spread_bar)
self.am = ArrayManager()
```
1 . 通过super( )的方法继承SpreadStrategyTemplate,在__init__( )函数中传入策略引擎、策略名称、价差以及参数设置(以上参数均由策略引擎在使用策略类创建策略实例时自动传入,用户无需进行设置);
2 . 调用K线生成模块(BarGenerator):通过时间切片将Tick数据合成1分钟K线数据。如有需求,还可合成更长的时间周期数据。
3 . 调用K线时间序列管理模块(ArrayManager):基于K线数据将其转化为便于向量化计算的时间序列数据结构,并在内部支持使用talib库来计算相应的技术指标。
ArrayManager的默认长度为100,如需调整ArrayManager的长度,可传入size参数进行调整(size不能小于计算指标的周期长度)。
### 价差策略引擎调用的函数
SpreadStrategyTemplate中的update_setting函数、该函数后面四个以get开头的函数和后面两个以update开头的函数,都是价差策略引擎去负责调用的函数,一般在策略编写的时候是不需要调用的。
### 策略的回调函数
SpreadStrategyTemplate中以on开头的函数称为回调函数,在编写策略的过程中能够用来接收价差行情或者接收状态更新。回调函数的作用是当某一个事件发生的时候,策略里的这类函数会被价差交易策略引擎自动调用(无需在策略中主动操作)。回调函数按其功能可分为以下三类:
#### 策略实例状态控制(所有策略都需要)
**on_init**
* 入参:无
* 出参:无
初始化策略时on_init函数会被调用,默认写法是调用write_log函数输出“策略初始化”日志,再调用load_bar函数加载历史数据,如下方代码所示:
```python3
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bar(10)
```
请注意,如果是基于Tick数据回测,请在此处调用load_tick函数。
策略初始化时,策略的inited和trading状态都为【False】,此时只是调用ArrayManager计算并缓存相关的计算指标,不能发出交易信号。调用完on_init函数之后,策略的inited状态才变为【True】,策略初始化才完成。
**on_start**
* 入参:无
* 出参:无
启动策略时on_start函数会被调用,默认写法是调用write_log函数输出“策略启动”日志,如下方代码所示:
```python3
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
```
调用策略的on_start函数启动策略后,策略的trading状态变为【True】,此时策略才能够发出交易信号。
**on_stop**
* 入参:无
* 出参:无
停止策略时on_stop函数会被调用,默认写法是调用write_log函数输出“策略停止”日志,同时还原策略的变量,如下方代码所示:
```python3
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
self.put_event()
```
调用策略的on_stop函数停止策略后,策略的trading状态变为【False】,此时策略就不会发出交易信号了。
#### 接收数据、计算指标、发出交易信号
**on_spread_data**
* 入参:无
* 出参:无
当价差数据更新的时候on_spread_data函数会被调用(因本次示例策略类StatisticalArbitrageStrategy不是基于on_spread_data交易,故不作示例讲解。基于on_spread_data交易的示例代码可参考示例策略BasicSpreadStrategy)。StatisticalArbitrageStrategy的写法是先调用get_spread_tick获取价差Tick数据,然后推进on_spread_tick函数中,如下方代码所示:
```python3
def on_spread_data(self):
"""
Callback when spread price is updated.
"""
tick = self.get_spread_tick()
self.on_spread_tick(tick)
```
**on_spread_tick**
* 入参:tick: TickData
* 出参:无
当策略收到最新的价差Tick数据的行情时,on_spread_tick函数会被调用。默认写法是通过BarGenerator的update_tick函数把收到的Tick数据推进前面创建的bg实例中以便合成1分钟的K线,如下方代码所示:
```python3
def on_spread_tick(self, tick: TickData):
"""
Callback when new spread tick data is generated.
"""
self.bg.update_tick(tick)
```
**on_spread_bar**
* 入参:bar: BarData
* 出参:无
当策略收到最新的价差K线数据时(实盘时默认推进来的是基于Tick合成的一分钟的K线,回测时则取决于选择参数时填入的K线数据频率),on_spread_bar函数就会被调用。
如果策略基于on_spread_bar推进来的K线交易,那么请把交易请求类函数都写在on_spread_bar函数下。示例策略类StatisticalArbitrageStrategy是通过1分钟K线数据回报来生成CTA信号的。一共有三部分,如下方代码所示:
```python3
def on_spread_bar(self, bar: BarData):
"""
Callback when spread bar data is generated.
"""
self.stop_all_algos()
self.am.update_bar(bar)
if not self.am.inited:
return
self.boll_mid = self.am.sma(self.boll_window)
self.boll_up, self.boll_down = self.am.boll(
self.boll_window, self.boll_dev)
if not self.spread_pos:
if bar.close_price >= self.boll_up:
self.start_short_algo(
bar.close_price - 10,
self.max_pos,
payup=self.payup,
interval=self.interval
)
elif bar.close_price <= self.boll_down:
self.start_long_algo(
bar.close_price + 10,
self.max_pos,
payup=self.payup,
interval=self.interval
)
elif self.spread_pos < 0:
if bar.close_price <= self.boll_mid:
self.start_long_algo(
bar.close_price + 10,
abs(self.spread_pos),
payup=self.payup,
interval=self.interval
)
else:
if bar.close_price >= self.boll_mid:
self.start_short_algo(
bar.close_price - 10,
abs(self.spread_pos),
payup=self.payup,
interval=self.interval
)
self.put_event()
```
- 清空未成交委托:为了防止之前下的单子在上1分钟没有成交,但是下1分钟可能已经调整了价格,就用stop_all_algos()方法立刻撤销之前未成交的所有委托,保证策略在当前这1分钟开始时的整个状态是清晰和唯一的;
- 调用K线时间序列管理模块:基于最新的1分钟价差K线数据来计算相应的技术指标,如布林带通道上下轨等。首先获取ArrayManager对象,然后将收到的K线推送进去,检查ArrayManager的初始化状态,如果还没初始化成功就直接返回,没有必要去进行后续的交易相关的逻辑判断。因为很多技术指标计算对最少K线数量有要求,如果数量不够的话计算出来的指标会出现错误或无意义。反之,如果没有return,就可以开始计算技术指标了;
- 信号计算:通过持仓的判断以及结合布林带通道在通道突破点挂出委托,同时设置离场点。
请注意,如果需要在图形界面刷新指标数值,请不要忘记调用put_event()函数。
#### 委托状态更新
以下函数在策略中几乎都可以直接pass,其具体逻辑应用交给回测/实盘引擎负责。
**on_spread_pos**
* 入参:无
* 出参:无
收到持有仓位更新时on_spread_pos函数会被调用。与CTA策略模块访问策略逻辑持仓不同,价差交易模块访问的是账户底层持仓。所以默认写法是通过调用get_spread_pos函数获取价差持仓,以供策略进行逻辑判断,如下方代码所示:
```python3
def on_spread_pos(self):
"""
Callback when spread position is updated.
"""
self.spread_pos = self.get_spread_pos()
self.put_event()
```
**on_spread_algo**
* 入参:algo: SpreadAlgoTemplate
* 出参:无
收到算法状态更新时on_spread_algo函数会被调用。
**on_order**
* 入参:order: OrderData
* 出参:无
收到策略委托回报时on_order函数会被调用。
**on_trade**
* 入参:trade: TradeData
* 出参:无
收到策略成交回报时on_trade函数会被调用。
### 主动函数
**start_long_algo**
* 入参:price: float, volume: float, payup: int, interval: int, lock: bool = False, extra: dict = None
* 出参:algoid: str
**start_short_algo**
* 入参:price: float, volume: float, payup: int, interval: int, lock: bool = False, extra: dict = None
* 出参:algoid: str
与CTA策略模块不同,价差交易的示例策略都是通过调用star_long_algo/start_short_algo函数(针对价差)而不是buy/sell/short/cover函数(针对特定合约)来发出委托的。在价差交易模块中,算法负责价差交易的执行,策略负责价差算法的调度。价差算法将价差交易简化为了普通委托,封装掉了所有主动腿下单和被动腿对冲的细节。
以下方star_long_algo函数的代码为例,可以看到,价格、数量、超价的数值、时间间隔是必填的参数,锁仓转换和开平方向则分别默认为False和Offset.NONE。也可以看到,函数内部收到传进来的参数之后就调用了SpreadStrategyTemplate里的start_algo函数来发单(因为是long指令,则自动把方向填成了LONG)
```python3
def start_long_algo(
self,
price: float,
volume: float,
payup: int,
interval: int,
lock: bool = False,
extra: dict = None
) -> str:
""""""
if not extra:
extra = None
return self.start_algo(
Direction.SHORT, price, volume,
payup, interval, lock, extra
)
```
**start_algo**
* 入参:direction: Direction, price: float, volume: float, payup: int, interval: int, lock: bool, extra: dict
* 出参:algoid: str
start_algo函数是价差策略引擎调用的启动新的价差交易算法的函数。一般在策略编写的时候不需要单独调用,通过start_long_algo/start_short_algo函数发送委托即可。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能发出交易委托。如果策略的Trading状态为【False】时调用了该函数,只会返回[]。
**stop_algo**
* 入参:algoid: str
* 出参:无
**stop_all_algos**
* 入参:无
* 出参:无
stop_algo和stop_all_algos都是负责停止价差算法的交易请求类函数。stop_algo是停止策略内指定的价差算法,stop_all_algos是停止策略所有的活动价差算法。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能撤单。
**buy**:买入开仓(Direction:LONG,Offset:OPEN)
**sell**:卖出平仓(Direction:SHORT,Offset:CLOSE)
**short**:卖出开仓(Direction:SHORT,Offset:OPEN)
**cover**:买入平仓(Direction:LONG,Offset:CLOSE)
* 入参:vt_symbol: str, price: float, volume: float, lock: bool = False
* 出参:vt_orderids: List[vt_orderid] / 无
buy/sell/short/cover都是策略内部的负责针对特定合约发出底层交易委托的请求类函数。策略可以通过这些函数给价差策略引擎发送交易信号来达到下单的目的。
以下方buy函数的代码为例,可以看到,本地代码、价格和数量是必填的参数,锁仓转换则默认为False。也可以看到,函数内部收到传进来的参数之后就调用了SpreadStrategyTemplate里的send_order函数来发单(因为是buy指令,则自动把方向填成了LONG,开平填成了OPEN)
如果lock设置为True,那么该笔订单则会进行锁仓委托转换(在有今仓的情况下,如果想平仓,则会先平掉所有的昨仓,然后剩下的部分都进行反向开仓来代替平今仓,以避免平今的手续费惩罚)。
```python3
def buy(self, vt_symbol: str, price: float, volume: float, lock: bool = False) -> List[str]:
""""""
return self.send_order(vt_symbol, price, volume, Direction.LONG, Offset.OPEN, lock)
```
**send_order**
* 入参:vt_symbol: str, price: float, volume: float, direction: Direction, offset: Offset, lock: bool = False
* 出参:vt_orderids / 无
send_order函数是价差策略引擎调用的针对特定合约(**而不是价差**)发送委托的函数。一般在策略编写的时候不需要单独调用,通过buy/sell/short/cover函数发送委托即可。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能发出交易委托。如果策略的Trading状态为【False】时调用了该函数,只会返回[]。
**cancel_order**
* 入参:vt_orderid: str
* 出参:无
**cancel_all**
* 入参:无
* 出参:无
cancel_order和cancel_all都是负责撤单的交易请求类函数。cancel_order是撤掉策略内指定的活动委托,cancel_all是撤掉策略所有的活动委托。
请注意,要在策略启动之后,也就是策略的trading状态变为【True】之后,才能撤单。
### 功能函数
以下为策略以外的功能函数:
**put_event**
* 入参:无
* 出参:无
在策略中调用put_event函数,可以通知图形界面刷新策略状态相关显示。
请注意,要策略初始化完成,inited状态变为【True】之后,才能刷新界面。
**write_log**
* 入参:msg: str
* 出参:无
在策略中调用write_log函数,可以进行指定内容的日志输出。
**get_spread_tick**
* 入参:无
* 出参:tick: TickData
在策略里调用get_spread_tick函数,可以获取价差Tick数据。
**get_spread_pos**
* 入参:无
* 出参:spread_pos: float
在策略里调用get_spread_pos函数,可以获取价差净持仓数据。
**get_leg_tick**
* 入参:vt_symbol: str
* 出参:leg.tick: TickData / None
在策略里调用get_leg_tick函数,可以获取特定合约的Tick数据。
**get_leg_pos**
* 入参:vt_symbol: str, direction: Direction = Direction.NET
* 出参:leg.net_pos: float / leg.long_pos: float /leg.short_pos: float / None
在策略里调用get_leg_pos函数,可以获取特定合约的持仓数据,用于处理瘸腿后的细粒度调整。
**send_email**
* 入参:msg: str
* 出参:无
配置好邮箱相关信息之后(配置方法详见基本使用篇的全局配置部分),在策略中调用send_email函数,可以发送指定内容的邮件到自己的邮箱。
请注意,要策略初始化完成,inited状态变为【True】之后,才能发送邮件。
**load_bar**
* 入参:days: int, interval: Interval = Interval.MINUTE, callback: Callable = None
* 出参:无
在策略中调用load_bar函数,可以在策略初始化时加载价差K线数据。
如下方代码所示,load_bar函数调用时,默认加载的天数是10,频率是一分钟,对应也就是加载10天的1分钟K线数据。在回测时,10天指的是10个交易日,而在实盘时,10天则是指的是自然日,因此建议加载的天数宁可多一些也不要太少。加载时会先依次尝试通过交易接口、数据服务、数据库获取历史数据,直到获取历史数据或返回空。
请注意,回测期内每条腿的K线数据(1分钟最佳),若有某条腿缺失一段,则所有腿的这一段数据都会被弃用。
```python3
def load_bar(
self,
days: int,
interval: Interval = Interval.MINUTE,
callback: Callable = None,
):
"""
Load historical bar data for initializing strategy.
"""
if not callback:
callback = self.on_spread_bar
self.strategy_engine.load_bar(self.spread, days, interval, callback)
```
**load_tick**
* 入参:days: int
* 出参:无
价差Tick数据来源:
首先需要在SpreadTrading模块中创建配置好价差后,通过DataRecorder模块来进行Tick录制,本地代码填入xx-spread.LOCAL,其中xx-spread为用户定义的价差名称,LOCAL为固定交易所后缀(代表本地生成)。
在策略中调用load_tick函数,可以在策略初始化时去数据库加载录制好的价差Tick盘口数据。
================================================
FILE: docs/community/app/web_trader.md
================================================
# WebTrader - Web服务器模块
## 功能简介
WebTrader是用于**Web应用后端服务**的功能模块,用户可以通过浏览器(而非PyQt桌面端)来运行管理VeighNa量化策略交易。
## 架构设计
WebTrader采用了FastAPI作为后端服务器,支持REST主动请求调用和WebSocket被动数据推送,运行时整体框架图如下:

后端服务包括两个独立的进程:
- 策略交易进程
- 运行VeighNa Trader的进程,负责所有策略交易功能的运行;
- 启动了RpcServer用于对Web服务进程功能调用;
- Web服务进程
- 运行了FastAPI的进程,负责对外提供Web访问的服务;
- 启动了RpcClient用于调用策略交易进程的相关功能。
从网页端到策略交易进程的双向通讯模式包括:
- 主动请求调用(订阅行情、挂撤单、查询数据)
- 浏览器发起REST API调用(访问某个URL地址提交数据)到Web服务进程;
- Web服务进程收到后,转换为RPC请求(Req-Rep通讯模式)发送给策略交易进程;
- 策略交易进程执行请求处理后,返回结果给Web服务进程;
- Web服务进程返回数据给浏览器。
- 被动数据推送(行情推送、委托推送)
- 浏览器发起Websocket连接到Web服务进程;
- 策略交易进程通过RPC推送(Pub-Sub通讯),将数据推送给Web服务进程;
- Web服务进程收到后,将数据通过Websocket API实时推送给浏览器(JSON格式)。
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【WebTrader】。
### 脚本加载
在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_webtrader import WebTraderApp
# 写在创建main_engine对象后
main_engine.add_app(WebTraderApp)
```
### 启动模块
在启动模块之前,请先连接登录交易接口(连接方法详见基本使用篇的连接接口部分)。看到VeighNa Trader主界面【日志】栏输出“合约信息查询成功”之后再启动模块,如下图所示:

成功连接交易接口后,在菜单栏中点击【功能】-> 【Web服务】,或者点击左侧按钮栏的图标:

即可进入RPC服务模块的UI界面,如下图所示:

此时系统中运行的只包括策略交易进程,左上角区域的服务器配置选项包括:
- 用户名和密码:从网页端登录Web应用时所用的用户名和密码,使用时请修改为自己想用的用户名和密码(通过启动目录.vntrader下的web_trader_setting.json修改),请注意这里的用户名和密码与底层交易接口无关;
- 请求和订阅地址:架构图中Web服务进程和策略交易进程之间,进行RPC通讯的地址,注意端口不要和其他程序冲突即可。
点击启动按钮后,会根据用户输入的配置信息在系统后台启动Web服务进程,同时在右侧区域输出Fast API运行过程中的相关日志信息。
## 接口演示
在启动Web服务后,在浏览器打开网址<http://127.0.0.1:8000/docs>,即可看到如下图所示的接口文档网页:

这里包含了目前WebTrader支持的相关接口信息,下面结合vnpy_webtrader项目下提供的[Jupyter Notebook](https://github.com/vnpy/vnpy_webtrader/blob/main/script/test.ipynb)进行相关的接口演示。
### 获得令牌(token)
```python3
import requests
import json
url = "http://127.0.0.1:8000/"
username = "vnpy"
password = "vnpy"
r = requests.post(
url + "token",
data={"username": username, "password": password},
headers={"accept": "application/json"}
)
token = r.json()["access_token"]
```
首先导入相应的模块requests和json,接着定义url和用户名和密码,通过requests的post方法传入相应参数就能够获得令牌(token),后续访问使用各种接口直接传入token即可。
### 行情订阅
```
r = requests.post(url + "tick/" + "cu2112.SHFE", headers={"Authorization":"Bearer " + token})
```
通过上述命令可实现对合约cu2112.SHFE的订阅,同时可以在图形界面收到该合约的行情数据推送,入下图所示:

### 批量查询
```python3
# 查询函数
def query_test(name):
"""查询对应类型的数据"""
r = requests.get(
url + name,
headers={"Authorization": "Bearer " + token}
)
return r.json()
# 批量查询
for name in ["tick", "contract", "account", "position", "order", "trade"]:
data = query_test(name)
print(name + "-" * 20)
if data:
print(data[0])
```
如有需要,同样可以通过发出主动请求查询相关的数据,比如tick数据、合约数据、账户数据、 持仓数据、委托数据以及成交数据。

### 委托测试
```python3
# 委托测试
req = {
"symbol": "cu2112",
"exchange": "SHFE",
"direction": "多",
"type": "限价",
"volume": 1,
"price": 71030,
"offset": "开",
"reference": "WebTrader"
}
r = requests.post(
url + "order",
json=req,
headers={"Authorization": "Bearer " + token}
)
vt_orderid = r.json()
print(vt_orderid)
```
下单后同样能在图形化界面看到委托信息,如下图所示:

### 撤单测试
```python3
# 撤单测试
r = requests.delete(
url + "order/" + vt_orderid,
headers={"Authorization": "Bearer " + token}
)
```
如果想将之前下的委托撤销,可以发送主动请求,结果同样会在图形化界面更新,如下图所示:

### Websocket测试
```python3
# Weboscket测试
from websocket import create_connection
ws = create_connection("ws://127.0.0.1:8000/ws/?token=" + token)
while True:
result = ws.recv()
print("Received '%s'" % result)
ws.close()
```
通过Websocket可以被动接收策略交易进程推送过来的行情数据和委托数据等,如下图所示:

## 后续计划
WebTrader仅实现了Web应用的后端(提供了浏览器访问数据的接口),而前端页面(也就是浏览器中看到的网页)则按照之前的计划交给社区用户来实现,欢迎大家贡献代码。
同时WebTrader目前只支持基础的手动交易功能,后续将会逐渐加上策略交易应用相关的管理功能(比如CtaStrategy的相关调用)。
================================================
FILE: docs/community/index.rst
================================================
社区版
~~~~~~~~~
.. toctree::
:maxdepth: 2
info/index
install/index
app/index
================================================
FILE: docs/community/info/contribution.md
================================================
# 贡献代码
---
## 创建PR
我们欢迎任何人贡献代码到VeighNa。
如果希望贡献代码请使用Github的PR(Pull Request)的流程。
PR流程大致如下:
---
1. [创建 Issue][CreateIssue] - 对于较大的改动(如新功能,大型重构等)建议先开issue讨论一下, 较小的improvement(如文档改进,bugfix等)直接发PR即可
2. Fork [VeighNa][#GithubVnpy] - 点击右上角**Fork**按钮
3. Clone你自己的fork: ```git clone https://github.com/$userid/vnpy.git```
> 如果你的fork已经过时,需要手动[sync][GithubDocForSync]
4. 从**dev**创建你自己的branch: ```git checkout -b $my_feature_branch dev```
5. 在$my_feature_branch上修改并将修改push到你Fork之后的仓库上
6. 创建从你的fork的$my_feature_branch分支到主项目的**dev**分支的[Pull Request]:
[点开这里][CreatePR] ,再点击**compare across forks**,选择需要的fork和branch创建PR
---
创建完PR之后请耐心等待:我们一旦有空就会检查PR,一旦你的代码有用且[符合要求](#代码风格),就会被合并!
---
## 代码风格
在为VeighNa写代码的时候,需要遵循一些基本的规则,否则你的代码可能无法被merge。
这些规则包括:
- [贡献代码](#贡献代码)
- [创建PR](#创建pr)
- [代码风格](#代码风格)
- [命名规则](#命名规则)
- [代码格式](#代码格式)
- [代码质量检查](#代码质量检查)
### 命名规则
我们的代码的命名规则如下:
* 类属性、类方法、参数和变量使用小写加下划线的形式
* 类名使用驼峰式命名
* 常量使用大写加下划线的形式
例如:
```python3
DEFAULT_PATH = "/tmp/VeighNa/"
class ClassA:
def __init__(self, arg_one: int, arg_two: str):
if arg_two is None:
arg_two = DEFAULT_PATH
self.property_one = arg_one
variable_one = "some string"
```
### 代码格式
我们对代码格式没有特别严格的要求,但是至少要符合pep8标准,并且额外要在类和函数下面带上docstring(就是一段"""""")。
要让代码符合pep8标准,写完代码之后使用[autopep8](https://github.com/hhatto/autopep8)格式化你的代码就可以了:
```bash
autopep8 --in-place --recursive .
```
### 代码质量检查
VeighNa项目使用两个工具来保证代码质量:
1. [ruff](https://github.com/astral-sh/ruff) - 用于代码风格和质量检查
- 在项目根目录下运行```ruff check .```检查代码中的风格问题
- 可以使用```ruff check --fix .```自动修复部分问题
2. [mypy](https://github.com/python/mypy) - 用于静态类型检查
- 在项目根目录下运行```mypy vnpy```检查代码中的类型注解问题
如果检查出error或warning,说明你的代码需要进行修改以符合项目标准。确保在提交PR前解决所有警告和错误。
[GithubVnpy]:https://github.com/vnpy/vnpy
[GithubDocForSync]:https://help.github.com/articles/syncing-a-fork/
[CreateIssue]:https://github.com/vnpy/vnpy/issues/new
[CreatePR]:https://github.com/vnpy/vnpy/compare?expand=1
================================================
FILE: docs/community/info/database.md
================================================
# 数据库
VeighNa Trader目前支持以下八种数据库:
## SQL类数据库简介
### SQLite(默认)
SQLite是一个轻量的嵌入式数据库,无需安装和配置数据服务程序,是VeighNa的**默认数据库**。适合入门新手用户,其特点如下:
- 存储在一个单一的跨平台的磁盘文件上;
- 不需要在系统中配置、安装和管理;
- 不需要一个单独的服务器进程。
#### SQLite配置字段
SQLite在VeighNa Trader中配置时,需填写以下字段信息:
| 字段名 | 值 | 是否必填 |
|--------- |---- | --- |
|database.name | sqlite | 可选(不填默认使用sqlite)
|database.database | 数据库文件(相对于trader目录) | 必填 |
SQLite配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | sqlite |
|database.database | database.db |
### MySQL
MySQL是目前主流的开源关系型数据库,其特点如下:
- 文档材料丰富,社区及用户活跃;
- 支持多种操作系统,多种开发语言;
- 可替换其他高性能NewSQL数据库兼容实现(如TiDB)。
#### MySQL配置字段
MySQL在VeighNa Trader中配置时,需要填写以下字段信息:
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "mysql"| 必填 |
|database.host | 地址 | 必填 |
|database.port | 端口 | 必填 |
|database.database | 数据库名 | 必填 |
|database.user | 用户名 | 可选 |
|database.password | 密码 | 可选 |
MySQL配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | mysql |
|database.host | localhost |
|database.port | 3306 |
|database.database | vnpy |
|database.user | root |
|database.password | |
### PostgreSQL
PostgreSQL是特性更为丰富的开源关系型数据库,只推荐熟手使用。相比于MySQL,其特点如下:
- 采用多进程结构;
- 支持通过扩展插件来新增功能。
#### PostgreSQL配置字段
PostgreSQL在VeighNa Trader中配置时,需要填写以下字段信息:
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "postgresql" | 必填 |
|database.host | 地址 | 必填 |
|database.port | 端口 | 必填 |
|database.database | 数据库名 | 必填 |
|database.user | 用户名 | 必填 |
|database.password | 密码 | 必填 |
PostgreSQL配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | postgresql |
|database.host | localhost |
|database.port | 5432 |
|database.database | vnpy |
|database.user | postgres |
|database.password | 123456 |
请注意,VeighNa不会主动为关系型数据库创建数据库,所以请确保所填写的database.database字段对应的数据库已经创建好了。若未创建数据库,请手动连接数据库并运行该命令:
```sql
create database <填写的database.database>;
```
## 非SQL类数据库简介
### MongoDB
MongoDB是一个基于分布式文件储存(bson格式)的非关系型数据库,其特点如下:
- 面向文档存储,操作比较简单;
- 支持丰富的存储类型和数据操作;
- 内置的热数据内存缓存实现更快的读写速度。
#### MongoDB配置字段
MongoDB在VeighNa Trader中配置时,需要填写以下字段信息:
| 字段名 | 值 | 是否必填|
|--------- |---- | ---|
|database.name | "mongodb" | 必填 |
|database.host | 地址| 必填 |
|database.port | 端口| 必填 |
|database.database | 数据库名| 必填 |
|database.user | 用户名| 可选 |
|database.password | 密码| 可选 |
|database.authentication_source | [创建用户所用的数据库][AuthSource]| 可选 |
MongoDB的带认证配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | mongodb |
|database.host | localhost |
|database.port | 27017 |
|database.database | vnpy |
|database.user | root |
|database.password | |
|database.authentication_source | vnpy |
[AuthSource]: https://docs.mongodb.com/manual/core/security-users/#user-authentication-database
### InfluxDB
InfluxDB是专门针对时间序列数据存储设计的非关系型数据库,其特点如下:
- 列式数据存储提供极高的读写效率;
- 采用独立服务进程的模式运行,也能支持多进程的并发访问需求。
在安装时需要选择2.0版本的InfluxDB。
请注意,运行influxd.exe的cmd需要保持运行,如果关闭则会导致InfluxDB退出,或者也可以使用一些辅助工具将其注册为后台运行的Windows服务。
#### InfluxDB配置字段
InfluxDB在VeighNa Trader中配置时,需要填写以下字段信息:
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "influxdb" | 必填 |
|database.host | 地址| 必填 |
|database.port | 端口| 必填 |
|database.database | 数据库名| 必填 |
|database.user | 用户名| 必填 |
|database.password | 密码| 必填 |
InfluxDB配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | influxdb |
|database.host | localhost |
|database.port | 8086 |
|database.database | vnpy |
|database.user | root |
|database.password | 12345678 |
### DolphinDB
DolphinDB是浙江智臾科技有限公司研发的一款高性能分布式时序数据库,特别适用于对速度要求极高的低延时或实时性任务,其特点如下:
- 列式分析型(OLAP)数据库,采用混合引擎(基于内存和硬盘),充分利用缓存来加速;
- 原生分区表存储,合理的分区方案可以让CPU多线程并行加载每个分区内的数据;
- 支持高效的数据压缩,显著减小硬盘存储空间的同时,还能大幅降低IO通讯的开销。
尽管DolphinDB是商业软件,但是也提供了免费的社区版,在安装时需要选择[2.0 Beta](https://github.com/dolphindb/release/blob/master/2.00/README.md)版本。
请注意:
- 运行dolphindb.exe的cmd需要保持运行,如果关闭则会导致DolphinDB退出,或者也可以使用一些辅助工具将其注册为后台运行的Windows服务;
- 因为DolphinDB目前不支持Python3.10,所以VeighNa Studio 3.0.0没有提供DolphinDB支持。
#### DolphinDB配置字段
需要填写以下字段:
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "dolphindb"| 必填 |
|database.host | 地址 | 必填 |
|database.port | 端口 | 必填 |
|database.database | 数据库名 | 必填 |
|database.user | 用户名 | 必填 |
|database.password | 密码 | 必填 |
DolphinDB配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | dolphindb |
|database.host | localhost |
|database.port | 8848 |
|database.database | vnpy |
|database.user | admin |
|database.password | 123456|
### Arctic
Arctic是由英国量化对冲基金Man AHL基于MongoDB开发的高性能金融时序数据库,其特点如下:
- 支持直接存储pandas的DataFrame和numpy的ndaaray对象;
- 允许对数据进行版本化管理(类似于数据库中的git),便于因子挖掘过程中的数据迭代管理;
- 基于分块化存储和LZ4压缩,在网络和磁盘IO方面节省大量资源,实现超高性能的数据查询。
请注意,因为Arctic目前不支持Python3.10,所以VeighNa Studio 3.0.0没有提供Arctic支持。
#### Artic配置字段
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "arctic"| 必填 |
|database.host | 地址 | 必填 |
|database.port | 端口 | 必填 |
Arctic配置示例如下所示:
| 字段名 | 值 |
|--------- |---- |
|database.name | arctic |
|database.host | localhost |
|database.database | vnpy |
### Level DB
LevelDB是由Google推出的高性能Key/Value数据库,其特点如下:
- 定位为通用型数据存储方案;
- 基于LSM算法实现进程内存储引擎;
- 支持数十亿级别的海量数据。
请注意,因为LevelDB目前不支持Python3.10,所以VeighNa Studio 3.0.0没有提供LevelDB支持。
#### LevelDB配置字段
| 字段名 | 值 | 是否必填 |
|--------- |---- | ---- |
|database.name | "leveldb"| 必填 |
|database.database | 数据库名 | 必填 |
|database.port | 端口 | 必填 |
LevelDB配置示例如下所示:
| 字段名 | 值 |
|--------- | ---- |
|database.name | leveldb |
|database.database | vnpy_data |
## 数据库配置(以MySQL为例)
本文档以MySQL为例,介绍数据库的配置过程。
首先在[MySQL官网](https://dev.mysql.com/downloads/)下载Windows版本安装包【MySQL Installer for Windows】,如下图所示:



下载完成后得到msi格式的安装包,双击打开后选择【Full】模式安装MySQL,一路点击【Next】按钮即可完成安装。

安装过程中将会自动从网站下载相关组件,先点击【Execute】按钮来补全,再点击【Next】按钮。


安装过程中将会要求输入3次密码,这里为了方便演示,我们将密码设置为1001,请在自己安装的过程中使用更加复杂安全的密码。
安装完毕后会自动打开MySQL的图形管理工具MySQL WorkBench,点击菜单栏【Database】->【Connect to Database】,如下图所示:

在弹出的对话框中,直接选择默认数据库Local Instance MySQL,然后点击【OK】按钮连接MySQL数据库服务器。

在自动打开的数据库管理界面中,点击下图中菜单栏红色方框的按钮,来创建新的数据库。在【Name】中输入“vnpy”,然后点击下方的【Apply】按钮确认。

在之后弹出的数据库脚本执行确认对话框中,同样点击【Apply】即可,这样就完成了在MySQL WorkBench的所有操作。
随后启动VeighNa Trader,点击菜单栏的【配置】,设置数据库相关字段:
- name要改成mysql(请注意大小写);
- database改成vnpy;
- host为本地IP,即localhost或者127.0.0.1;
- port为MySQL的默认端口3306;
- user用户名为root
- password密码则是之前设置的1001。
```json
database.name: mysql
database.database: vnpy
database.host: localhost
database.port: 3306
database.user: root
database.password: 1001
```
填写完毕后如下图所示:

保存完成配置修改后,重启VeighNa Trader来启用新的数据库配置。重启后,在打开VeighNa Trader的过程中若无报错提示,则说明MySQL数据库配置成功。
## 脚本使用
脚本使用前,请先按照上文配置好使用的数据库, 使用时调用相应的函数接口。
### 脚本加载
#### 在脚本中加载所需的包和数据结构
```python3
from datetime import datetime
from typing import List
from vnpy.trader.constant import Exchange, Interval
from vnpy.trader.database import get_database
from vnpy.trader.object import BarData, TickData
# 获取数据库实例
database = get_database()
```
#### 配置所需合约的具体参数数据
```python3
# 合约代码,888为米筐的连续合约,仅用于示范,具体合约代码请根据需求自行更改
symbol = "cu888"
# 交易所,目标合约的交易所
exchange = Exchange.SHFE
# 历史数据开始时间,精确到日
start = datetime(2019, 1, 1)
# 历史数据结束时间,精确到日
end = datetime(2021, 1, 20)
# 数据的时间粒度,这里示例采用日级别
interval = Interval.DAILY
```
#### 数据库的读取操作
如数据库指定时间段没有数据,返回空列表
```python3
# 读取数据库中k线数据
bar1 = database.load_bar_data(
symbol=symbol,
exchange=exchange,
interval=interval,
start=start,
end=end
)
# 读取数据库中tick数据
tick1 = database.load_tick_data(
symbol=symbol,
exchange=exchange,
start=start,
end=end
)
```
#### 数据库的写入操作
请注意,示例中的**bar_data**和**tick_data**均未在示例中展现获取和转换方法。如需以脚本方式写入,请自行参考源码或其他途径,转换成示例中的数据结构。
```python3
# 需要存入的k线数据,请自行获取并转换成所需的形式
bar_data: List[BarData] = None
database.save_bar_data(bar_data)
# 需要存入的k线数据,请自行获取并转换成所需的形式
tick_data: List[TickData] = None
# 将tick数据存入数据库
database.save_tick_data(tick_data)
```
#### 数据库删除操作
无法恢复,请谨慎操作
```python3
# 删除数据库中k线数据
database.delete_bar_data(
symbol=symbol,
exchange=exchange,
interval=interval
)
# 删除数据库中tick数据
database.delete_tick_data(
symbol=symbol,
exchange=exchange
)
```
================================================
FILE: docs/community/info/datafeed.md
================================================
# 数据服务
对于数据服务,VeighNa提供了标准化的接口BaseDatafeed(位于vnpy.trader.datafeed中),实现了更加灵活的数据服务支持。在全局配置中,和数据服务相关的字段都以datafeed作为前缀。
具体字段含义如下:
- datafeed.name:数据服务接口的名称,必须为全称的小写英文字母;
- datafeed.username:数据服务的用户名;
- datafeed.password:数据服务的密码。
以上字段对于所有数据服务都是必填的,如果是token方式授权请填写在datafeed.password字段中。目前VeighNa Trader支持以下七种数据服务,**具体每个数据服务的细节可在对应的项目地址中找到**。
## 迅投研
迅投研是由睿智融科公司推出的专业数据服务,对于大部分个人投资者来说应该都是性价比比较高的选择:
- 项目地址:[vnpy_xt](https://github.com/vnpy/vnpy_xt)
- 数据分类:股票、期货、期权、基金、合约信息、财务信息
- 数据周期:日线、小时线、分钟线、TICK(实时更新)
- 注册申请:[迅投研](https://xuntou.net/#/signup?utm_source=vnpy)
## RQData
米筐RQData是由米筐科技公司推出的云端数据服务,提供了广泛的国内金融市场品种数据支持:
- 项目地址:[vnpy_rqdata](https://github.com/vnpy/vnpy_rqdata)
- 数据分类:股票、期货、期权、基金和黄金TD
- 数据周期:日线、小时线、分钟线、TICK(实时更新)
- 注册申请:[RICEQUANT](https://www.ricequant.com/welcome/purchase?utm_source=vnpy)
**请注意,配置信息里的username和password不是米筐官网登录用的账号和密码。**
## UData
恒有数UData是由恒生电子推出的云端数据服务,提供不限次、不限量的多种金融数据获取:
- 项目地址:[vnpy_udata](https://github.com/vnpy/vnpy_udata)
- 数据分类:股票、期货
- 数据周期:分钟线(盘后更新)
- 注册申请:[恒有数UData](https://udata.hs.net/home)
## TuShare
TuShare是国内知名的开源Python金融数据接口项目,由大神Jimmy团队长期开发维护,除了行情数据外还提供许多另类数据:
- 项目地址:[vnpy_tushare](https://www.github.com/vnpy/vnpy_tushare)
- 数据分类:股票、期货
- 数据周期:日线、分钟线(盘后更新)
- 注册申请:[Tushare大数据社区](https://tushare.pro/)
## TQSDK
天勤TQSDK是由信易科技推出的Python程序化交易解决方案,提供当前可交易合约上市以来的历史数据获取:
- 项目地址:[vnpy_tqsdk](https://github.com/vnpy/vnpy_tqsdk)
- 数据分类:期货
- 数据周期:分钟线(实时更新)
- 注册申请:[天勤量化-信易科技(shinnytech.com)](https://www.shinnytech.com/tianqin)
## Wind
万得Wind对于在国内金融机构工作的从业者来说,已经是工作中的标准配置,不管是股票、债券还是商品市场的数据,Wind可以说是应有尽有:
- 项目地址:[vnpy_wind](https://github.com/vnpy/vnpy_wind)
- 数据分类:期货
- 数据周期:分钟线(实时更新)
- 注册申请:[Wind金融终端](https://www.wind.com.cn/newsite/wft.html)
## iFinD
同花顺iFinD是同花顺公司推出的面向专业机构用户的金融数据终端,且在过去几年中的市场占有率快速上升:
- 项目地址:[vnpy_ifind](https://github.com/vnpy/vnpy_ifind)
- 数据分类:期货
- 数据周期:分钟线(实时更新)
- 注册申请:[iFinD金融数据终端](http://www.51ifind.com/)
## Tinysoft
作为国内老牌金融数据公司的天软,其核心产品【天软.NET金融分析平台】(简称TinySoft),在券商研究所和自营领域积累了大量用户。翻看券商的金融工程研报时,经常会发现图表的备注信息中写有“以上数据来自天软”的数据来源说明:
- 项目地址:[vnpy_tinysoft](https://github.com/vnpy/vnpy_tinysoft)
- 数据分类:期货
- 数据周期:分钟线(实时更新)
- 注册申请:[天软.NET金融分析平台](http://www.tinysoft.com.cn/TSDN/HomePage.tsl)
请注意,因为Tinysoft目前不支持Python3.10,所以VeighNa Studio 3.0.0没有提供Tinysoft支持。
## 脚本使用
脚本使用前,请先按照上文配置好使用的数据服务, 使用时调用相应的函数接口(具体接口支持请参考上文中支持的数据周期)。
### 脚本加载
#### 在脚本中加载所需的包和数据结构
```python3
from datetime import datetime
from vnpy.trader.constant import Exchange, Interval
from vnpy.trader.datafeed import get_datafeed
from vnpy.trader.object import HistoryRequest
# 获取数据服务实例
datafeed = get_datafeed()
```
#### 获取k线级别的历史数据
```python3
req = HistoryRequest(
# 合约代码(示例cu888为米筐连续合约代码,仅用于示范,具体合约代码请根据需求查询数据服务提供商)
symbol="cu888",
# 合约所在交易所
exchange=Exchange.SHFE,
# 历史数据开始时间
start=datetime(2019, 1, 1),
# 历史数据结束时间
end=datetime(2021, 1, 20),
# 数据时间粒度,默认可选分钟级、小时级和日级,具体选择需要结合该数据服务的权限和需求自行选择
interval=Interval.DAILY
)
# 获取k线历史数据
data = datafeed.query_bar_history(req)
```
#### 获取tick级别的历史数据
由于tick数据量较大,下载前请先参考上文确认数据服务是否提供tick数据的下载服务
```python3
req = HistoryRequest(
# 合约代码(示例cu888为米筐连续合约代码,仅用于示范,具体合约代码请根据需求查询数据服务提供商)
symbol="cu888",
# 合约所在交易所
exchange=Exchange.SHFE,
# 历史数据开始时间
start=datetime(2019, 1, 1),
# 历史数据结束时间
end=datetime(2021, 1, 20),
# 数据时间粒度,为tick级别
interval=Interval.TICK
)
# 获取tick历史数据
data = datafeed.query_tick_history(req)
```
================================================
FILE: docs/community/info/gateway.md
================================================
# 交易接口
## 加载启动
### VeighNa Station加载
启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【交易接口】栏勾选想要交易的接口。
### 脚本加载
以CTP接口为例,在启动脚本中添加如下代码:
```python3
# 写在顶部
from vnpy_ctp import CtpGateway
# 写在创建main_engine对象后
main_engine.add_gateway(CtpGateway)
```
## 连接接口
在图形化操作界面VeighNa Trader上的菜单栏中点击【系统】->【连接CTP】,会弹出账号配置窗口,如下图所示:

输入账号、密码等相关信息即可连接接口,并立刻进行查询工作: 如查询账号信息、查询持仓、查询委托信息、查询成交信息等。查询成功后可在主界面的组件中看到输出的日志,如下图所示:

### 修改json配置文件
接口配置相关信息保存在json文件中,放置在用户目录下的.vntrader文件夹内,如下图所示:

如果需要修改接口配置文件,用户既可以在图形化界面VeighNa Trader内修改,也可以直接在.vntrader文件夹下修改对应的json文件。
另外将json配置文件分离于vnpy的好处在于:避免每次升级都要重新配置json文件。
### 查看可交易的合约
先登录接口,然后在菜单栏中点击【帮助】->【查询合约】即可弹出空白的【查询合约】窗口,点击【查询】按钮后才会显示查询结果。留空则查询全部合约,如下图所示:

## 接口分类
| 接口 | 类型 |
| ---------------------| :--------------------------------------------: |
| CTP | 期货、期货期权(实盘6.5.1) |
| CTP测试 | 期货、期货期权(测试6.5.1) |
| CTP Mini | 期货、期货期权(实盘1.4) |
| 飞马 | 期货 |
| CTP期权 | ETF期权(实盘20190802) |
| 顶点飞创 | ETF期权 |
| 顶点HTS | ETF期权 |
| 恒生UFT | 期货、ETF期权 |
| 易盛 | 期货、黄金TD |
| 中泰XTP | A股、两融、ETF期权 |
| 国泰君安统一交易网关 | A股 |
| 华鑫奇点股票 | A股 |
| 华鑫奇点期权 | ETF期权 |
| 中亿汇达Comstar | 银行间市场 |
| 东方证券OST | A股 |
| 盈透证券 | 海外多品种 |
| 易盛9.0外盘 | 外盘期货 |
| 直达期货 | 外盘期货 |
| 融航 | 期货资管 |
| TTS | 期货 |
| 飞鼠 | 黄金TD |
| 金仕达黄金 | 黄金TD |
## 接口详解
### CTP
#### 接口支持
- 操作系统
- Windows
- Ubuntu
- 交易品种
- 期货
- 期货期权
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 用户名:
- 密码:
- 经纪商代码:
- 交易服务器:
- 行情服务器:
- 产品名称:
- 授权编码:
#### 获取账号
- 仿真账号:从SimNow网站上获取。只需输入手机号码和短信验证即可(短信验证有时只能在工作日正常工作时段收到)。SimNow的用户名(InvestorID)为6位纯数字,经纪商编号为9999,并且提供两套环境用于盘中仿真交易以及盘后的测试。需要修改一次密码之后才能使用。请注意每套仿真环境的适用时间段是不同的。
- 实盘账号:在期货公司开户,通过联系客户经理可以开通。用户名为纯数字,经纪商编号也是4位纯数字(每个期货公司的经纪商编号都不同)。另外,实盘账号也可以开通仿真交易功能,同样需要联系客户经理。
### CTPTEST(CTP测试)
#### 接口支持
- 操作系统
- Windows
- Ubuntu
- 交易品种
- 期货
- 期货期权
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 用户名:
- 密码:
- 经纪商代码:
- 交易服务器:
- 行情服务器:
- 产品名称:
- 授权编码:
#### 获取账号
在期货公司开户,通过联系客户经理向期货公司申请进行穿透式接入测试。
### MINI(CTP Mini)
#### 接口支持
- 操作系统
- Windows
- Ubuntu
- 交易品种
- 期货
- 期货期权
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 用户名:
- 密码:
- 经纪商代码:
- 交易服务器:
- 行情服务器:
- 产品名称:
- 授权编码:
#### 获取账号
在期货公司开户,通过联系客户经理可以开通。用户名为纯数字,经纪商编号也是4位纯数字(每个期货公司的经纪商编号都不同)。另外,实盘账号也可以开通仿真交易功能,同样需要联系客户经理。
### FEMAS(飞马)
#### 接口支持
- 操作系统
- Windows
- 交易品种
- 期货
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 用户名:
- 密码:
- 经纪商代码:
- 交易服务器:
- 行情服务器:
- 产品名称:
- 授权编码:
#### 获取账号
在期货公司开户,通过联系客户经理可以开通。用户名为纯数字,经纪商代码也是4位纯数字(每个期货公司的经纪商编号都不同)。另外,实盘账号也可以开通仿真交易功能,同样需要联系客户经理。
### SOPT(CTP期权)
#### 接口支持
- 操作系统
- Windows
- Ubuntu
- 交易品种
- ETF期权
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 用户名:
- 密码:
- 经纪商代码:
- 交易服务器:
- 行情服务器:
- 产品名称:
- 授权编码:
#### 获取账号
在期货公司开户,通过联系客户经理可以开通。用户名为纯数字,经纪商代码也是4位纯数字(每个期货公司的经纪商代码都不同)。另外,实盘账号也可以开通仿真交易功能,同样需要联系客户经理。
### SEC(顶点飞创)
#### 接口支持
- 操作系统
- Windows
- 交易品种
- ETF期权
- 持仓方向
- 股票只支持单向持仓
- 股票期权只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
- 账号:
- 密码:
- 行情地址:
- 交易地址:
- 行情协议:TCP、UDP
- 授权码:
- 产品号:
- 采集类型:顶点、恒生、金证、金仕达
- 行情压缩:N、Y
#### 获取账号
在期货公司开户,通过联系客户经理可以开通。
### HTS(顶点HTS)
#### 接口支持
- 操作系统
- Windows
- 交易品种
- ETF期权
- 持仓方向
- 双向持仓
- 历史数据
- 不提供
#### 相关字段
- 账号:
- 密码:
- 行情地址:
- 交易地址:
- 行情协议:TCP、UDP
- 授权码:
- 产品号:
- 采集类型:顶点、恒生、金证、金仕达
- 行情压缩:N、Y
#### 获取账号
在期货公司开户,通过联系客户经理可以开通。
### UFT(恒生UFT)
#### 接口支持
- 操作系统
- Windows
- Ubuntu
- 交易品种
- 期货
- ETF期权
- 持仓方向
- 只支持双向持仓
- 历史数据
- 不提供
#### 相关字段
gitextract_unzv_8vm/
├── .github/
│ ├── CODE_OF_CONDUCT.md
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── SUPPORT.md
│ └── workflows/
│ └── pythonapp.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_ENG.md
├── docs/
│ ├── community/
│ │ ├── app/
│ │ │ ├── algo_trading.md
│ │ │ ├── chart_wizard.md
│ │ │ ├── cta_backtester.md
│ │ │ ├── cta_strategy.md
│ │ │ ├── data_manager.md
│ │ │ ├── data_recorder.md
│ │ │ ├── excel_rtd.md
│ │ │ ├── index.rst
│ │ │ ├── option_master.md
│ │ │ ├── paper_account.md
│ │ │ ├── portfolio_manager.md
│ │ │ ├── portfolio_strategy.md
│ │ │ ├── risk_manager.md
│ │ │ ├── rpc_service.md
│ │ │ ├── script_trader.md
│ │ │ ├── spread_trading.md
│ │ │ └── web_trader.md
│ │ ├── index.rst
│ │ ├── info/
│ │ │ ├── contribution.md
│ │ │ ├── database.md
│ │ │ ├── datafeed.md
│ │ │ ├── gateway.md
│ │ │ ├── i18n.md
│ │ │ ├── index.rst
│ │ │ ├── introduction.md
│ │ │ ├── pycharm.md
│ │ │ ├── veighna_station.md
│ │ │ ├── veighna_trader.md
│ │ │ └── vscode.md
│ │ └── install/
│ │ ├── index.rst
│ │ ├── mac_install.md
│ │ ├── ubuntu_install.md
│ │ └── windows_install.md
│ ├── conf.py
│ ├── elite/
│ │ ├── extension/
│ │ │ ├── elite_algotrading.md
│ │ │ ├── elite_dingtalk.md
│ │ │ ├── elite_feishu.md
│ │ │ ├── elite_ladder.md
│ │ │ └── index.rst
│ │ ├── index.rst
│ │ ├── info/
│ │ │ ├── elite_install.md
│ │ │ ├── elite_lab.md
│ │ │ ├── elite_trader.md
│ │ │ └── index.rst
│ │ └── strategy/
│ │ ├── elite_algotrading.md
│ │ ├── elite_ctastrategy.md
│ │ ├── elite_datamanager.md
│ │ ├── elite_filter.md
│ │ ├── elite_function.md
│ │ ├── elite_optionstrategy.md
│ │ ├── elite_portfoliostrategy.md
│ │ ├── elite_riskmanager.md
│ │ ├── elite_spreadtrading.md
│ │ └── index.rst
│ └── index.rst
├── examples/
│ ├── alpha_research/
│ │ ├── download_data_rq.ipynb
│ │ ├── download_data_xt.ipynb
│ │ ├── research_workflow_alpha101.ipynb
│ │ ├── research_workflow_lasso.ipynb
│ │ ├── research_workflow_lgb.ipynb
│ │ └── research_workflow_mlp.ipynb
│ ├── candle_chart/
│ │ └── run.py
│ ├── client_server/
│ │ ├── run_client.py
│ │ └── run_server.py
│ ├── cta_backtesting/
│ │ ├── backtesting_demo.ipynb
│ │ └── portfolio_backtesting.ipynb
│ ├── data_recorder/
│ │ └── data_recorder.py
│ ├── download_bars/
│ │ └── download_bars.ipynb
│ ├── no_ui/
│ │ └── run.py
│ ├── notebook_trading/
│ │ └── demo_notebook.ipynb
│ ├── portfolio_backtesting/
│ │ └── backtesting_demo.ipynb
│ ├── simple_rpc/
│ │ ├── test_client.py
│ │ └── test_server.py
│ ├── spread_backtesting/
│ │ └── backtesting.ipynb
│ └── veighna_trader/
│ ├── demo_script.py
│ └── run.py
├── install.bat
├── install.sh
├── install_osx.sh
├── pyproject.toml
├── tests/
│ └── test_alpha101.py
└── vnpy/
├── __init__.py
├── alpha/
│ ├── __init__.py
│ ├── dataset/
│ │ ├── __init__.py
│ │ ├── cs_function.py
│ │ ├── datasets/
│ │ │ ├── __init__.py
│ │ │ ├── alpha_101.py
│ │ │ └── alpha_158.py
│ │ ├── math_function.py
│ │ ├── processor.py
│ │ ├── ta_function.py
│ │ ├── template.py
│ │ ├── ts_function.py
│ │ └── utility.py
│ ├── lab.py
│ ├── logger.py
│ ├── model/
│ │ ├── __init__.py
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ ├── lasso_model.py
│ │ │ ├── lgb_model.py
│ │ │ └── mlp_model.py
│ │ └── template.py
│ └── strategy/
│ ├── __init__.py
│ ├── backtesting.py
│ ├── strategies/
│ │ ├── __init__.py
│ │ └── equity_demo_strategy.py
│ └── template.py
├── chart/
│ ├── __init__.py
│ ├── axis.py
│ ├── base.py
│ ├── item.py
│ ├── manager.py
│ └── widget.py
├── event/
│ ├── __init__.py
│ └── engine.py
├── py.typed
├── rpc/
│ ├── __init__.py
│ ├── client.py
│ ├── common.py
│ └── server.py
└── trader/
├── __init__.py
├── app.py
├── constant.py
├── converter.py
├── database.py
├── datafeed.py
├── engine.py
├── event.py
├── gateway.py
├── locale/
│ ├── __init__.py
│ ├── build_hook.py
│ ├── en/
│ │ └── LC_MESSAGES/
│ │ └── vnpy.po
│ ├── generate_mo.bat
│ ├── generate_pot.bat
│ └── vnpy.pot
├── logger.py
├── object.py
├── optimize.py
├── setting.py
├── ui/
│ ├── __init__.py
│ ├── ico/
│ │ └── __init__.py
│ ├── mainwindow.py
│ ├── qt.py
│ └── widget.py
└── utility.py
SYMBOL INDEX (873 symbols across 49 files)
FILE: examples/candle_chart/run.py
function update_bar (line 34) | def update_bar() -> None:
FILE: examples/client_server/run_client.py
function main (line 9) | def main():
FILE: examples/client_server/run_server.py
function main_ui (line 13) | def main_ui() -> None:
function process_log_event (line 30) | def process_log_event(event: Event) -> None:
function main_terminal (line 37) | def main_terminal() -> None:
FILE: examples/data_recorder/data_recorder.py
function run_recorder (line 65) | def run_recorder() -> None:
FILE: examples/no_ui/run.py
function check_trading_period (line 41) | def check_trading_period() -> bool:
function run_child (line 56) | def run_child() -> None:
function run_parent (line 97) | def run_parent() -> None:
FILE: examples/simple_rpc/test_client.py
class TestClient (line 6) | class TestClient(RpcClient):
method __init__ (line 11) | def __init__(self) -> None:
method callback (line 17) | def callback(self, topic: str, data: Any) -> None:
FILE: examples/simple_rpc/test_server.py
class TestServer (line 6) | class TestServer(RpcServer):
method __init__ (line 11) | def __init__(self):
method add (line 19) | def add(self, a, b):
FILE: examples/veighna_trader/demo_script.py
function run (line 6) | def run(engine: ScriptEngine):
FILE: examples/veighna_trader/run.py
function main (line 39) | def main():
FILE: tests/test_alpha101.py
function create_test_df (line 9) | def create_test_df(n_symbols: int = 50, n_days: int = 300) -> pl.DataFrame:
function test_df (line 61) | def test_df() -> pl.DataFrame:
class TestAlpha101 (line 69) | class TestAlpha101:
method test_alpha1 (line 72) | def test_alpha1(self, test_df: pl.DataFrame) -> None:
method test_alpha2 (line 78) | def test_alpha2(self, test_df: pl.DataFrame) -> None:
method test_alpha3 (line 84) | def test_alpha3(self, test_df: pl.DataFrame) -> None:
method test_alpha4 (line 90) | def test_alpha4(self, test_df: pl.DataFrame) -> None:
method test_alpha5 (line 96) | def test_alpha5(self, test_df: pl.DataFrame) -> None:
method test_alpha6 (line 102) | def test_alpha6(self, test_df: pl.DataFrame) -> None:
method test_alpha7 (line 108) | def test_alpha7(self, test_df: pl.DataFrame) -> None:
method test_alpha8 (line 114) | def test_alpha8(self, test_df: pl.DataFrame) -> None:
method test_alpha9 (line 120) | def test_alpha9(self, test_df: pl.DataFrame) -> None:
method test_alpha10 (line 126) | def test_alpha10(self, test_df: pl.DataFrame) -> None:
method test_alpha11 (line 132) | def test_alpha11(self, test_df: pl.DataFrame) -> None:
method test_alpha12 (line 138) | def test_alpha12(self, test_df: pl.DataFrame) -> None:
method test_alpha13 (line 144) | def test_alpha13(self, test_df: pl.DataFrame) -> None:
method test_alpha14 (line 150) | def test_alpha14(self, test_df: pl.DataFrame) -> None:
method test_alpha15 (line 156) | def test_alpha15(self, test_df: pl.DataFrame) -> None:
method test_alpha16 (line 162) | def test_alpha16(self, test_df: pl.DataFrame) -> None:
method test_alpha17 (line 168) | def test_alpha17(self, test_df: pl.DataFrame) -> None:
method test_alpha18 (line 174) | def test_alpha18(self, test_df: pl.DataFrame) -> None:
method test_alpha19 (line 180) | def test_alpha19(self, test_df: pl.DataFrame) -> None:
method test_alpha20 (line 186) | def test_alpha20(self, test_df: pl.DataFrame) -> None:
method test_alpha21 (line 192) | def test_alpha21(self, test_df: pl.DataFrame) -> None:
method test_alpha22 (line 198) | def test_alpha22(self, test_df: pl.DataFrame) -> None:
method test_alpha23 (line 204) | def test_alpha23(self, test_df: pl.DataFrame) -> None:
method test_alpha24 (line 210) | def test_alpha24(self, test_df: pl.DataFrame) -> None:
method test_alpha25 (line 216) | def test_alpha25(self, test_df: pl.DataFrame) -> None:
method test_alpha26 (line 222) | def test_alpha26(self, test_df: pl.DataFrame) -> None:
method test_alpha27 (line 228) | def test_alpha27(self, test_df: pl.DataFrame) -> None:
method test_alpha28 (line 234) | def test_alpha28(self, test_df: pl.DataFrame) -> None:
method test_alpha29 (line 240) | def test_alpha29(self, test_df: pl.DataFrame) -> None:
method test_alpha30 (line 246) | def test_alpha30(self, test_df: pl.DataFrame) -> None:
method test_alpha31 (line 252) | def test_alpha31(self, test_df: pl.DataFrame) -> None:
method test_alpha32 (line 258) | def test_alpha32(self, test_df: pl.DataFrame) -> None:
method test_alpha33 (line 264) | def test_alpha33(self, test_df: pl.DataFrame) -> None:
method test_alpha34 (line 270) | def test_alpha34(self, test_df: pl.DataFrame) -> None:
method test_alpha35 (line 276) | def test_alpha35(self, test_df: pl.DataFrame) -> None:
method test_alpha36 (line 282) | def test_alpha36(self, test_df: pl.DataFrame) -> None:
method test_alpha37 (line 288) | def test_alpha37(self, test_df: pl.DataFrame) -> None:
method test_alpha38 (line 294) | def test_alpha38(self, test_df: pl.DataFrame) -> None:
method test_alpha39 (line 300) | def test_alpha39(self, test_df: pl.DataFrame) -> None:
method test_alpha40 (line 306) | def test_alpha40(self, test_df: pl.DataFrame) -> None:
method test_alpha41 (line 312) | def test_alpha41(self, test_df: pl.DataFrame) -> None:
method test_alpha42 (line 318) | def test_alpha42(self, test_df: pl.DataFrame) -> None:
method test_alpha43 (line 324) | def test_alpha43(self, test_df: pl.DataFrame) -> None:
method test_alpha44 (line 330) | def test_alpha44(self, test_df: pl.DataFrame) -> None:
method test_alpha45 (line 336) | def test_alpha45(self, test_df: pl.DataFrame) -> None:
method test_alpha46 (line 342) | def test_alpha46(self, test_df: pl.DataFrame) -> None:
method test_alpha47 (line 348) | def test_alpha47(self, test_df: pl.DataFrame) -> None:
method test_alpha48 (line 354) | def test_alpha48(self, test_df: pl.DataFrame) -> None:
method test_alpha49 (line 360) | def test_alpha49(self, test_df: pl.DataFrame) -> None:
method test_alpha50 (line 366) | def test_alpha50(self, test_df: pl.DataFrame) -> None:
method test_alpha51 (line 372) | def test_alpha51(self, test_df: pl.DataFrame) -> None:
method test_alpha52 (line 378) | def test_alpha52(self, test_df: pl.DataFrame) -> None:
method test_alpha53 (line 384) | def test_alpha53(self, test_df: pl.DataFrame) -> None:
method test_alpha54 (line 390) | def test_alpha54(self, test_df: pl.DataFrame) -> None:
method test_alpha55 (line 396) | def test_alpha55(self, test_df: pl.DataFrame) -> None:
method test_alpha57 (line 404) | def test_alpha57(self, test_df: pl.DataFrame) -> None:
method test_alpha58 (line 410) | def test_alpha58(self, test_df: pl.DataFrame) -> None:
method test_alpha59 (line 416) | def test_alpha59(self, test_df: pl.DataFrame) -> None:
method test_alpha60 (line 422) | def test_alpha60(self, test_df: pl.DataFrame) -> None:
method test_alpha61 (line 428) | def test_alpha61(self, test_df: pl.DataFrame) -> None:
method test_alpha62 (line 434) | def test_alpha62(self, test_df: pl.DataFrame) -> None:
method test_alpha63 (line 440) | def test_alpha63(self, test_df: pl.DataFrame) -> None:
method test_alpha64 (line 446) | def test_alpha64(self, test_df: pl.DataFrame) -> None:
method test_alpha65 (line 452) | def test_alpha65(self, test_df: pl.DataFrame) -> None:
method test_alpha66 (line 458) | def test_alpha66(self, test_df: pl.DataFrame) -> None:
method test_alpha67 (line 464) | def test_alpha67(self, test_df: pl.DataFrame) -> None:
method test_alpha68 (line 470) | def test_alpha68(self, test_df: pl.DataFrame) -> None:
method test_alpha69 (line 476) | def test_alpha69(self, test_df: pl.DataFrame) -> None:
method test_alpha70 (line 482) | def test_alpha70(self, test_df: pl.DataFrame) -> None:
method test_alpha71 (line 488) | def test_alpha71(self, test_df: pl.DataFrame) -> None:
method test_alpha72 (line 494) | def test_alpha72(self, test_df: pl.DataFrame) -> None:
method test_alpha73 (line 500) | def test_alpha73(self, test_df: pl.DataFrame) -> None:
method test_alpha74 (line 506) | def test_alpha74(self, test_df: pl.DataFrame) -> None:
method test_alpha75 (line 512) | def test_alpha75(self, test_df: pl.DataFrame) -> None:
method test_alpha76 (line 518) | def test_alpha76(self, test_df: pl.DataFrame) -> None:
method test_alpha77 (line 524) | def test_alpha77(self, test_df: pl.DataFrame) -> None:
method test_alpha78 (line 530) | def test_alpha78(self, test_df: pl.DataFrame) -> None:
method test_alpha79 (line 536) | def test_alpha79(self, test_df: pl.DataFrame) -> None:
method test_alpha80 (line 542) | def test_alpha80(self, test_df: pl.DataFrame) -> None:
method test_alpha81 (line 548) | def test_alpha81(self, test_df: pl.DataFrame) -> None:
method test_alpha82 (line 554) | def test_alpha82(self, test_df: pl.DataFrame) -> None:
method test_alpha83 (line 560) | def test_alpha83(self, test_df: pl.DataFrame) -> None:
method test_alpha84 (line 566) | def test_alpha84(self, test_df: pl.DataFrame) -> None:
method test_alpha85 (line 572) | def test_alpha85(self, test_df: pl.DataFrame) -> None:
method test_alpha86 (line 578) | def test_alpha86(self, test_df: pl.DataFrame) -> None:
method test_alpha87 (line 584) | def test_alpha87(self, test_df: pl.DataFrame) -> None:
method test_alpha88 (line 590) | def test_alpha88(self, test_df: pl.DataFrame) -> None:
method test_alpha89 (line 596) | def test_alpha89(self, test_df: pl.DataFrame) -> None:
method test_alpha90 (line 602) | def test_alpha90(self, test_df: pl.DataFrame) -> None:
method test_alpha91 (line 608) | def test_alpha91(self, test_df: pl.DataFrame) -> None:
method test_alpha92 (line 614) | def test_alpha92(self, test_df: pl.DataFrame) -> None:
method test_alpha93 (line 620) | def test_alpha93(self, test_df: pl.DataFrame) -> None:
method test_alpha94 (line 626) | def test_alpha94(self, test_df: pl.DataFrame) -> None:
method test_alpha95 (line 632) | def test_alpha95(self, test_df: pl.DataFrame) -> None:
method test_alpha96 (line 638) | def test_alpha96(self, test_df: pl.DataFrame) -> None:
method test_alpha97 (line 644) | def test_alpha97(self, test_df: pl.DataFrame) -> None:
method test_alpha98 (line 650) | def test_alpha98(self, test_df: pl.DataFrame) -> None:
method test_alpha99 (line 656) | def test_alpha99(self, test_df: pl.DataFrame) -> None:
method test_alpha100 (line 662) | def test_alpha100(self, test_df: pl.DataFrame) -> None:
method test_alpha101 (line 668) | def test_alpha101(self, test_df: pl.DataFrame) -> None:
FILE: vnpy/alpha/dataset/cs_function.py
function cs_rank (line 10) | def cs_rank(feature: DataProxy) -> DataProxy:
function cs_mean (line 20) | def cs_mean(feature: DataProxy) -> DataProxy:
function cs_std (line 30) | def cs_std(feature: DataProxy) -> DataProxy:
function cs_sum (line 40) | def cs_sum(feature: DataProxy) -> DataProxy:
function cs_scale (line 50) | def cs_scale(feature: DataProxy) -> DataProxy:
FILE: vnpy/alpha/dataset/datasets/alpha_101.py
class Alpha101 (line 6) | class Alpha101(AlphaDataset):
method __init__ (line 9) | def __init__(
FILE: vnpy/alpha/dataset/datasets/alpha_158.py
class Alpha158 (line 6) | class Alpha158(AlphaDataset):
method __init__ (line 9) | def __init__(
FILE: vnpy/alpha/dataset/math_function.py
function less (line 10) | def less(feature1: DataProxy, feature2: DataProxy | float) -> DataProxy:
function greater (line 26) | def greater(feature1: DataProxy, feature2: DataProxy | float) -> DataProxy:
function log (line 43) | def log(feature: DataProxy) -> DataProxy:
function abs (line 53) | def abs(feature: DataProxy) -> DataProxy:
function sign (line 63) | def sign(feature: DataProxy) -> DataProxy:
function quesval (line 73) | def quesval(threshold: float, feature1: DataProxy, feature2: DataProxy |...
function quesval2 (line 97) | def quesval2(threshold: DataProxy, feature1: DataProxy, feature2: DataPr...
function pow1 (line 121) | def pow1(base: DataProxy, exponent: float) -> DataProxy:
function pow2 (line 135) | def pow2(base: DataProxy, exponent: DataProxy) -> DataProxy:
FILE: vnpy/alpha/dataset/processor.py
function process_drop_na (line 9) | def process_drop_na(df: pl.DataFrame, names: list[str] | None = None) ->...
function process_fill_na (line 22) | def process_fill_na(df: pl.DataFrame, fill_value: float, fill_label: boo...
function process_cs_norm (line 34) | def process_cs_norm(
function process_robust_zscore_norm (line 77) | def process_robust_zscore_norm(
function process_cs_rank_norm (line 112) | def process_cs_rank_norm(df: pl.DataFrame, names: list[str]) -> pl.DataF...
FILE: vnpy/alpha/dataset/ta_function.py
function to_pd_series (line 12) | def to_pd_series(feature: DataProxy) -> pd.Series:
function to_pl_dataframe (line 18) | def to_pl_dataframe(series: pd.Series) -> pl.DataFrame:
function ta_rsi (line 23) | def ta_rsi(close: DataProxy, window: int) -> DataProxy:
function ta_atr (line 33) | def ta_atr(high: DataProxy, low: DataProxy, close: DataProxy, window: in...
FILE: vnpy/alpha/dataset/template.py
class AlphaDataset (line 23) | class AlphaDataset:
method __init__ (line 26) | def __init__(
method add_feature (line 58) | def add_feature(
method set_label (line 75) | def set_label(self, expression: str) -> None:
method add_processor (line 81) | def add_processor(self, task: str, processor: Callable[[pl.DataFrame],...
method prepare_data (line 90) | def prepare_data(self, filters: dict | None = None, max_workers: int |...
method process_data (line 159) | def process_data(self) -> None:
method fetch_raw (line 174) | def fetch_raw(self, segment: Segment) -> pl.DataFrame:
method fetch_infer (line 181) | def fetch_infer(self, segment: Segment) -> pl.DataFrame:
method fetch_learn (line 188) | def fetch_learn(self, segment: Segment) -> pl.DataFrame:
method show_feature_performance (line 195) | def show_feature_performance(self, name: str) -> None:
method show_signal_performance (line 242) | def show_signal_performance(self, signal: pl.DataFrame) -> None:
function query_by_time (line 274) | def query_by_time(df: pl.DataFrame, start: datetime | str = "", end: dat...
function calculate_feature (line 289) | def calculate_feature(args: tuple[pl.DataFrame, str, str | pl.expr.expr....
FILE: vnpy/alpha/dataset/ts_function.py
function ts_delay (line 12) | def ts_delay(feature: DataProxy, window: int) -> DataProxy:
function ts_min (line 22) | def ts_min(feature: DataProxy, window: int) -> DataProxy:
function ts_max (line 32) | def ts_max(feature: DataProxy, window: int) -> DataProxy:
function ts_argmax (line 42) | def ts_argmax(feature: DataProxy, window: int) -> DataProxy:
function ts_argmin (line 52) | def ts_argmin(feature: DataProxy, window: int) -> DataProxy:
function ts_rank (line 62) | def ts_rank(feature: DataProxy, window: int) -> DataProxy:
function ts_sum (line 72) | def ts_sum(feature: DataProxy, window: int) -> DataProxy:
function ts_mean (line 82) | def ts_mean(feature: DataProxy, window: int) -> DataProxy:
function ts_std (line 92) | def ts_std(feature: DataProxy, window: int) -> DataProxy:
function ts_slope (line 102) | def ts_slope(feature: DataProxy, window: int) -> DataProxy:
function ts_quantile (line 130) | def ts_quantile(feature: DataProxy, window: int, quantile: float) -> Dat...
function ts_rsquare (line 140) | def ts_rsquare(feature: DataProxy, window: int) -> DataProxy:
function ts_resi (line 186) | def ts_resi(feature: DataProxy, window: int) -> DataProxy:
function ts_corr (line 226) | def ts_corr(feature1: DataProxy, feature2: DataProxy, window: int) -> Da...
function ts_less (line 243) | def ts_less(feature1: DataProxy, feature2: DataProxy | float) -> DataProxy:
function ts_greater (line 259) | def ts_greater(feature1: DataProxy, feature2: DataProxy | float) -> Data...
function ts_log (line 276) | def ts_log(feature: DataProxy) -> DataProxy:
function ts_abs (line 286) | def ts_abs(feature: DataProxy) -> DataProxy:
function ts_delta (line 296) | def ts_delta(feature: DataProxy, window: int) -> DataProxy:
function ts_cov (line 301) | def ts_cov(feature1: DataProxy, feature2: DataProxy, window: int) -> Dat...
function ts_decay_linear (line 306) | def ts_decay_linear(feature: DataProxy, window: int) -> DataProxy:
function ts_product (line 321) | def ts_product(feature: DataProxy, window: int) -> DataProxy:
FILE: vnpy/alpha/dataset/utility.py
class DataProxy (line 8) | class DataProxy:
method __init__ (line 11) | def __init__(self, df: pl.DataFrame) -> None:
method result (line 18) | def result(self, s: pl.Series) -> "DataProxy":
method __add__ (line 25) | def __add__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __sub__ (line 33) | def __sub__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __mul__ (line 41) | def __mul__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __rmul__ (line 49) | def __rmul__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __truediv__ (line 57) | def __truediv__(self, other: Union["DataProxy", int, float]) -> "DataP...
method __abs__ (line 65) | def __abs__(self) -> "DataProxy":
method __gt__ (line 70) | def __gt__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __ge__ (line 78) | def __ge__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __lt__ (line 86) | def __lt__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __le__ (line 94) | def __le__(self, other: Union["DataProxy", int, float]) -> "DataProxy":
method __eq__ (line 102) | def __eq__(self, other: Union["DataProxy", int, float]) -> "DataProxy"...
function calculate_by_expression (line 111) | def calculate_by_expression(df: pl.DataFrame, expression: str) -> pl.Dat...
function calculate_by_polars (line 165) | def calculate_by_polars(df: pl.DataFrame, expression: pl.expr.expr.Expr)...
function to_datetime (line 174) | def to_datetime(arg: datetime | str) -> datetime:
class Segment (line 187) | class Segment(Enum):
FILE: vnpy/alpha/lab.py
class AlphaLab (line 20) | class AlphaLab:
method __init__ (line 23) | def __init__(self, lab_path: str) -> None:
method save_bar_data (line 51) | def save_bar_data(self, bars: list[BarData]) -> None:
method load_bar_data (line 96) | def load_bar_data(
method load_bar_df (line 156) | def load_bar_df(
method save_component_data (line 245) | def save_component_data(
method load_component_data (line 257) | def load_component_data(
method load_component_symbols (line 281) | def load_component_symbols(
method load_component_filters (line 301) | def load_component_filters(
method add_contract_setting (line 349) | def add_contract_setting(
method load_contract_setttings (line 379) | def load_contract_setttings(self) -> dict:
method save_dataset (line 389) | def save_dataset(self, name: str, dataset: AlphaDataset) -> None:
method load_dataset (line 396) | def load_dataset(self, name: str) -> AlphaDataset | None:
method remove_dataset (line 407) | def remove_dataset(self, name: str) -> bool:
method list_all_datasets (line 417) | def list_all_datasets(self) -> list[str]:
method save_model (line 421) | def save_model(self, name: str, model: AlphaModel) -> None:
method load_model (line 428) | def load_model(self, name: str) -> AlphaModel | None:
method remove_model (line 439) | def remove_model(self, name: str) -> bool:
method list_all_models (line 449) | def list_all_models(self) -> list[str]:
method save_signal (line 453) | def save_signal(self, name: str, signal: pl.DataFrame) -> None:
method load_signal (line 459) | def load_signal(self, name: str) -> pl.DataFrame | None:
method remove_signal (line 468) | def remove_signal(self, name: str) -> bool:
method list_all_signals (line 478) | def list_all_signals(self) -> list[str]:
FILE: vnpy/alpha/model/models/lasso_model.py
class LassoModel (line 13) | class LassoModel(AlphaModel):
method __init__ (line 16) | def __init__(
method fit (line 40) | def fit(self, dataset: AlphaDataset) -> None:
method predict (line 75) | def predict(self, dataset: AlphaDataset, segment: Segment) -> np.ndarray:
method detail (line 112) | def detail(self) -> None:
FILE: vnpy/alpha/model/models/lgb_model.py
class LgbModel (line 12) | class LgbModel(AlphaModel):
method __init__ (line 15) | def __init__(
method _prepare_data (line 53) | def _prepare_data(self, dataset: AlphaDataset) -> list[lgb.Dataset]:
method fit (line 84) | def fit(self, dataset: AlphaDataset) -> None:
method predict (line 113) | def predict(self, dataset: AlphaDataset, segment: Segment) -> np.ndarray:
method detail (line 149) | def detail(self) -> None:
FILE: vnpy/alpha/model/models/mlp_model.py
class MlpModel (line 22) | class MlpModel(AlphaModel):
method __init__ (line 35) | def __init__(
method fit (line 137) | def fit(
method _train_step (line 224) | def _train_step(
method _evaluate_step (line 264) | def _evaluate_step(
method _loss_fn (line 329) | def _loss_fn(self, pred: torch.Tensor, target: torch.Tensor) -> torch....
method _predict_batch (line 349) | def _predict_batch(self, data: torch.Tensor, return_cpu: bool = True) ...
method predict (line 384) | def predict(self, dataset: AlphaDataset, segment: Segment) -> np.ndarray:
method _check_tensor_nan (line 410) | def _check_tensor_nan(self, tensor: torch.Tensor, name: str) -> None:
method detail (line 428) | def detail(self) -> pd.DataFrame | None:
method _calculate_feature_importance (line 458) | def _calculate_feature_importance(self) -> pd.DataFrame:
class AverageMeter (line 493) | class AverageMeter:
method __init__ (line 509) | def __init__(self) -> None:
method reset (line 519) | def reset(self) -> None:
method update (line 532) | def update(self, val: float, n: int = 1) -> None:
class MlpNetwork (line 553) | class MlpNetwork(nn.Module):
method __init__ (line 566) | def __init__(
method _get_activation (line 620) | def _get_activation(self, name: str) -> nn.Module:
method _initialize_weights (line 646) | def _initialize_weights(self) -> None:
method forward (line 666) | def forward(self, x: torch.Tensor) -> torch.Tensor:
FILE: vnpy/alpha/model/template.py
class AlphaModel (line 9) | class AlphaModel(metaclass=ABCMeta):
method fit (line 13) | def fit(self, dataset: AlphaDataset) -> None:
method predict (line 20) | def predict(self, dataset: AlphaDataset, segment: Segment) -> np.ndarray:
method detail (line 26) | def detail(self) -> Any:
FILE: vnpy/alpha/strategy/backtesting.py
class BacktestingEngine (line 22) | class BacktestingEngine:
method __init__ (line 27) | def __init__(self, lab: AlphaLab) -> None:
method set_parameters (line 70) | def set_parameters(
method add_strategy (line 104) | def add_strategy(self, strategy_class: type, setting: dict, signal_df:...
method load_data (line 112) | def load_data(self) -> None:
method run_backtesting (line 150) | def run_backtesting(self) -> None:
method calculate_result (line 170) | def calculate_result(self) -> pl.DataFrame | None:
method calculate_statistics (line 228) | def calculate_statistics(self) -> dict:
method show_chart (line 404) | def show_chart(self) -> None:
method show_performance (line 440) | def show_performance(self, benchmark_symbol: str) -> None:
method update_daily_close (line 561) | def update_daily_close(self, bars: dict[str, BarData], dt: datetime) -...
method new_bars (line 579) | def new_bars(self, dt: datetime) -> None:
method cross_order (line 619) | def cross_order(self) -> None:
method get_signal (line 709) | def get_signal(self) -> pl.DataFrame:
method send_order (line 723) | def send_order(
method cancel_order (line 756) | def cancel_order(self, strategy: AlphaStrategy, vt_orderid: str) -> None:
method write_log (line 765) | def write_log(self, msg: str, strategy: AlphaStrategy | None = None) -...
method get_all_trades (line 770) | def get_all_trades(self) -> list[TradeData]:
method get_all_orders (line 774) | def get_all_orders(self) -> list[OrderData]:
method get_all_daily_results (line 778) | def get_all_daily_results(self) -> list["PortfolioDailyResult"]:
method get_cash_available (line 782) | def get_cash_available(self) -> float:
method get_holding_value (line 786) | def get_holding_value(self) -> float:
class ContractDailyResult (line 799) | class ContractDailyResult:
method __init__ (line 802) | def __init__(self, result_date: date, close_price: float) -> None:
method add_trade (line 822) | def add_trade(self, trade: TradeData) -> None:
method calculate_pnl (line 826) | def calculate_pnl(
method update_close_price (line 870) | def update_close_price(self, close_price: float) -> None:
class PortfolioDailyResult (line 875) | class PortfolioDailyResult:
method __init__ (line 878) | def __init__(self, result_date: date, close_prices: dict[str, float]) ...
method add_trade (line 899) | def add_trade(self, trade: TradeData) -> None:
method calculate_pnl (line 904) | def calculate_pnl(
method update_close_prices (line 935) | def update_close_prices(self, close_prices: dict[str, float]) -> None:
FILE: vnpy/alpha/strategy/strategies/equity_demo_strategy.py
class EquityDemoStrategy (line 12) | class EquityDemoStrategy(AlphaStrategy):
method on_init (line 25) | def on_init(self) -> None:
method on_trade (line 32) | def on_trade(self, trade: TradeData) -> None:
method on_bars (line 38) | def on_bars(self, bars: dict[str, BarData]) -> None:
FILE: vnpy/alpha/strategy/template.py
class AlphaStrategy (line 15) | class AlphaStrategy(metaclass=ABCMeta):
method __init__ (line 18) | def __init__(
method on_init (line 44) | def on_init(self) -> None:
method on_bars (line 49) | def on_bars(self, bars: dict[str, BarData]) -> None:
method on_trade (line 54) | def on_trade(self, trade: TradeData) -> None:
method update_trade (line 58) | def update_trade(self, trade: TradeData) -> None:
method update_order (line 67) | def update_order(self, order: OrderData) -> None:
method get_signal (line 74) | def get_signal(self) -> pl.DataFrame:
method buy (line 78) | def buy(self, vt_symbol: str, price: float, volume: float) -> list[str]:
method sell (line 82) | def sell(self, vt_symbol: str, price: float, volume: float) -> list[str]:
method short (line 86) | def short(self, vt_symbol: str, price: float, volume: float) -> list[s...
method cover (line 90) | def cover(self, vt_symbol: str, price: float, volume: float) -> list[s...
method send_order (line 94) | def send_order(
method cancel_order (line 112) | def cancel_order(self, vt_orderid: str) -> None:
method cancel_all (line 116) | def cancel_all(self) -> None:
method get_pos (line 121) | def get_pos(self, vt_symbol: str) -> float:
method get_target (line 125) | def get_target(self, vt_symbol: str) -> float:
method set_target (line 129) | def set_target(self, vt_symbol: str, target: float) -> None:
method execute_trading (line 133) | def execute_trading(self, bars: dict[str, BarData], price_add: float) ...
method write_log (line 187) | def write_log(self, msg: str) -> None:
method get_cash_available (line 191) | def get_cash_available(self) -> float:
method get_holding_value (line 195) | def get_holding_value(self) -> float:
method get_portfolio_value (line 199) | def get_portfolio_value(self) -> float:
method get_cash (line 203) | def get_cash(self) -> float:
FILE: vnpy/chart/axis.py
class DatetimeAxis (line 10) | class DatetimeAxis(pg.AxisItem):
method __init__ (line 13) | def __init__(self, manager: BarManager, *args: Any, **kwargs: Any) -> ...
method tickStrings (line 22) | def tickStrings(self, values: list[int], scale: float, spacing: int) -...
FILE: vnpy/chart/base.py
function to_int (line 19) | def to_int(value: float) -> int:
FILE: vnpy/chart/item.py
class ChartItem (line 12) | class ChartItem(pg.GraphicsObject):
method __init__ (line 15) | def __init__(self, manager: BarManager) -> None:
method _draw_bar_picture (line 45) | def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
method boundingRect (line 52) | def boundingRect(self) -> QtCore.QRectF:
method get_y_range (line 59) | def get_y_range(self, min_ix: int | None = None, max_ix: int | None = ...
method get_info_text (line 68) | def get_info_text(self, ix: int) -> str:
method update_history (line 74) | def update_history(self, history: list[BarData]) -> None:
method update_bar (line 87) | def update_bar(self, bar: BarData) -> None:
method update (line 99) | def update(self) -> None:
method paint (line 107) | def paint(
method _draw_item_picture (line 137) | def _draw_item_picture(self, min_ix: int, max_ix: int) -> None:
method clear_all (line 159) | def clear_all(self) -> None:
class CandleItem (line 168) | class CandleItem(ChartItem):
method __init__ (line 171) | def __init__(self, manager: BarManager) -> None:
method _draw_bar_picture (line 175) | def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
method boundingRect (line 215) | def boundingRect(self) -> QtCore.QRectF:
method get_y_range (line 226) | def get_y_range(self, min_ix: int | None = None, max_ix: int | None = ...
method get_info_text (line 235) | def get_info_text(self, ix: int) -> str:
class VolumeItem (line 268) | class VolumeItem(ChartItem):
method __init__ (line 271) | def __init__(self, manager: BarManager) -> None:
method _draw_bar_picture (line 275) | def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
method boundingRect (line 302) | def boundingRect(self) -> QtCore.QRectF:
method get_y_range (line 313) | def get_y_range(self, min_ix: int | None = None, max_ix: int | None = ...
method get_info_text (line 322) | def get_info_text(self, ix: int) -> str:
FILE: vnpy/chart/manager.py
class BarManager (line 9) | class BarManager:
method __init__ (line 12) | def __init__(self) -> None:
method update_history (line 21) | def update_history(self, history: list[BarData]) -> None:
method update_bar (line 42) | def update_bar(self, bar: BarData) -> None:
method get_count (line 57) | def get_count(self) -> int:
method get_index (line 63) | def get_index(self, dt: datetime) -> int | None:
method get_datetime (line 69) | def get_datetime(self, ix: float) -> datetime | None:
method get_bar (line 76) | def get_bar(self, ix: float) -> BarData | None:
method get_all_bars (line 87) | def get_all_bars(self) -> list[BarData]:
method get_price_range (line 93) | def get_price_range(self, min_ix: float | None = None, max_ix: float |...
method get_volume_range (line 124) | def get_volume_range(self, min_ix: float | None = None, max_ix: float ...
method _clear_cache (line 155) | def _clear_cache(self) -> None:
method clear_all (line 162) | def clear_all(self) -> None:
FILE: vnpy/chart/widget.py
class ChartWidget (line 20) | class ChartWidget(pg.PlotWidget):
method __init__ (line 24) | def __init__(self, parent: QtWidgets.QWidget | None = None) -> None:
method _init_ui (line 42) | def _init_ui(self) -> None:
method _get_new_x_axis (line 53) | def _get_new_x_axis(self) -> DatetimeAxis:
method add_cursor (line 56) | def add_cursor(self) -> None:
method add_plot (line 62) | def add_plot(
method add_item (line 114) | def add_item(
method get_plot (line 131) | def get_plot(self, plot_name: str) -> pg.PlotItem:
method get_all_plots (line 137) | def get_all_plots(self) -> list[pg.PlotItem]:
method clear_all (line 143) | def clear_all(self) -> None:
method update_history (line 155) | def update_history(self, history: list[BarData]) -> None:
method update_bar (line 168) | def update_bar(self, bar: BarData) -> None:
method _update_plot_limits (line 182) | def _update_plot_limits(self) -> None:
method _update_x_range (line 196) | def _update_x_range(self) -> None:
method _update_y_range (line 206) | def _update_y_range(self) -> None:
method paintEvent (line 224) | def paintEvent(self, event: QtGui.QPaintEvent) -> None:
method keyPressEvent (line 237) | def keyPressEvent(self, event: QtGui.QKeyEvent) -> None:
method wheelEvent (line 252) | def wheelEvent(self, event: QtGui.QWheelEvent) -> None:
method _on_key_left (line 263) | def _on_key_left(self) -> None:
method _on_key_right (line 276) | def _on_key_right(self) -> None:
method _on_key_down (line 289) | def _on_key_down(self) -> None:
method _on_key_up (line 301) | def _on_key_up(self) -> None:
method move_to_right (line 313) | def move_to_right(self) -> None:
class ChartCursor (line 324) | class ChartCursor(QtCore.QObject):
method __init__ (line 327) | def __init__(
method _init_ui (line 349) | def _init_ui(self) -> None:
method _init_line (line 355) | def _init_line(self) -> None:
method _init_label (line 379) | def _init_label(self) -> None:
method _init_info (line 400) | def _init_info(self) -> None:
method _connect_signal (line 417) | def _connect_signal(self) -> None:
method _mouse_moved (line 423) | def _mouse_moved(self, evt: tuple) -> None:
method _update_line (line 448) | def _update_line(self) -> None:
method _update_label (line 461) | def _update_label(self) -> None:
method update_info (line 488) | def update_info(self) -> None:
method move_right (line 511) | def move_right(self) -> None:
method move_left (line 521) | def move_left(self) -> None:
method _update_after_move (line 531) | def _update_after_move(self) -> None:
method clear_all (line 544) | def clear_all(self) -> None:
FILE: vnpy/event/engine.py
class Event (line 16) | class Event:
method __init__ (line 23) | def __init__(self, type: str, data: Any = None) -> None:
class EventEngine (line 33) | class EventEngine:
method __init__ (line 42) | def __init__(self, interval: int = 1) -> None:
method _run (line 55) | def _run(self) -> None:
method _process (line 66) | def _process(self, event: Event) -> None:
method _run_timer (line 80) | def _run_timer(self) -> None:
method start (line 89) | def start(self) -> None:
method stop (line 97) | def stop(self) -> None:
method put (line 105) | def put(self, event: Event) -> None:
method register (line 111) | def register(self, type: str, handler: HandlerType) -> None:
method unregister (line 120) | def unregister(self, type: str, handler: HandlerType) -> None:
method register_general (line 132) | def register_general(self, handler: HandlerType) -> None:
method unregister_general (line 140) | def unregister_general(self, handler: HandlerType) -> None:
FILE: vnpy/rpc/client.py
class RemoteException (line 11) | class RemoteException(Exception):
method __init__ (line 16) | def __init__(self, value: Any) -> None:
method __str__ (line 22) | def __str__(self) -> str:
class RpcClient (line 29) | class RpcClient:
method __init__ (line 32) | def __init__(self) -> None:
method __getattr__ (line 56) | def __getattr__(self, name: str) -> Any:
method start (line 88) | def start(
method stop (line 112) | def stop(self) -> None:
method join (line 122) | def join(self) -> None:
method run (line 128) | def run(self) -> None:
method callback (line 152) | def callback(self, topic: str, data: Any) -> None:
method subscribe_topic (line 158) | def subscribe_topic(self, topic: str) -> None:
method on_disconnected (line 164) | def on_disconnected(self) -> None:
FILE: vnpy/rpc/server.py
class RpcServer (line 11) | class RpcServer:
method __init__ (line 14) | def __init__(self) -> None:
method is_active (line 38) | def is_active(self) -> bool:
method start (line 42) | def start(
method stop (line 67) | def stop(self) -> None:
method join (line 77) | def join(self) -> None:
method run (line 83) | def run(self) -> None:
method publish (line 116) | def publish(self, topic: str, data: object) -> None:
method register (line 123) | def register(self, func: Callable) -> None:
method check_heartbeat (line 129) | def check_heartbeat(self) -> None:
FILE: vnpy/trader/app.py
class BaseApp (line 10) | class BaseApp(ABC):
FILE: vnpy/trader/constant.py
class Direction (line 10) | class Direction(Enum):
class Offset (line 19) | class Offset(Enum):
class Status (line 30) | class Status(Enum):
class Product (line 42) | class Product(Enum):
class OrderType (line 61) | class OrderType(Enum):
class OptionType (line 74) | class OptionType(Enum):
class Exchange (line 82) | class Exchange(Enum):
class Currency (line 142) | class Currency(Enum):
class Interval (line 152) | class Interval(Enum):
FILE: vnpy/trader/converter.py
class PositionHolding (line 17) | class PositionHolding:
method __init__ (line 20) | def __init__(self, contract: ContractData) -> None:
method update_position (line 43) | def update_position(self, position: PositionData) -> None:
method update_order (line 54) | def update_order(self, order: OrderData) -> None:
method update_order_request (line 64) | def update_order_request(self, req: OrderRequest, vt_orderid: str) -> ...
method update_trade (line 71) | def update_trade(self, trade: TradeData) -> None:
method calculate_frozen (line 112) | def calculate_frozen(self) -> None:
method sum_pos_frozen (line 156) | def sum_pos_frozen(self) -> None:
method convert_order_request_shfe (line 168) | def convert_order_request_shfe(self, req: OrderRequest) -> list[OrderR...
method convert_order_request_lock (line 202) | def convert_order_request_lock(self, req: OrderRequest) -> list[OrderR...
method convert_order_request_net (line 242) | def convert_order_request_net(self, req: OrderRequest) -> list[OrderRe...
class OffsetConverter (line 310) | class OffsetConverter:
method __init__ (line 313) | def __init__(self, oms_engine: "OmsEngine") -> None:
method update_position (line 319) | def update_position(self, position: PositionData) -> None:
method update_trade (line 328) | def update_trade(self, trade: TradeData) -> None:
method update_order (line 337) | def update_order(self, order: OrderData) -> None:
method update_order_request (line 346) | def update_order_request(self, req: OrderRequest, vt_orderid: str) -> ...
method get_position_holding (line 355) | def get_position_holding(self, vt_symbol: str) -> PositionHolding | None:
method convert_order_request (line 367) | def convert_order_request(
method is_convert_required (line 390) | def is_convert_required(self, vt_symbol: str) -> bool:
FILE: vnpy/trader/database.py
function convert_tz (line 17) | def convert_tz(dt: datetime) -> datetime:
class BarOverview (line 26) | class BarOverview:
class TickOverview (line 40) | class TickOverview:
class BaseDatabase (line 52) | class BaseDatabase(ABC):
method save_bar_data (line 58) | def save_bar_data(self, bars: list[BarData], stream: bool = False) -> ...
method save_tick_data (line 65) | def save_tick_data(self, ticks: list[TickData], stream: bool = False) ...
method load_bar_data (line 72) | def load_bar_data(
method load_tick_data (line 86) | def load_tick_data(
method delete_bar_data (line 99) | def delete_bar_data(
method delete_tick_data (line 111) | def delete_tick_data(
method get_bar_overview (line 122) | def get_bar_overview(self) -> list[BarOverview]:
method get_tick_overview (line 129) | def get_tick_overview(self) -> list[TickOverview]:
function get_database (line 139) | def get_database() -> BaseDatabase:
FILE: vnpy/trader/datafeed.py
class BaseDatafeed (line 10) | class BaseDatafeed:
method init (line 15) | def init(self, output: Callable = print) -> bool:
method query_bar_history (line 21) | def query_bar_history(self, req: HistoryRequest, output: Callable = pr...
method query_tick_history (line 28) | def query_tick_history(self, req: HistoryRequest, output: Callable = p...
function get_datafeed (line 39) | def get_datafeed() -> BaseDatafeed:
FILE: vnpy/trader/engine.py
class BaseEngine (line 51) | class BaseEngine(ABC):
method __init__ (line 57) | def __init__(
method close (line 68) | def close(self) -> None:
class MainEngine (line 73) | class MainEngine:
method __init__ (line 78) | def __init__(self, event_engine: EventEngine | None = None) -> None:
method add_engine (line 94) | def add_engine(self, engine_class: type[EngineType]) -> EngineType:
method add_gateway (line 102) | def add_gateway(self, gateway_class: type[BaseGateway], gateway_name: ...
method add_app (line 120) | def add_app(self, app_class: type[BaseApp]) -> BaseEngine:
method init_engines (line 130) | def init_engines(self) -> None:
method write_log (line 160) | def write_log(self, msg: str, source: str = "MainEngine") -> None:
method get_gateway (line 168) | def get_gateway(self, gateway_name: str) -> BaseGateway | None:
method get_engine (line 177) | def get_engine(self, engine_name: str) -> BaseEngine | None:
method get_default_setting (line 186) | def get_default_setting(self, gateway_name: str) -> dict[str, str | bo...
method get_all_gateway_names (line 195) | def get_all_gateway_names(self) -> list[str]:
method get_all_apps (line 201) | def get_all_apps(self) -> list[BaseApp]:
method get_all_exchanges (line 207) | def get_all_exchanges(self) -> list[Exchange]:
method connect (line 213) | def connect(self, setting: dict, gateway_name: str) -> None:
method subscribe (line 223) | def subscribe(self, req: SubscribeRequest, gateway_name: str) -> None:
method send_order (line 233) | def send_order(self, req: OrderRequest, gateway_name: str) -> str:
method cancel_order (line 245) | def cancel_order(self, req: CancelRequest, gateway_name: str) -> None:
method send_quote (line 255) | def send_quote(self, req: QuoteRequest, gateway_name: str) -> str:
method cancel_quote (line 267) | def cancel_quote(self, req: CancelRequest, gateway_name: str) -> None:
method query_history (line 277) | def query_history(self, req: HistoryRequest, gateway_name: str) -> lis...
method close (line 289) | def close(self) -> None:
class LogEngine (line 304) | class LogEngine(BaseEngine):
method __init__ (line 317) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method process_log_event (line 325) | def process_log_event(self, event: Event) -> None:
method register_log (line 334) | def register_log(self, event_type: str) -> None:
class OmsEngine (line 339) | class OmsEngine(BaseEngine):
method __init__ (line 344) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method register_event (line 363) | def register_event(self) -> None:
method process_tick_event (line 373) | def process_tick_event(self, event: Event) -> None:
method process_order_event (line 378) | def process_order_event(self, event: Event) -> None:
method process_trade_event (line 395) | def process_trade_event(self, event: Event) -> None:
method process_position_event (line 405) | def process_position_event(self, event: Event) -> None:
method process_account_event (line 415) | def process_account_event(self, event: Event) -> None:
method process_contract_event (line 420) | def process_contract_event(self, event: Event) -> None:
method process_quote_event (line 429) | def process_quote_event(self, event: Event) -> None:
method get_tick (line 441) | def get_tick(self, vt_symbol: str) -> TickData | None:
method get_order (line 447) | def get_order(self, vt_orderid: str) -> OrderData | None:
method get_trade (line 453) | def get_trade(self, vt_tradeid: str) -> TradeData | None:
method get_position (line 459) | def get_position(self, vt_positionid: str) -> PositionData | None:
method get_account (line 465) | def get_account(self, vt_accountid: str) -> AccountData | None:
method get_contract (line 471) | def get_contract(self, vt_symbol: str) -> ContractData | None:
method get_quote (line 477) | def get_quote(self, vt_quoteid: str) -> QuoteData | None:
method get_all_ticks (line 483) | def get_all_ticks(self) -> list[TickData]:
method get_all_orders (line 489) | def get_all_orders(self) -> list[OrderData]:
method get_all_trades (line 495) | def get_all_trades(self) -> list[TradeData]:
method get_all_positions (line 501) | def get_all_positions(self) -> list[PositionData]:
method get_all_accounts (line 507) | def get_all_accounts(self) -> list[AccountData]:
method get_all_contracts (line 513) | def get_all_contracts(self) -> list[ContractData]:
method get_all_quotes (line 519) | def get_all_quotes(self) -> list[QuoteData]:
method get_all_active_orders (line 525) | def get_all_active_orders(self) -> list[OrderData]:
method get_all_active_quotes (line 531) | def get_all_active_quotes(self) -> list[QuoteData]:
method update_order_request (line 537) | def update_order_request(self, req: OrderRequest, vt_orderid: str, gat...
method convert_order_request (line 545) | def convert_order_request(
method get_converter (line 562) | def get_converter(self, gateway_name: str) -> OffsetConverter | None:
class EmailEngine (line 569) | class EmailEngine(BaseEngine):
method __init__ (line 574) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method send_email (line 582) | def send_email(self, subject: str, content: str, receiver: str | None ...
method run (line 600) | def run(self) -> None:
method start (line 622) | def start(self) -> None:
method close (line 627) | def close(self) -> None:
FILE: vnpy/trader/gateway.py
class BaseGateway (line 33) | class BaseGateway(ABC):
method __init__ (line 81) | def __init__(self, event_engine: EventEngine, gateway_name: str) -> None:
method on_event (line 86) | def on_event(self, type: str, data: object = None) -> None:
method on_tick (line 93) | def on_tick(self, tick: TickData) -> None:
method on_trade (line 101) | def on_trade(self, trade: TradeData) -> None:
method on_order (line 109) | def on_order(self, order: OrderData) -> None:
method on_position (line 117) | def on_position(self, position: PositionData) -> None:
method on_account (line 125) | def on_account(self, account: AccountData) -> None:
method on_quote (line 133) | def on_quote(self, quote: QuoteData) -> None:
method on_log (line 141) | def on_log(self, log: LogData) -> None:
method on_contract (line 147) | def on_contract(self, contract: ContractData) -> None:
method write_log (line 153) | def write_log(self, msg: str) -> None:
method connect (line 161) | def connect(self, setting: dict) -> None:
method close (line 183) | def close(self) -> None:
method subscribe (line 190) | def subscribe(self, req: SubscribeRequest) -> None:
method send_order (line 197) | def send_order(self, req: OrderRequest) -> str:
method cancel_order (line 215) | def cancel_order(self, req: CancelRequest) -> None:
method send_quote (line 223) | def send_quote(self, req: QuoteRequest) -> str:
method cancel_quote (line 240) | def cancel_quote(self, req: CancelRequest) -> None:
method query_account (line 249) | def query_account(self) -> None:
method query_position (line 256) | def query_position(self) -> None:
method query_history (line 262) | def query_history(self, req: HistoryRequest) -> list[BarData]:
method get_default_setting (line 268) | def get_default_setting(self) -> dict[str, str | int | float | bool]:
FILE: vnpy/trader/locale/build_hook.py
class LocaleBuildHook (line 8) | class LocaleBuildHook(BuildHookInterface):
method initialize (line 11) | def initialize(self, version: str, build_data: dict) -> None:
FILE: vnpy/trader/object.py
class BaseData (line 18) | class BaseData:
class TickData (line 30) | class TickData(BaseData):
method __post_init__ (line 82) | def __post_init__(self) -> None:
class BarData (line 88) | class BarData(BaseData):
method __post_init__ (line 106) | def __post_init__(self) -> None:
class OrderData (line 112) | class OrderData(BaseData):
method __post_init__ (line 132) | def __post_init__(self) -> None:
method is_active (line 137) | def is_active(self) -> bool:
method create_cancel_request (line 143) | def create_cancel_request(self) -> "CancelRequest":
class TradeData (line 154) | class TradeData(BaseData):
method __post_init__ (line 171) | def __post_init__(self) -> None:
class PositionData (line 179) | class PositionData(BaseData):
method __post_init__ (line 194) | def __post_init__(self) -> None:
class AccountData (line 201) | class AccountData(BaseData):
method __post_init__ (line 212) | def __post_init__(self) -> None:
class LogData (line 219) | class LogData(BaseData):
method __post_init__ (line 227) | def __post_init__(self) -> None:
class ContractData (line 233) | class ContractData(BaseData):
method __post_init__ (line 259) | def __post_init__(self) -> None:
class QuoteData (line 265) | class QuoteData(BaseData):
method __post_init__ (line 285) | def __post_init__(self) -> None:
method is_active (line 290) | def is_active(self) -> bool:
method create_cancel_request (line 296) | def create_cancel_request(self) -> "CancelRequest":
class SubscribeRequest (line 307) | class SubscribeRequest:
method __post_init__ (line 315) | def __post_init__(self) -> None:
class OrderRequest (line 321) | class OrderRequest:
method __post_init__ (line 335) | def __post_init__(self) -> None:
method create_order_data (line 339) | def create_order_data(self, orderid: str, gateway_name: str) -> OrderD...
class CancelRequest (line 359) | class CancelRequest:
method __post_init__ (line 368) | def __post_init__(self) -> None:
class HistoryRequest (line 374) | class HistoryRequest:
method __post_init__ (line 385) | def __post_init__(self) -> None:
class QuoteRequest (line 391) | class QuoteRequest:
method __post_init__ (line 406) | def __post_init__(self) -> None:
method create_quote_data (line 410) | def create_quote_data(self, quoteid: str, gateway_name: str) -> QuoteD...
FILE: vnpy/trader/optimize.py
class OptimizationSetting (line 26) | class OptimizationSetting:
method __init__ (line 31) | def __init__(self) -> None:
method add_parameter (line 36) | def add_parameter(
method set_target (line 65) | def set_target(self, target_name: str) -> None:
method generate_settings (line 69) | def generate_settings(self) -> list[dict]:
function check_optimization_setting (line 83) | def check_optimization_setting(
function run_bf_optimization (line 99) | def run_bf_optimization(
function run_ga_optimization (line 132) | def run_ga_optimization(
function ga_evaluate (line 232) | def ga_evaluate(
FILE: vnpy/trader/ui/mainwindow.py
class MainWindow (line 39) | class MainWindow(QtWidgets.QMainWindow):
method __init__ (line 44) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method init_ui (line 58) | def init_ui(self) -> None:
method init_dock (line 66) | def init_dock(self) -> None:
method init_menu (line 100) | def init_menu(self) -> None:
method init_toolbar (line 184) | def init_toolbar(self) -> None:
method add_action (line 203) | def add_action(
method create_dock (line 223) | def create_dock(
method connect_gateway (line 243) | def connect_gateway(self, gateway_name: str) -> None:
method closeEvent (line 250) | def closeEvent(self, event: QtGui.QCloseEvent) -> None:
method open_widget (line 277) | def open_widget(self, widget_class: type[QtWidgets.QWidget], name: str...
method save_window_setting (line 291) | def save_window_setting(self, name: str) -> None:
method load_window_setting (line 299) | def load_window_setting(self, name: str) -> None:
method restore_window_setting (line 311) | def restore_window_setting(self) -> None:
method send_test_email (line 318) | def send_test_email(self) -> None:
method open_forum (line 324) | def open_forum(self) -> None:
method edit_global_setting (line 329) | def edit_global_setting(self) -> None:
FILE: vnpy/trader/ui/qt.py
function create_qapp (line 21) | def create_qapp(app_name: str = "VeighNa Trader") -> QtWidgets.QApplicat...
class ExceptionWidget (line 74) | class ExceptionWidget(QtWidgets.QWidget):
method __init__ (line 78) | def __init__(self, parent: QtWidgets.QWidget | None = None) -> None:
method init_ui (line 85) | def init_ui(self) -> None:
method show_exception (line 113) | def show_exception(self, msg: str) -> None:
method _copy_text (line 118) | def _copy_text(self) -> None:
method _open_community (line 123) | def _open_community(self) -> None:
FILE: vnpy/trader/ui/widget.py
class BaseCell (line 48) | class BaseCell(QtWidgets.QTableWidgetItem):
method __init__ (line 53) | def __init__(self, content: Any, data: Any) -> None:
method set_content (line 64) | def set_content(self, content: Any, data: Any) -> None:
method get_data (line 73) | def get_data(self) -> Any:
method __lt__ (line 79) | def __lt__(self, other: "BaseCell") -> bool: # type: ignore
class EnumCell (line 87) | class EnumCell(BaseCell):
method __init__ (line 92) | def __init__(self, content: Enum, data: Any) -> None:
method set_content (line 96) | def set_content(self, content: Any, data: Any) -> None:
class DirectionCell (line 104) | class DirectionCell(EnumCell):
method __init__ (line 109) | def __init__(self, content: Enum, data: Any) -> None:
method set_content (line 113) | def set_content(self, content: Any, data: Any) -> None:
class BidCell (line 125) | class BidCell(BaseCell):
method __init__ (line 130) | def __init__(self, content: Any, data: Any) -> None:
class AskCell (line 137) | class AskCell(BaseCell):
method __init__ (line 142) | def __init__(self, content: Any, data: Any) -> None:
class PnlCell (line 149) | class PnlCell(BaseCell):
method __init__ (line 154) | def __init__(self, content: Any, data: Any) -> None:
method set_content (line 158) | def set_content(self, content: Any, data: Any) -> None:
class TimeCell (line 171) | class TimeCell(BaseCell):
method __init__ (line 178) | def __init__(self, content: Any, data: Any) -> None:
method set_content (line 182) | def set_content(self, content: datetime | None, data: Any) -> None:
class DateCell (line 200) | class DateCell(BaseCell):
method __init__ (line 205) | def __init__(self, content: Any, data: Any) -> None:
method set_content (line 209) | def set_content(self, content: Any, data: Any) -> None:
class MsgCell (line 218) | class MsgCell(BaseCell):
method __init__ (line 223) | def __init__(self, content: str, data: Any) -> None:
class BaseMonitor (line 229) | class BaseMonitor(QtWidgets.QTableWidget):
method __init__ (line 241) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method init_ui (line 253) | def init_ui(self) -> None:
method init_table (line 258) | def init_table(self) -> None:
method init_menu (line 272) | def init_menu(self) -> None:
method register_event (line 286) | def register_event(self) -> None:
method process_event (line 294) | def process_event(self, event: Event) -> None:
method insert_new_row (line 319) | def insert_new_row(self, data: Any) -> None:
method update_old_row (line 340) | def update_old_row(self, data: Any) -> None:
method resize_columns (line 351) | def resize_columns(self) -> None:
method save_csv (line 357) | def save_csv(self) -> None:
method contextMenuEvent (line 386) | def contextMenuEvent(self, event: QtGui.QContextMenuEvent) -> None:
method save_setting (line 392) | def save_setting(self) -> None:
method load_setting (line 397) | def load_setting(self) -> None:
class TickMonitor (line 407) | class TickMonitor(BaseMonitor):
class LogMonitor (line 434) | class LogMonitor(BaseMonitor):
class TradeMonitor (line 450) | class TradeMonitor(BaseMonitor):
class OrderMonitor (line 473) | class OrderMonitor(BaseMonitor):
method init_ui (line 498) | def init_ui(self) -> None:
method cancel_order (line 507) | def cancel_order(self, cell: BaseCell) -> None:
class PositionMonitor (line 516) | class PositionMonitor(BaseMonitor):
class AccountMonitor (line 538) | class AccountMonitor(BaseMonitor):
class QuoteMonitor (line 556) | class QuoteMonitor(BaseMonitor):
method init_ui (line 581) | def init_ui(self) -> None:
method cancel_quote (line 590) | def cancel_quote(self, cell: BaseCell) -> None:
class ConnectDialog (line 599) | class ConnectDialog(QtWidgets.QDialog):
method __init__ (line 604) | def __init__(self, main_engine: MainEngine, gateway_name: str) -> None:
method init_ui (line 616) | def init_ui(self) -> None:
method connect_gateway (line 667) | def connect_gateway(self) -> None:
class TradingWidget (line 692) | class TradingWidget(QtWidgets.QWidget):
method __init__ (line 699) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method init_ui (line 712) | def init_ui(self) -> None:
method create_label (line 842) | def create_label(
method register_event (line 856) | def register_event(self) -> None:
method process_tick_event (line 861) | def process_tick_event(self, event: Event) -> None:
method set_vt_symbol (line 903) | def set_vt_symbol(self) -> None:
method clear_label_text (line 946) | def clear_label_text(self) -> None:
method send_order (line 977) | def send_order(self) -> None:
method cancel_all (line 1013) | def cancel_all(self) -> None:
method update_with_cell (line 1022) | def update_with_cell(self, cell: BaseCell) -> None:
class ActiveOrderMonitor (line 1053) | class ActiveOrderMonitor(OrderMonitor):
method process_event (line 1058) | def process_event(self, event: Event) -> None:
class ContractManager (line 1074) | class ContractManager(QtWidgets.QWidget):
method __init__ (line 1095) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method init_ui (line 1103) | def init_ui(self) -> None:
method show_contracts (line 1136) | def show_contracts(self) -> None:
class AboutDialog (line 1172) | class AboutDialog(QtWidgets.QDialog):
method __init__ (line 1177) | def __init__(self, main_engine: MainEngine, event_engine: EventEngine)...
method init_ui (line 1186) | def init_ui(self) -> None:
class GlobalDialog (line 1219) | class GlobalDialog(QtWidgets.QDialog):
method __init__ (line 1224) | def __init__(self) -> None:
method init_ui (line 1232) | def init_ui(self) -> None:
method update_setting (line 1265) | def update_setting(self) -> None:
FILE: vnpy/trader/utility.py
function extract_vt_symbol (line 23) | def extract_vt_symbol(vt_symbol: str) -> tuple[str, Exchange]:
function generate_vt_symbol (line 31) | def generate_vt_symbol(symbol: str, exchange: Exchange) -> str:
function _get_trader_dir (line 38) | def _get_trader_dir(temp_name: str) -> tuple[Path, Path]:
function get_file_path (line 65) | def get_file_path(filename: str) -> Path:
function get_folder_path (line 72) | def get_folder_path(folder_name: str) -> Path:
function get_icon_path (line 82) | def get_icon_path(filepath: str, ico_name: str) -> str:
function load_json (line 91) | def load_json(filename: str) -> dict:
function save_json (line 106) | def save_json(filename: str, data: dict) -> None:
function round_to (line 120) | def round_to(value: float, target: float) -> float:
function floor_to (line 130) | def floor_to(value: float, target: float) -> float:
function ceil_to (line 140) | def ceil_to(value: float, target: float) -> float:
function get_digits (line 150) | def get_digits(value: float) -> int:
class BarGenerator (line 166) | class BarGenerator:
method __init__ (line 176) | def __init__(
method update_tick (line 204) | def update_tick(self, tick: TickData) -> None:
method update_bar (line 262) | def update_bar(self, bar: BarData) -> None:
method update_bar_minute_window (line 273) | def update_bar_minute_window(self, bar: BarData) -> None:
method update_bar_hour_window (line 311) | def update_bar_hour_window(self, bar: BarData) -> None:
method on_hour_bar (line 390) | def on_hour_bar(self, bar: BarData) -> None:
method update_bar_daily_window (line 430) | def update_bar_daily_window(self, bar: BarData) -> None:
method generate (line 474) | def generate(self) -> BarData | None:
class ArrayManager (line 488) | class ArrayManager:
method __init__ (line 495) | def __init__(self, size: int = 100) -> None:
method update_bar (line 509) | def update_bar(self, bar: BarData) -> None:
method open (line 534) | def open(self) -> np.ndarray:
method high (line 541) | def high(self) -> np.ndarray:
method low (line 548) | def low(self) -> np.ndarray:
method close (line 555) | def close(self) -> np.ndarray:
method volume (line 562) | def volume(self) -> np.ndarray:
method turnover (line 569) | def turnover(self) -> np.ndarray:
method open_interest (line 576) | def open_interest(self) -> np.ndarray:
method sma (line 583) | def sma(self, n: int, array: Literal[False] = False) -> float: ...
method sma (line 585) | def sma(self, n: int, array: Literal[True]) -> np.ndarray: ...
method sma (line 586) | def sma(self, n: int, array: bool = False) -> float | np.ndarray:
method ema (line 598) | def ema(self, n: int, array: Literal[False] = False) -> float: ...
method ema (line 600) | def ema(self, n: int, array: Literal[True]) -> np.ndarray: ...
method ema (line 601) | def ema(self, n: int, array: bool = False) -> float | np.ndarray:
method kama (line 613) | def kama(self, n: int, array: Literal[False] = False) -> float: ...
method kama (line 615) | def kama(self, n: int, array: Literal[True]) -> np.ndarray: ...
method kama (line 616) | def kama(self, n: int, array: bool = False) -> float | np.ndarray:
method wma (line 628) | def wma(self, n: int, array: Literal[False] = False) -> float: ...
method wma (line 630) | def wma(self, n: int, array: Literal[True]) -> np.ndarray: ...
method wma (line 631) | def wma(self, n: int, array: bool = False) -> float | np.ndarray:
method apo (line 643) | def apo(self, fast_period: int, slow_period: int, matype: int = 0, arr...
method apo (line 645) | def apo(self, fast_period: int, slow_period: int, matype: int = 0, *, ...
method apo (line 646) | def apo(
method cmo (line 664) | def cmo(self, n: int, array: Literal[False] = False) -> float: ...
method cmo (line 666) | def cmo(self, n: int, array: Literal[True]) -> np.ndarray: ...
method cmo (line 667) | def cmo(self, n: int, array: bool = False) -> float | np.ndarray:
method mom (line 679) | def mom(self, n: int, array: Literal[False] = False) -> float: ...
method mom (line 681) | def mom(self, n: int, array: Literal[True]) -> np.ndarray: ...
method mom (line 682) | def mom(self, n: int, array: bool = False) -> float | np.ndarray:
method ppo (line 694) | def ppo(self, fast_period: int, slow_period: int, matype: int = 0, arr...
method ppo (line 696) | def ppo(self, fast_period: int, slow_period: int, matype: int = 0, *, ...
method ppo (line 697) | def ppo(
method roc (line 715) | def roc(self, n: int, array: Literal[False] = False) -> float: ...
method roc (line 717) | def roc(self, n: int, array: Literal[True]) -> np.ndarray: ...
method roc (line 718) | def roc(self, n: int, array: bool = False) -> float | np.ndarray:
method rocr (line 730) | def rocr(self, n: int, array: Literal[False] = False) -> float: ...
method rocr (line 732) | def rocr(self, n: int, array: Literal[True]) -> np.ndarray: ...
method rocr (line 733) | def rocr(self, n: int, array: bool = False) -> float | np.ndarray:
method rocp (line 745) | def rocp(self, n: int, array: Literal[False] = False) -> float: ...
method rocp (line 747) | def rocp(self, n: int, array: Literal[True]) -> np.ndarray: ...
method rocp (line 748) | def rocp(self, n: int, array: bool = False) -> float | np.ndarray:
method rocr_100 (line 760) | def rocr_100(self, n: int, array: Literal[False] = False) -> float: ...
method rocr_100 (line 762) | def rocr_100(self, n: int, array: Literal[True]) -> np.ndarray: ...
method rocr_100 (line 763) | def rocr_100(self, n: int, array: bool = False) -> float | np.ndarray:
method trix (line 775) | def trix(self, n: int, array: Literal[False] = False) -> float: ...
method trix (line 777) | def trix(self, n: int, array: Literal[True]) -> np.ndarray: ...
method trix (line 778) | def trix(self, n: int, array: bool = False) -> float | np.ndarray:
method std (line 790) | def std(self, n: int, nbdev: int = 1, array: Literal[False] = False) -...
method std (line 792) | def std(self, n: int, nbdev: int = 1, *, array: Literal[True]) -> np.n...
method std (line 793) | def std(self, n: int, nbdev: int = 1, array: bool = False) -> float | ...
method obv (line 805) | def obv(self, array: Literal[False] = False) -> float: ...
method obv (line 807) | def obv(self, array: Literal[True]) -> np.ndarray: ...
method obv (line 808) | def obv(self, array: bool = False) -> float | np.ndarray:
method cci (line 820) | def cci(self, n: int, array: Literal[False] = False) -> float: ...
method cci (line 822) | def cci(self, n: int, array: Literal[True]) -> np.ndarray: ...
method cci (line 823) | def cci(self, n: int, array: bool = False) -> float | np.ndarray:
method atr (line 835) | def atr(self, n: int, array: Literal[False] = False) -> float: ...
method atr (line 837) | def atr(self, n: int, array: Literal[True]) -> np.ndarray: ...
method atr (line 838) | def atr(self, n: int, array: bool = False) -> float | np.ndarray:
method natr (line 850) | def natr(self, n: int, array: Literal[False] = False) -> float: ...
method natr (line 852) | def natr(self, n: int, array: Literal[True]) -> np.ndarray: ...
method natr (line 853) | def natr(self, n: int, array: bool = False) -> float | np.ndarray:
method rsi (line 865) | def rsi(self, n: int, array: Literal[False] = False) -> float: ...
method rsi (line 867) | def rsi(self, n: int, array: Literal[True]) -> np.ndarray: ...
method rsi (line 868) | def rsi(self, n: int, array: bool = False) -> float | np.ndarray:
method macd (line 880) | def macd(self, fast_period: int, slow_period: int, signal_period: int,...
method macd (line 882) | def macd(self, fast_period: int, slow_period: int, signal_period: int,...
method macd (line 883) | def macd(
method adx (line 901) | def adx(self, n: int, array: Literal[False] = False) -> float: ...
method adx (line 903) | def adx(self, n: int, array: Literal[True]) -> np.ndarray: ...
method adx (line 904) | def adx(self, n: int, array: bool = False) -> float | np.ndarray:
method adxr (line 916) | def adxr(self, n: int, array: Literal[False] = False) -> float: ...
method adxr (line 918) | def adxr(self, n: int, array: Literal[True]) -> np.ndarray: ...
method adxr (line 919) | def adxr(self, n: int, array: bool = False) -> float | np.ndarray:
method dx (line 931) | def dx(self, n: int, array: Literal[False] = False) -> float: ...
method dx (line 933) | def dx(self, n: int, array: Literal[True]) -> np.ndarray: ...
method dx (line 934) | def dx(self, n: int, array: bool = False) -> float | np.ndarray:
method minus_di (line 946) | def minus_di(self, n: int, array: Literal[False] = False) -> float: ...
method minus_di (line 948) | def minus_di(self, n: int, array: Literal[True]) -> np.ndarray: ...
method minus_di (line 949) | def minus_di(self, n: int, array: bool = False) -> float | np.ndarray:
method plus_di (line 961) | def plus_di(self, n: int, array: Literal[False] = False) -> float: ...
method plus_di (line 963) | def plus_di(self, n: int, array: Literal[True]) -> np.ndarray: ...
method plus_di (line 964) | def plus_di(self, n: int, array: bool = False) -> float | np.ndarray:
method willr (line 976) | def willr(self, n: int, array: Literal[False] = False) -> float: ...
method willr (line 978) | def willr(self, n: int, array: Literal[True]) -> np.ndarray: ...
method willr (line 979) | def willr(self, n: int, array: bool = False) -> float | np.ndarray:
method ultosc (line 991) | def ultosc(self, time_period1: int = 7, time_period2: int = 14, time_p...
method ultosc (line 993) | def ultosc(self, time_period1: int = 7, time_period2: int = 14, time_p...
method ultosc (line 994) | def ultosc(
method trange (line 1012) | def trange(self, array: Literal[False] = False) -> float: ...
method trange (line 1014) | def trange(self, array: Literal[True]) -> np.ndarray: ...
method trange (line 1015) | def trange(self, array: bool = False) -> float | np.ndarray:
method boll (line 1027) | def boll(self, n: int, dev: float, array: Literal[False] = False) -> t...
method boll (line 1029) | def boll(self, n: int, dev: float, array: Literal[True]) -> tuple[np.n...
method boll (line 1030) | def boll(
method keltner (line 1054) | def keltner(self, n: int, dev: float, array: Literal[False] = False) -...
method keltner (line 1056) | def keltner(self, n: int, dev: float, array: Literal[True]) -> tuple[n...
method keltner (line 1057) | def keltner(
method donchian (line 1081) | def donchian(self, n: int, array: Literal[False] = False) -> tuple[flo...
method donchian (line 1083) | def donchian(self, n: int, array: Literal[True]) -> tuple[np.ndarray, ...
method donchian (line 1084) | def donchian(
method aroon (line 1098) | def aroon(self, n: int, array: Literal[False] = False) -> tuple[float,...
method aroon (line 1100) | def aroon(self, n: int, array: Literal[True]) -> tuple[np.ndarray, np....
method aroon (line 1101) | def aroon(
method aroonosc (line 1116) | def aroonosc(self, n: int, array: Literal[False] = False) -> float: ...
method aroonosc (line 1118) | def aroonosc(self, n: int, array: Literal[True]) -> np.ndarray: ...
method aroonosc (line 1119) | def aroonosc(self, n: int, array: bool = False) -> float | np.ndarray:
method minus_dm (line 1132) | def minus_dm(self, n: int, array: Literal[False] = False) -> float: ...
method minus_dm (line 1134) | def minus_dm(self, n: int, array: Literal[True]) -> np.ndarray: ...
method minus_dm (line 1135) | def minus_dm(self, n: int, array: bool = False) -> float | np.ndarray:
method plus_dm (line 1148) | def plus_dm(self, n: int, array: Literal[False] = False) -> float: ...
method plus_dm (line 1150) | def plus_dm(self, n: int, array: Literal[True]) -> np.ndarray: ...
method plus_dm (line 1151) | def plus_dm(self, n: int, array: bool = False) -> float | np.ndarray:
method mfi (line 1164) | def mfi(self, n: int, array: Literal[False] = False) -> float: ...
method mfi (line 1166) | def mfi(self, n: int, array: Literal[True]) -> np.ndarray: ...
method mfi (line 1167) | def mfi(self, n: int, array: bool = False) -> float | np.ndarray:
method ad (line 1179) | def ad(self, array: Literal[False] = False) -> float: ...
method ad (line 1181) | def ad(self, array: Literal[True]) -> np.ndarray: ...
method ad (line 1182) | def ad(self, array: bool = False) -> float | np.ndarray:
method adosc (line 1194) | def adosc(self, fast_period: int, slow_period: int, array: Literal[Fal...
method adosc (line 1196) | def adosc(self, fast_period: int, slow_period: int, array: Literal[Tru...
method adosc (line 1197) | def adosc(
method bop (line 1214) | def bop(self, array: Literal[False] = False) -> float: ...
method bop (line 1216) | def bop(self, array: Literal[True]) -> np.ndarray: ...
method bop (line 1217) | def bop(self, array: bool = False) -> float | np.ndarray:
method stoch (line 1230) | def stoch(self, fastk_period: int, slowk_period: int, slowk_matype: in...
method stoch (line 1232) | def stoch(self, fastk_period: int, slowk_period: int, slowk_matype: in...
method stoch (line 1233) | def stoch(
method sar (line 1260) | def sar(self, acceleration: float, maximum: float, array: Literal[Fals...
method sar (line 1262) | def sar(self, acceleration: float, maximum: float, array: Literal[True...
method sar (line 1263) | def sar(self, acceleration: float, maximum: float, array: bool = False...
function virtual (line 1275) | def virtual(func: Callable) -> Callable:
Copy disabled (too large)
Download .json
Condensed preview — 155 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (34,494K chars).
[
{
"path": ".github/CODE_OF_CONDUCT.md",
"chars": 266,
"preview": "# 行为准则\n\n这是一份VeighNa项目社区的行为准则,也是项目作者自己在刚入行量化金融行业时对于理想中的社区的期望:\n\n* 为交易员而生:作为一款从金融机构量化业务中诞生的交易系统开发框架,设计上都优先满足机构专业交易员的使用习惯,而不"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 231,
"preview": "## 环境\n\n* 操作系统: 如Windows 11或者Ubuntu 22.04\n* Python版本: 如VeighNa Studio-4.0.0\n* VeighNa版本: 如v4.0.0发行版或者dev branch 20250320("
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 86,
"preview": "建议每次发起的PR内容尽可能精简,复杂的修改请拆分为多次PR,便于管理合并。\n\n## 改进内容\n\n1. \n2. \n3.\n\n## 相关的Issue号(如有)\n\nClose #"
},
{
"path": ".github/SUPPORT.md",
"chars": 202,
"preview": "# 获取帮助\n\n在开发和使用VeighNa项目的过程中遇到问题时,获取帮助的渠道包括:\n\n* Github Issues:[Issues页面](https://github.com/vnpy/vnpy/issues)\n* 官方QQ群: 26"
},
{
"path": ".github/workflows/pythonapp.yml",
"chars": 878,
"preview": "name: Python application\n\non: [push]\n\njobs:\n build:\n\n runs-on: windows-latest\n\n steps:\n - uses: actions/checko"
},
{
"path": ".gitignore",
"chars": 309,
"preview": "# Python\n*.pyc\n*.pyo\n*.pyd\n*.egg-info/\n\n# Jupyter\n.ipynb_checkpoints\n\n# IDE\n.vscode\n.idea\n*.wpr\n*.wpu\n.vs\nx64\n\n# Temp\nbu"
},
{
"path": "CHANGELOG.md",
"chars": 20687,
"preview": "# 4.3.0版本\n\n## 新增\n\n1. vnpy.alpha增加WorldQuant的Alpha 101因子特征数据集\n\n## 调整\n\n1. vnpy_sec/vnpy_esunny升级适配4.0版本\n2. vnpy_ctabacktes"
},
{
"path": "LICENSE",
"chars": 1087,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015-present, Xiaoyou Chen\n\nPermission is hereby granted, free of charge, to any pe"
},
{
"path": "README.md",
"chars": 12908,
"preview": "# VeighNa - By Traders, For Traders, AI-Powered.\n\n<p align=\"center\">\n <img src =\"https://vnpy.oss-cn-shanghai.aliyuncs."
},
{
"path": "README_ENG.md",
"chars": 22889,
"preview": "# VeighNa - By Traders, For Traders, AI-Powered.\n\n<p align=\"center\">\n <img src =\"https://vnpy.oss-cn-shanghai.aliyuncs."
},
{
"path": "docs/community/app/algo_trading.md",
"chars": 3900,
"preview": "# AlgoTrading - 算法委托执行交易模块\n\n## 功能简介\n\nAlgoTrading是用于**算法委托执行交易**的模块,用户可以通过其UI界面操作来便捷完成启动算法、保存配置、停止算法等任务。\n\n算法交易负责委托订单的具体执行"
},
{
"path": "docs/community/app/chart_wizard.md",
"chars": 1413,
"preview": "# ChartWizard - 实时K线图表模块\n\n## 功能简介\n\nChartWizard是用于**实时K线图表展示**的功能模块,用户可以通过其UI界面查看实时和历史K线行情,目前只支持显示1分钟级别的K线数据,实时K线(最新的一根K线"
},
{
"path": "docs/community/app/cta_backtester.md",
"chars": 6784,
"preview": "# CtaBacktester - CTA回测研究模块\n\n## 功能简介\n\nCtaBacktester是用于**CTA回测研究**的功能模块,用户可以通过其UI界面操作来便捷完成数据下载、历史回测、结果分析和参数优化等任务。\n\n## 加载启"
},
{
"path": "docs/community/app/cta_strategy.md",
"chars": 22440,
"preview": "# CtaStrategy - CTA自动交易模块\n\n## 功能简介\n\nCtaStrategy是用于**CTA自动交易**的功能模块,用户可以通过其UI界面操作来便捷完成策略初始化、策略启动、策略停止、策略参数编辑以及策略移除等任务。\n\n#"
},
{
"path": "docs/community/app/data_manager.md",
"chars": 4442,
"preview": "# DataManager - 历史数据管理模块\n\n## 功能简介\n\nDataManager是用于**历史数据管理**的功能模块,用户可以通过其UI界面操作来便捷完成数据下载、数据查看、数据导入和数据导出等任务。\n\n## 加载启动\n\n###"
},
{
"path": "docs/community/app/data_recorder.md",
"chars": 1755,
"preview": "# DataRecorder - 实盘行情记录模块\n\nDataRecorder是用于**实盘行情记录**的模块,用户可以利用该模块记录实时Tick数据和K线数据,并自动写入保存到数据库中。\n\n记录的数据可以通过DataManager模块查看"
},
{
"path": "docs/community/app/excel_rtd.md",
"chars": 2742,
"preview": "# ExcelRtd - EXCEL RTD模块\n\n## 功能简介\n\nExcelRtd是用于**在Excel中访问VeighNa程序内任意数据信息**的功能模块,\nRTD全称是RealTimeData,是微软提供的主要面向金融行业中实时数据"
},
{
"path": "docs/community/app/index.rst",
"chars": 386,
"preview": "策略应用\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n :caption: Elite版\n\n cta_strategy.md\n cta_backtester.md\n spread_trad"
},
{
"path": "docs/community/app/option_master.md",
"chars": 5625,
"preview": "# OptionMaster - 期权波动率交易模块\n\n## 功能简介\n\nOptionMaster是用于**期权波动率交易**的功能模块,用户可以通过OptionMaster完成期权实时定价、波动率曲面跟踪、持仓希腊值监控、组合压力测试、电"
},
{
"path": "docs/community/app/paper_account.md",
"chars": 2280,
"preview": "# PaperAccount - 本地仿真交易模块\n\n\n## 功能简介\n\nPaperAccount是用于**本地仿真交易**的功能模块,用户可以通过其UI界面基于实盘行情进行本地化的模拟交易。\n\n## 加载启动\n\n### VeighNa S"
},
{
"path": "docs/community/app/portfolio_manager.md",
"chars": 2266,
"preview": "\n# PortfolioManager - 投资组合管理模块\n\n## 功能简介\n\nPortfolioManager是用于**投资组合管理**的功能模块,用户可以在盘中通过其UI界面对交易策略进行实时的业绩跟踪和盈亏分析。 \n\n\n## 加载"
},
{
"path": "docs/community/app/portfolio_strategy.md",
"chars": 24278,
"preview": "# PortfolioStrategy - 多合约组合策略模块\n\n## 功能简介\n\nPortfolioStrategy是用于**多合约组合策略实盘**的功能模块,用户可以通过其UI界面操作来便捷完成策略初始化、策略启动、策略停止、策略参数编"
},
{
"path": "docs/community/app/risk_manager.md",
"chars": 1406,
"preview": "# RiskManager - 事前风控管理模块\n\n## 功能简介\n\nRiskManager模块是用于**事前风控管理**的功能模块,用户可以通过其UI界面操作来便捷完成启动风控,参数修改和停止风控等任务。\n\n## 加载启动\n\n### Ve"
},
{
"path": "docs/community/app/rpc_service.md",
"chars": 2493,
"preview": "# RpcService - RPC服务器模块\n\n## 功能简介\n\nRpcService是用于**将VeighNa Trader进程转化为RPC服务器**的功能模块,对外提供交易路由、行情数据推送、持仓资金查询等功能。\n\n关于RPC的具体应"
},
{
"path": "docs/community/app/script_trader.md",
"chars": 8988,
"preview": "# ScriptTrader - 脚本策略交易模块\n\n## 功能简介\n\nScriptTrader是用于**脚本策略交易**的功能模块,提供了交互式的量化分析和程序化交易功能,又提供以整个策略连续运行的脚本策略功能。\n\n故其可视为直接利用Py"
},
{
"path": "docs/community/app/spread_trading.md",
"chars": 21089,
"preview": "# SpreadTrading - 多合约价差套利模块\n\n## 功能简介\n\nSpreadTrading是用于**多合约价差套利**的功能模块,用户可以通过其UI界面操作来便捷创建灵活的价差合约、完成手动交易和自动交易等任务。\n\n\n## 加载"
},
{
"path": "docs/community/app/web_trader.md",
"chars": 4406,
"preview": "# WebTrader - Web服务器模块\n\n## 功能简介\n\nWebTrader是用于**Web应用后端服务**的功能模块,用户可以通过浏览器(而非PyQt桌面端)来运行管理VeighNa量化策略交易。\n\n## 架构设计\n\nWebTra"
},
{
"path": "docs/community/index.rst",
"chars": 89,
"preview": "社区版\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n\n info/index\n install/index\n app/index\n"
},
{
"path": "docs/community/info/contribution.md",
"chars": 1969,
"preview": "# 贡献代码\n\n---\n## 创建PR\n我们欢迎任何人贡献代码到VeighNa。 \n\n如果希望贡献代码请使用Github的PR(Pull Request)的流程。\n\nPR流程大致如下:\n\n---\n1. [创建 Issue][CreateI"
},
{
"path": "docs/community/info/database.md",
"chars": 9212,
"preview": "# 数据库\n\nVeighNa Trader目前支持以下八种数据库:\n\n## SQL类数据库简介\n\n### SQLite(默认)\n\nSQLite是一个轻量的嵌入式数据库,无需安装和配置数据服务程序,是VeighNa的**默认数据库**。适合入"
},
{
"path": "docs/community/info/datafeed.md",
"chars": 3394,
"preview": "# 数据服务\n\n\n对于数据服务,VeighNa提供了标准化的接口BaseDatafeed(位于vnpy.trader.datafeed中),实现了更加灵活的数据服务支持。在全局配置中,和数据服务相关的字段都以datafeed作为前缀。\n\n具"
},
{
"path": "docs/community/info/gateway.md",
"chars": 8285,
"preview": "# 交易接口\n\n## 加载启动\n\n### VeighNa Station加载\n\n启动登录VeighNa Station后,点击【交易】按钮,在配置对话框中的【交易接口】栏勾选想要交易的接口。\n\n### 脚本加载\n\n以CTP接口为例,在启动脚"
},
{
"path": "docs/community/info/i18n.md",
"chars": 4441,
"preview": "# 国际化(i18n)\n\nPython中的i18n可以实现程序的多语言支持。下面通过vnpy包在Windows系统上进行演示。\n\n\n## 标记字符\n\n在源码中标记需要翻译的字符,如以下代码所示:\n\n```python\nfrom .local"
},
{
"path": "docs/community/info/index.rst",
"chars": 216,
"preview": "交易功能\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n :caption: Elite版\n\n introduction.md\n veighna_station.md\n veighna_tr"
},
{
"path": "docs/community/info/introduction.md",
"chars": 2896,
"preview": "# 功能介绍\n\n作为一套基于Python的量化交易程序开发框架,VeighNa致力于提供从交易API对接到策略自动交易的量化解决方案。\n\n## 目标用户\n\n如果有以下需求,不妨试试看VeighNa:\n\n* 基于Python语言来开发自己的量"
},
{
"path": "docs/community/info/pycharm.md",
"chars": 7019,
"preview": "# PyCharm开发指南\n\nPyCharm是由JetBrains公司推出针对Python语言的IDE,其内置一整套可以帮助用户在使用Python语言开发时提高其效率的工具。本文档意在为用户提供通过PyCharm开发使用VeighNa的方案"
},
{
"path": "docs/community/info/veighna_station.md",
"chars": 3858,
"preview": "# VeighNa Station\n\n## 启动程序\n\n### 点击图标启动\n\n安装成功后,双击桌面上VeighNa Station快捷方式:\n\n是微软开发的跨平台免费源代码编辑器。用户可以通过内置的扩展程序商店安装扩展,以拓展其功能。本文档旨在为用户提供在VSCode中开发VeighNa的参考方案。\n\n"
},
{
"path": "docs/community/install/index.rst",
"chars": 106,
"preview": "安装指南\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n\n windows_install.md\n ubuntu_install.md\n mac_install.md"
},
{
"path": "docs/community/install/mac_install.md",
"chars": 2979,
"preview": "# Mac安装指南\n\n## Mac系统的CTP接口支持\n\n得益于Python语言本身的跨平台优势(Windows、Linux、Mac三大系统),VeighNa量化交易平台的核心框架部分很早就可以在Mac系统上运行。\n\n但由于C++类交易AP"
},
{
"path": "docs/community/install/ubuntu_install.md",
"chars": 2608,
"preview": "# Ubuntu安装指南\n\n## 检查Python\n\n检查本地Python版本,需要需要3.7版本以上的版本,可在命令行运行python命令查看。\n\n。\n\n\n## 应用场景\n\n市场深度交易组件应用于单合约实时日内交易。支持显示买方和卖方订单的实时挂单数据,按目前价格进行更新以反映实时市场活动。\n\n\n"
},
{
"path": "docs/elite/extension/index.rst",
"chars": 129,
"preview": "智能交易\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n\n elite_ladder.md\n elite_algotrading.md\n elite_dingtalk.md\n elite_f"
},
{
"path": "docs/elite/index.rst",
"chars": 98,
"preview": "Elite版\n~~~~~~~~~\n\n.. toctree::\n :maxdepth: 2\n\n info/index\n strategy/index\n extension/index"
},
{
"path": "docs/elite/info/elite_install.md",
"chars": 964,
"preview": "# Elite安装配置\n\n本文档中安装步骤适用的操作系统包括:\n\n- Windows 10/11\n- Windows Server 2019/2022\n\n> 其他版本的Windows系统安装时可能遇到各种依赖库问题,不推荐使用。\n\n\n## "
},
{
"path": "docs/elite/info/elite_lab.md",
"chars": 2110,
"preview": "# 投研开发环境\n\n\n## 启动运行\n\n### 点击图标启动\n\n安装成功后,双击桌面上VeighNa Elite Lab快捷方式:\n\n:\n \"\"\"\n "
},
{
"path": "examples/simple_rpc/test_server.py",
"chars": 685,
"preview": "from time import sleep, time\n\nfrom vnpy.rpc import RpcServer\n\n\nclass TestServer(RpcServer):\n \"\"\"\n Test RpcServer\n "
},
{
"path": "examples/spread_backtesting/backtesting.ipynb",
"chars": 3192,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n "
},
{
"path": "examples/veighna_trader/demo_script.py",
"chars": 956,
"preview": "from time import sleep\n\nfrom vnpy_scripttrader import ScriptEngine\n\n\ndef run(engine: ScriptEngine):\n \"\"\"\n 脚本策略的主函数"
},
{
"path": "examples/veighna_trader/run.py",
"chars": 3016,
"preview": "from vnpy.event import EventEngine\n\nfrom vnpy.trader.engine import MainEngine\nfrom vnpy.trader.ui import MainWindow, cre"
},
{
"path": "install.bat",
"chars": 460,
"preview": "@ECHO OFF\nSET python=%1\nSET pypi_index=%2\nIF %python%\"\" == \"\" SET python=python\nIF %pypi_index%\"\" == \"\" SET "
},
{
"path": "install.sh",
"chars": 868,
"preview": "#!/usr/bin/env bash\n\npython=$1\npypi_index=$2\nshift 2\n\n\n[[ -z $python ]] && python=python3\n[[ -z $pypi_index ]] && pypi_i"
},
{
"path": "install_osx.sh",
"chars": 621,
"preview": "#!/usr/bin/env bash\n\npython=$1\npypi_index=$2\nshift 2\n\n[[ -z $python ]] && python=python3\n[[ -z $pypi_index ]] && pypi_in"
},
{
"path": "pyproject.toml",
"chars": 3101,
"preview": "[project]\nname = \"vnpy\"\ndynamic = [\"version\"]\ndescription = \"A framework for developing quant trading systems.\"\nreadme ="
},
{
"path": "tests/test_alpha101.py",
"chars": 35511,
"preview": "import pytest\r\nimport polars as pl\r\nimport numpy as np\r\nfrom datetime import datetime, timedelta\r\n\r\nfrom vnpy.alpha.data"
},
{
"path": "vnpy/__init__.py",
"chars": 1146,
"preview": "# The MIT License (MIT)\n\n# Copyright (c) 2015-present, Xiaoyou Chen\n\n# Permission is hereby granted, free of charge, to "
},
{
"path": "vnpy/alpha/__init__.py",
"chars": 357,
"preview": "from .logger import logger\nfrom .dataset import AlphaDataset, Segment, to_datetime\nfrom .model import AlphaModel\nfrom .s"
},
{
"path": "vnpy/alpha/dataset/__init__.py",
"chars": 424,
"preview": "from .template import AlphaDataset\nfrom .utility import Segment, to_datetime\nfrom .processor import (\n process_drop_n"
},
{
"path": "vnpy/alpha/dataset/cs_function.py",
"chars": 1715,
"preview": "\"\"\"\nCross Section Operators\n\"\"\"\n\nimport polars as pl\n\nfrom .utility import DataProxy\n\n\ndef cs_rank(feature: DataProxy) -"
},
{
"path": "vnpy/alpha/dataset/datasets/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/alpha/dataset/datasets/alpha_101.py",
"chars": 20155,
"preview": "import polars as pl\n\nfrom vnpy.alpha import AlphaDataset\n\n\nclass Alpha101(AlphaDataset):\n \"\"\"101 basic factors from W"
},
{
"path": "vnpy/alpha/dataset/datasets/alpha_158.py",
"chars": 5478,
"preview": "import polars as pl\n\nfrom vnpy.alpha import AlphaDataset\n\n\nclass Alpha158(AlphaDataset):\n \"\"\"158 basic factors from Q"
},
{
"path": "vnpy/alpha/dataset/math_function.py",
"chars": 5855,
"preview": "\"\"\"\nMath Functions\n\"\"\"\n\nimport polars as pl\n\nfrom .utility import DataProxy\n\n\ndef less(feature1: DataProxy, feature2: Da"
},
{
"path": "vnpy/alpha/dataset/processor.py",
"chars": 3563,
"preview": "from datetime import datetime\n\nimport numpy as np\nimport polars as pl\n\nfrom .utility import to_datetime\n\n\ndef process_dr"
},
{
"path": "vnpy/alpha/dataset/ta_function.py",
"chars": 1251,
"preview": "\"\"\"\nTechnical Analysis Operators\n\"\"\"\n\nimport talib\nimport polars as pl\nimport pandas as pd\n\nfrom .utility import DataPro"
},
{
"path": "vnpy/alpha/dataset/template.py",
"chars": 10025,
"preview": "import time\nfrom datetime import datetime\nfrom typing import cast\nfrom collections.abc import Callable\nfrom multiprocess"
},
{
"path": "vnpy/alpha/dataset/ts_function.py",
"chars": 11170,
"preview": "\"\"\"Time Series Operators\"\"\"\n\nfrom typing import cast\n\nfrom scipy import stats\nimport polars as pl\nimport numpy as np\n\nfr"
},
{
"path": "vnpy/alpha/dataset/utility.py",
"chars": 6003,
"preview": "from datetime import datetime\nfrom enum import Enum\nfrom typing import Union\n\nimport polars as pl\n\n\nclass DataProxy:\n "
},
{
"path": "vnpy/alpha/lab.py",
"chars": 15550,
"preview": "import json\nimport shelve\nimport pickle\nfrom pathlib import Path\nfrom datetime import datetime, timedelta\nfrom collectio"
},
{
"path": "vnpy/alpha/logger.py",
"chars": 234,
"preview": "import sys\n\nfrom loguru import logger\n\n\n# Remove default output\nlogger.remove()\n\n\n# Add terminal output\nfmt: str = \"<gre"
},
{
"path": "vnpy/alpha/model/__init__.py",
"chars": 67,
"preview": "from .template import AlphaModel\n\n\n__all__ = [\n \"AlphaModel\",\n]\n"
},
{
"path": "vnpy/alpha/model/models/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/alpha/model/models/lasso_model.py",
"chars": 3911,
"preview": "import numpy as np\nimport polars as pl\nfrom sklearn.linear_model import Lasso # type: ignore\n\nfrom vnpy.alpha impor"
},
{
"path": "vnpy/alpha/model/models/lgb_model.py",
"chars": 4849,
"preview": "from typing import cast\n\nimport numpy as np\nimport polars as pl\nimport lightgbm as lgb\nimport matplotlib.pyplot as plt\n\n"
},
{
"path": "vnpy/alpha/model/models/mlp_model.py",
"chars": 20757,
"preview": "import copy\nfrom collections import defaultdict\nfrom typing import Literal, cast\n\nimport numpy as np\nimport pandas as pd"
},
{
"path": "vnpy/alpha/model/template.py",
"chars": 674,
"preview": "from abc import ABCMeta, abstractmethod\nfrom typing import Any\n\nimport numpy as np\n\nfrom vnpy.alpha.dataset import Alpha"
},
{
"path": "vnpy/alpha/strategy/__init__.py",
"chars": 140,
"preview": "from .template import AlphaStrategy\nfrom .backtesting import BacktestingEngine\n\n\n__all__ = [\n \"AlphaStrategy\",\n \"B"
},
{
"path": "vnpy/alpha/strategy/backtesting.py",
"chars": 33660,
"preview": "from collections import defaultdict\nfrom datetime import date, datetime\nfrom copy import copy\nfrom typing import cast\nim"
},
{
"path": "vnpy/alpha/strategy/strategies/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/alpha/strategy/strategies/equity_demo_strategy.py",
"chars": 5125,
"preview": "from collections import defaultdict\n\nimport polars as pl\n\nfrom vnpy.trader.object import BarData, TradeData\nfrom vnpy.tr"
},
{
"path": "vnpy/alpha/strategy/template.py",
"chars": 6885,
"preview": "from abc import ABCMeta, abstractmethod\nfrom collections import defaultdict\nfrom typing import TYPE_CHECKING\n\nimport pol"
},
{
"path": "vnpy/chart/__init__.py",
"chars": 144,
"preview": "from .widget import ChartWidget\nfrom .item import CandleItem, VolumeItem\n\n\n__all__ = [\n \"ChartWidget\",\n \"CandleIte"
},
{
"path": "vnpy/chart/axis.py",
"chars": 1143,
"preview": "from datetime import datetime\nfrom typing import Any\n\nimport pyqtgraph as pg # type: ignore\n\nfrom .manager import B"
},
{
"path": "vnpy/chart/base.py",
"chars": 367,
"preview": "from vnpy.trader.ui import QtGui\n\n\nWHITE_COLOR = (255, 255, 255)\nBLACK_COLOR = (0, 0, 0)\nGREY_COLOR = (100, 100, 100)\n\nU"
},
{
"path": "vnpy/chart/item.py",
"chars": 9495,
"preview": "from abc import abstractmethod\n\nimport pyqtgraph as pg # type: ignore\n\nfrom vnpy.trader.ui import QtCore, QtGui, Qt"
},
{
"path": "vnpy/chart/manager.py",
"chars": 5009,
"preview": "from datetime import datetime\nfrom _collections_abc import dict_keys\n\nfrom vnpy.trader.object import BarData\n\nfrom .base"
},
{
"path": "vnpy/chart/widget.py",
"chars": 16162,
"preview": "from datetime import datetime\n\nimport pyqtgraph as pg # type: ignore\n\nfrom vnpy.trader.ui import QtGui, QtWidgets, "
},
{
"path": "vnpy/event/__init__.py",
"chars": 119,
"preview": "from .engine import Event, EventEngine, EVENT_TIMER\n\n\n__all__ = [\n \"Event\",\n \"EventEngine\",\n \"EVENT_TIMER\",\n]\n"
},
{
"path": "vnpy/event/engine.py",
"chars": 4239,
"preview": "\"\"\"\nEvent-driven framework of VeighNa framework.\n\"\"\"\n\nfrom collections import defaultdict\nfrom collections.abc import Ca"
},
{
"path": "vnpy/py.typed",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/rpc/__init__.py",
"chars": 110,
"preview": "from .client import RpcClient\nfrom .server import RpcServer\n\n\n__all__ = [\n \"RpcClient\",\n \"RpcServer\",\n]\n"
},
{
"path": "vnpy/rpc/client.py",
"chars": 4657,
"preview": "import threading\nfrom time import time\nfrom functools import lru_cache\nfrom typing import Any\n\nimport zmq\n\nfrom .common "
},
{
"path": "vnpy/rpc/common.py",
"chars": 174,
"preview": "import signal\n\n\n# Achieve Ctrl-c interrupt recv\nsignal.signal(signal.SIGINT, signal.SIG_DFL)\n\n\nHEARTBEAT_TOPIC = \"heartb"
},
{
"path": "vnpy/rpc/server.py",
"chars": 3839,
"preview": "import threading\nimport traceback\nfrom time import time\nfrom collections.abc import Callable\n\nimport zmq\n\nfrom .common i"
},
{
"path": "vnpy/trader/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/trader/app.py",
"chars": 711,
"preview": "from abc import ABC\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING\n\n\nif TYPE_CHECKING:\n from .engine impor"
},
{
"path": "vnpy/trader/constant.py",
"chars": 4297,
"preview": "\"\"\"\nGeneral constant enums used in the trading platform.\n\"\"\"\n\nfrom enum import Enum\n\nfrom .locale import _\n\n\nclass Direc"
},
{
"path": "vnpy/trader/converter.py",
"chars": 14119,
"preview": "from copy import copy\nfrom typing import TYPE_CHECKING\n\nfrom .object import (\n ContractData,\n OrderData,\n Trade"
},
{
"path": "vnpy/trader/database.py",
"chars": 3532,
"preview": "from abc import ABC, abstractmethod\nfrom datetime import datetime\nfrom types import ModuleType\nfrom dataclasses import d"
},
{
"path": "vnpy/trader/datafeed.py",
"chars": 1776,
"preview": "from types import ModuleType\nfrom collections.abc import Callable\nfrom importlib import import_module\n\nfrom .object impo"
},
{
"path": "vnpy/trader/engine.py",
"chars": 20753,
"preview": "import smtplib\nimport os\nimport traceback\nfrom abc import ABC, abstractmethod\nfrom email.message import EmailMessage\nfro"
},
{
"path": "vnpy/trader/event.py",
"chars": 302,
"preview": "\"\"\"\nEvent type string used in the trading platform.\n\"\"\"\n\nfrom vnpy.event import EVENT_TIMER # noqa\n\nEVENT_TICK = \"eTick"
},
{
"path": "vnpy/trader/gateway.py",
"chars": 7678,
"preview": "from abc import ABC, abstractmethod\n\nfrom vnpy.event import Event, EventEngine\nfrom .event import (\n EVENT_TICK,\n "
},
{
"path": "vnpy/trader/locale/__init__.py",
"chars": 240,
"preview": "import gettext\nfrom pathlib import Path\n\n\nlocaledir: Path = Path(__file__).parent\n\ntranslations: gettext.GNUTranslations"
},
{
"path": "vnpy/trader/locale/build_hook.py",
"chars": 923,
"preview": "from pathlib import Path\n\nfrom hatchling.builders.hooks.plugin.interface import BuildHookInterface\nfrom babel.messages.m"
},
{
"path": "vnpy/trader/locale/en/LC_MESSAGES/vnpy.po",
"chars": 13359,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR ORGANIZATION\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\nmsgid \"\"\nmsgstr \"\"\n\""
},
{
"path": "vnpy/trader/locale/generate_mo.bat",
"chars": 129,
"preview": "python C:\\veighna_studio\\Tools\\i18n\\msgfmt.py -o vnpy\\trader\\locale\\en\\LC_MESSAGES\\vnpy.mo vnpy\\trader\\locale\\en\\LC_MESS"
},
{
"path": "vnpy/trader/locale/generate_pot.bat",
"chars": 116,
"preview": "python C:\\veighna_studio\\Tools\\i18n\\pygettext.py -o vnpy\\trader\\locale\\vnpy.pot vnpy\\trader\\*.py vnpy\\trader\\ui\\*.py"
},
{
"path": "vnpy/trader/locale/vnpy.pot",
"chars": 10332,
"preview": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR ORGANIZATION\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\nmsgid \"\"\nmsgstr \"\"\n\""
},
{
"path": "vnpy/trader/logger.py",
"chars": 1117,
"preview": "import sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom logging import DEBUG, INFO, WARNING, ERROR, CRITI"
},
{
"path": "vnpy/trader/object.py",
"chars": 10512,
"preview": "\"\"\"\nBasic data structure used for general trading function in the trading platform.\n\"\"\"\n\nfrom dataclasses import datacla"
},
{
"path": "vnpy/trader/optimize.py",
"chars": 7666,
"preview": "from collections.abc import Callable\nfrom itertools import product\nfrom concurrent.futures import ProcessPoolExecutor\nfr"
},
{
"path": "vnpy/trader/setting.py",
"chars": 904,
"preview": "\"\"\"\nGlobal setting of the trading platform.\n\"\"\"\n\nfrom logging import INFO\nfrom tzlocal import get_localzone_name\n\nfrom ."
},
{
"path": "vnpy/trader/ui/__init__.py",
"chars": 200,
"preview": "from .qt import QtCore, QtWidgets, QtGui, Qt, create_qapp\nfrom .mainwindow import MainWindow\n\n\n__all__ = [\n \"MainWind"
},
{
"path": "vnpy/trader/ui/ico/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "vnpy/trader/ui/mainwindow.py",
"chars": 10235,
"preview": "\"\"\"\nImplements main window of the trading platform.\n\"\"\"\n\nfrom types import ModuleType\nimport webbrowser\nfrom functools i"
},
{
"path": "vnpy/trader/ui/qt.py",
"chars": 3908,
"preview": "import ctypes\nimport platform\nimport sys\nimport traceback\nimport webbrowser\nimport types\nimport threading\n\nimport qdarks"
},
{
"path": "vnpy/trader/ui/widget.py",
"chars": 43490,
"preview": "\"\"\"\nBasic widgets for UI.\n\"\"\"\n\nimport csv\nimport platform\nfrom enum import Enum\nfrom typing import cast, Any\nfrom copy i"
},
{
"path": "vnpy/trader/utility.py",
"chars": 40838,
"preview": "\"\"\"\nGeneral utility functions.\n\"\"\"\n\nimport json\nimport sys\nfrom datetime import datetime, time\nfrom pathlib import Path\n"
}
]
About this extraction
This page contains the full source code of the vnpy/vnpy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 155 files (32.4 MB), approximately 8.5M tokens, and a symbol index with 873 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.