Giter Site home page Giter Site logo

vnpy_ctastrategy's Introduction

VeighNa - By Traders, For Traders.

💬 Want to read this in english ? Go here

VeighNa是一套基于Python的开源量化交易系统开发框架,在开源社区持续不断的贡献下一步步成长为多功能量化交易平台,自发布以来已经积累了众多来自金融机构或相关领域的用户,包括私募基金、证券公司、期货公司等。

🚀 🚀 🚀 面向专业交易员的【VeighNa Elite量化终端】已经正式发布,针对专业交易员群体在海量策略并发、智能移仓换月、算法拆单执行、多账户交易支持等方面的需求提供了完善支持。了解更详细的信息请扫描下方二维码关注后,点击菜单栏的【社区交流 -> Elite会员服务】即可

在使用VeighNa进行二次开发(策略、模块等)的过程中有任何疑问,请查看VeighNa项目文档,如果无法解决请前往官方社区论坛的【提问求助】板块寻求帮助,也欢迎在【经验分享】板块分享你的使用心得!

想要获取更多关于VeighNa的资讯信息? 请扫描下方二维码添加小助手加入【VeighNa社区交流微信群】:

功能特点

  1. 多功能量化交易平台(trader),整合了多种交易接口,并针对具体策略算法和功能开发提供了简洁易用的API,用于快速构建交易员所需的量化交易应用。

  2. 覆盖国内外所拥有的下述交易品种的交易接口(gateway):

    • 国内市场

      • CTP(ctp):国内期货、期权

      • CTP Mini(mini):国内期货、期权

      • CTP证券(sopt):ETF期权

      • 飞马(femas):国内期货

      • 恒生UFT(uft):国内期货、ETF期权

      • 易盛(esunny):国内期货、黄金TD

      • 顶点飞创(sec):ETF期权

      • 顶点HTS(hts):ETF期权

      • 中泰XTP(xtp):国内证券(A股)、ETF期权

      • 华鑫奇点(tora):国内证券(A股)、ETF期权

      • 国泰君安(hft):国内证券(A股、两融)

      • 东证OST(ost):国内证券(A股)

      • 东方财富EMT(emt):国内证券(A股)

      • 飞鼠(sgit):黄金TD、国内期货

      • 金仕达黄金(ksgold):黄金TD

      • 融航(rohon):期货资管

      • 杰宜斯(jees):期货资管

      • 中汇亿达(comstar):银行间市场

      • 掘金(gm):国内证券(仿真)

      • 恒生云UF(uf):国内证券(仿真)

      • TTS(tts):国内期货(仿真)

    • 海外市场

      • Interactive Brokers(ib):海外证券、期货、期权、贵金属等

      • 易盛9.0外盘(tap):海外期货

      • 直达期货(da):海外期货

    • 特殊应用

      • RQData行情(rqdata):跨市场(股票、指数、ETF、期货)实时行情

      • 迅投研行情(xt):跨市场(股票、指数、可转债、ETF、期货、期权)实时行情

      • RPC服务(rpc):跨进程通讯接口,用于分布式架构

  3. 覆盖下述各类量化策略的交易应用(app):

    • cta_strategy:CTA策略引擎模块,在保持易用性的同时,允许用户针对CTA类策略运行过程中委托的报撤行为进行细粒度控制(降低交易滑点、实现高频策略)

    • cta_backtester:CTA策略回测模块,无需使用Jupyter Notebook,直接使用图形界面进行策略回测分析、参数优化等相关工作

    • spread_trading:价差交易模块,支持自定义价差,实时计算价差行情和持仓,支持价差算法交易以及自动价差策略两种模式

    • option_master:期权交易模块,针对国内期权市场设计,支持多种期权定价模型、隐含波动率曲面计算、希腊值风险跟踪等功能

    • portfolio_strategy:组合策略模块,面向同时交易多合约的量化策略(Alpha、期权套利等),提供历史数据回测和实盘自动交易功能

    • algo_trading:算法交易模块,提供多种常用的智能交易算法:TWAP、Sniper、Iceberg、BestLimit等

    • script_trader:脚本策略模块,面向多标的类量化策略和计算任务设计,同时也可以在命令行中实现REPL指令形式的交易,不支持回测功能

    • paper_account:本地仿真模块,纯本地化实现的仿真模拟交易功能,基于交易接口获取的实时行情进行委托撮合,提供委托成交推送以及持仓记录

    • chart_wizard:K线图表模块,基于RQData数据服务(期货)或者交易接口获取历史数据,并结合Tick推送显示实时行情变化

    • portfolio_manager:交易组合管理模块,以独立的策略交易组合(子账户)为基础,提供委托成交记录管理、交易仓位自动跟踪以及每日盈亏实时统计功能

    • rpc_service:RPC服务模块,允许将某一进程启动为服务端,作为统一的行情和交易路由通道,允许多客户端同时连接,实现多进程分布式系统

    • data_manager:历史数据管理模块,通过树形目录查看数据库中已有的数据概况,选择任意时间段数据查看字段细节,支持CSV文件的数据导入和导出

    • data_recorder:行情记录模块,基于图形界面进行配置,根据需求实时录制Tick或者K线行情到数据库中,用于策略回测或者实盘初始化

    • excel_rtd:Excel RTD(Real Time Data)实时数据服务,基于pyxll模块实现在Excel中获取各类数据(行情、合约、持仓等)的实时推送更新

    • risk_manager:风险管理模块,提供包括交易流控、下单数量、活动委托、撤单总数等规则的统计和限制,有效实现前端风控功能

    • web_trader:Web服务模块,针对B-S架构需求设计,实现了提供主动函数调用(REST)和被动数据推送(Websocket)的Web服务器

  4. Python交易API接口封装(api),提供上述交易接口的底层对接实现。

    • REST Client(rest):基于协程异步IO的高性能REST API客户端,采用事件消息循环的编程模型,支持高并发实时交易请求发送

    • Websocket Client(websocket):基于协程异步IO的高性能Websocket API客户端,支持和REST Client共用事件循环并发运行

  5. 简洁易用的事件驱动引擎(event),作为事件驱动型交易程序的核心。

  6. 对接各类数据库的适配器接口(database):

    • SQL类

      • SQLite(sqlite):轻量级单文件数据库,无需安装和配置数据服务程序,VeighNa的默认选项,适合入门新手用户

      • MySQL(mysql):主流的开源关系型数据库,文档资料极为丰富,且可替换其他NewSQL兼容实现(如TiDB)

      • PostgreSQL(postgresql):特性更为丰富的开源关系型数据库,支持通过扩展插件来新增功能,只推荐熟手使用

    • NoSQL类

      • DolphinDB(dolphindb):一款高性能分布式时序数据库,适用于对速度要求极高的低延时或实时性任务

      • Arctic(arctic):高性能金融时序数据库,采用了分块化储存、LZ4压缩等性能优化方案,以实现时序数据的高效读写

      • TDengine(taos):分布式、高性能、支持SQL的时序数据库,带有内建的缓存、流式计算、数据订阅等系统功能,能大幅减少研发和运维的复杂度

      • TimescaleDB(timescaledb):基于PostgreSQL开发的一款时序数据库,以插件化扩展的形式安装,支持自动按空间和时间对数据进行分区

      • MongoDB(mongodb):基于分布式文件储存(bson格式)的文档式数据库,内置的热数据内存缓存提供更快读写速度

      • InfluxDB(influxdb):针对TimeSeries Data专门设计的时序数据库,列式数据储存提供极高的读写效率和外围分析应用

      • LevelDB(leveldb):由Google推出的高性能Key/Value数据库,基于LSM算法实现进程内存储引擎,支持数十亿级别的海量数据

  7. 对接下述各类数据服务的适配器接口(datafeed):

    • 迅投研(xt):股票、期货、期权、基金、债券

    • 米筐RQData(rqdata):股票、期货、期权、基金、债券、黄金TD

    • 恒生UData(udata):股票、期货、期权

    • TuShare(tushare):股票、期货、期权、基金

    • 万得Wind(wind):股票、期货、基金、债券

    • 天软Tinysoft(tinysoft):股票、期货、基金、债券

    • 同花顺iFinD(ifind):股票、期货、基金、债券

    • 天勤TQSDK(tqsdk):期货

  8. 跨进程通讯标准组件(rpc),用于实现分布式部署的复杂交易系统。

  9. Python高性能K线图表(chart),支持大数据量图表显示以及实时数据更新功能。

  10. 社区论坛知乎专栏,内容包括VeighNa项目的开发教程和Python在量化交易领域的应用研究等内容。

  11. 官方交流群262656087(QQ),管理严格(定期清除长期潜水的成员),入群费将捐赠给VeighNa社区基金。

注:以上关于功能特点的说明为根据说明文档发布时情况罗列,后续可能存在更新或调整。若功能描述同实际存在出入,欢迎通过Issue联系进行调整。

环境准备

  • 推荐使用VeighNa团队为量化交易专门打造的Python发行版VeighNa Studio-3.9.2,集成内置了VeighNa框架以及VeighNa Station量化管理平台,无需手动安装
  • 支持的系统版本:Windows 11以上 / Windows Server 2019以上 / Ubuntu 22.04 LTS以上
  • 支持的Python版本:Python 3.10以上(64位),推荐使用Python 3.10

安装步骤

这里下载Release发布版本,解压后运行以下命令安装:

Windows

install.bat

Ubuntu

bash install.sh

Macos

bash install_osx.sh

注意:setup.cfg中列举了VeighNa框架安装所需的依赖库,requirements.txt中给出了这些依赖库的推荐安装版本。

使用指南

  1. SimNow注册CTP仿真账号,并在该页面获取经纪商代码以及交易行情服务器地址。

  2. VeighNa社区论坛注册获得VeighNa Station账号密码(论坛账号密码即是)

  3. 启动VeighNa Station(安装VeighNa Studio后会在桌面自动创建快捷方式),输入上一步的账号密码登录

  4. 点击底部的VeighNa Trader按钮,开始你的交易!!!

注意:

  • 在VeighNa Trader的运行过程中请勿关闭VeighNa Station(会自动退出)

脚本运行

除了基于VeighNa Station的图形化启动方式外,也可以在任意目录下创建run.py,写入以下示例代码:

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 - 对于较大的改动(如新功能,大型重构等)建议先开issue讨论一下,较小的improvement(如文档改进,bugfix等)直接发PR即可

  2. Fork VeighNa - 点击右上角Fork按钮

  3. Clone你自己的fork: git clone https://github.com/$userid/vnpy.git

    • 如果你的fork已经过时,需要手动sync:同步方法
  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] - 在此点击compare across forks,选择需要的fork和branch创建PR

  7. 等待review, 需要继续改进,或者被Merge!

在提交代码的时候,请遵守以下规则,以提高代码质量:

  • 使用flake8检查你的代码,确保没有error和warning。在项目根目录下运行flake8即可。

其他内容

版权说明

MIT

vnpy_ctastrategy's People

Contributors

edanflame avatar gabrielvon avatar ieachen avatar lanceyliao avatar noranhe avatar playfund avatar pluspku avatar vnpy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vnpy_ctastrategy's Issues

load_strategy_class_from_folder不能识别linux目录下的策略文件

bug说明:pathname没有区分windows及linux/Mac OS,导致非linux环境下,不能找到strategies目录下的策略文件
修正:pathname需要区分是否为windows环境
示例:
import platform
platform_name: str = platform.system().lower()
if platform_name == 'windows':
pathname: str = str(path) + f"\.{suffix}"
else:
pathname: str = str(path) + f"/
.{suffix}"

回测停止单被错误触发

环境

  • 操作系统: Debian
  • Python版本: 3.10
  • VeighNa版本: V3.9.0

Issue类型

Bug

重现步骤

回测的时候,在用limit_order 开单成功后,在 on_trade() 里面新下一个止损的停止单。
这个停止单会被当前bar 触发成交,这是不合理的

问题分析

backtesting 的执行逻辑如下,cross_limit_order() 里面触发 on_trade(), 然后新发出一个止损的stop_order。
这个stop_order 会被下面的 cross_stop_order() 触发成交,当前bar 已经走完,这里触发成交是不合理的。

` def new_bar(self, bar: BarData) -> None:
""""""
self.bar = bar
self.datetime = bar.datetime

    self.cross_limit_order()
    self.cross_stop_order()
    self.strategy.on_bar(bar)

`

删除策略以后,只会删除cta_strategy_setting.json而不会删除cta_strategy_data.json里的数

strategy_engine.remove_strategy("xxxxx")
调用remove_strategy以后,只有cta_strategy_setting.json里的相应的数据被清理了,但是保存变量的cta_strategy_data.json里的数据没被清理。
这会导致下次如果新建一样名字的策略,会加载之前的数据。这是故意这么设计的吗?为什么呢
从语义来说,既然是删除了策略,就应该把保存的变量也清理干净,就像删除了文件,总不能创建新的同名文件还会残留之前老文件的内容吧?

论坛帖子URL:https://www.vnpy.com/forum/topic/31619-shan-chu-ce-lue-yi-hou-zhi-hui-shan-chu-cta-strategy-setting-jsoner-bu-hui-shan-chu-cta-strategy-data-jsonli-de-shu-ju

如果在子线程使用roll_over, 因为直接调用了 QTextEdit 的append函数,会报错。

子线程使用roll_over中进行移仓,因为直接调用了 QTextEdit 的append函数,这个时候就会出现下面的错误:
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)

代码:
def write_log(self, text: str) -> None:
""""""
now = datetime.now()
text = now.strftime("%H:%M:%S\t") + text
self.log_edit.append(text)

修改使用定义信号,改为信号槽
log_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(str)

    def __init__
    ...
    self.log_signal.connect(self.log_txt_append)
    ...

def write_log(self, text: str) -> None:
	""""""
	now = datetime.now()
	text = now.strftime("%H:%M:%S\t") + text
	self.main_engine.write_log(text)
	self.log_signal.emit(text)

def log_txt_append(self,text):
	self.log_edit.append(text)
	self.log_edit.moveCursor(QtGui.QTextCursor.End)

callback(data)重复调用

应该把backtesting.py在load_bar函数下的callback调用加回来,把template下load_bar函数下的callback调用删掉(导致elite版本重复调用)

bug: array mananger 计算 bollingerbands

一个在特定数据场景下出现的 am.boll 计算的错误,这个 bug 应该是 talib 的,代码如下所示:

import numpy as np
import talib as ta

close = np.array([
    0.06357,0.06359,0.06369,0.06356,0.06364,0.06358,0.06354,0.06345,0.0634,
    0.06345,0.0634 ,0.06346,0.06345,0.06372,0.06349,0.06378,0.06375,0.06381,
    0.06377,0.06364,0.06377,0.06361,0.06365,0.06379,0.06385,0.06381,0.06371,
    0.0637 ,0.06369,0.06369,0.06369,0.0638 ,0.06396,0.06392,0.06389,0.06382,
    0.06395,0.06393,0.064  ,0.06394,0.06387,0.0638 ,0.06385,0.06391,0.06389,
    0.06392,0.06395,0.06392,0.064  ,0.064  ,0.06411,0.06408,0.06405,0.06408,
    0.06403,0.06403,0.064  ,0.06401,0.06395,0.06395
])

sma = ta.SMA(close, 30)[-1]
std = ta.STDDEV(close, 30, 1)[-1]

up = sma + 2.8 * std
down = sma - 2.8 * std

print("原有方式:", sma, std, up, down)

bbands = ta.BBANDS(close, 30, 2.8, 2.8)
print("自带的 bbands:", bbands[0][-1], bbands[2][-1])

std = close[-30:].std()
up = sma + 2.8 * std
down = sma - 2.8 * std

print("使用 np 计算 std:", sma, std, up, down)

输出如下:

原有方式: 0.06394333333333334 0.0 0.06394333333333334 0.06394333333333334
自带的 bbands: 0.06394333333333334 0.06394333333333334
使用 np 计算 std: 0.06394333333333334 9.17363371601224e-05 0.06420019507738169 0.06368647158928499

talib 的 STDDEV 计算的标准差不知道为什么在这个数据集的计算结果为 0,估计要看 talib 源码了,但是 github 上没有找到,建议换成 numpy 的 std 计算标准。

不想引入其他技术指标库了,写了一个完全用 numpy 实现的 bollinger bands。

如下代码:

import numpy as np
from numpy.lib.stride_tricks import sliding_window_view as rolling

def boll(source, window, ndev, array=False):
    rolling_source = rolling(source, window_shape=window)

    sma: np.ndarray = rolling_source.mean(axis=1)
    std: np.ndarray = rolling_source.std(axis=1)

    up: np.ndarray = sma + ndev * std
    down: np.ndarray = sma - ndev * std

    if array:
        return up, down
    return up[-1], down[-1]

在返回成交信息很多时候,sync_strategy_data写入卡住

在ctaEngine 中 的process_trade_event,如在开盘时候挂单成交策略较多,挂单成交信息返回较多且散时,其中的sync_strategy_data 写入variables到json文件会卡住,没有报错信息,但是有策略没有更新,虽然内存中pos持仓正确,如果突然重启发现variables错误。

可以考虑使用更新到数据库,有缓冲机制;或者thread写入json file使用单独线程

callback(bar) 重复调用

https://github.com/vnpy/vnpy_ctastrategy/blob/main/vnpy_ctastrategy/backtesting.py#L789

重复调用 callback(bar) 导致重复调用on_bar
vnpy_ctastrategy/template.py

    def load_bar(
        self,
        days: int,
        interval: Interval = Interval.MINUTE,
        callback: Callable = None,
        use_database: bool = False
    ) -> None:

        if not callback:
            callback: Callable = self.on_bar

        bars: List[BarData] = self.cta_engine.load_bar(
            self.vt_symbol,
            days,
            interval,
            callback,
            use_database
        )

        for bar in bars:
            callback(bar)

vnpy_ctastrategy/backtesting.py

    def load_bar(
        self,
        vt_symbol: str,
        days: int,
        interval: Interval,
        callback: Callable,
        use_database: bool
    ) -> List[BarData]:
        """"""
        self.callback = callback

        init_end = self.start - INTERVAL_DELTA_MAP[interval]
        init_start = self.start - timedelta(days=days)

        symbol, exchange = extract_vt_symbol(vt_symbol)

        bars: List[BarData] = load_bar_data(
            symbol,
            exchange,
            interval,
            init_start,
            init_end
        )

        for bar in bars:
            callback(bar)

        return bars

回测成交为空报错

建议在backtesting.py中的calculate_result函数下进行results判断,没有results就输出日志,有results再给self.daily_df赋值

可变对象在类实例化时不会重复创建,但单策略运行在多品种时需要对同一个类进行多次实例化,如何修改或避免?

parameters: list = []

在Python中,可变对象在类实例化时不会重复创建,这意味着它们在类的多次实例化中是共享的。这与不可变对象(如整数、字符串等)的行为不同,不可变对象在每次实例化时都会创建一个新的对象。

以下是一个简单的例子,说明了可变对象在类实例化中的共享特性:

class MutableObject:
    shared_list = []

    def add_item(self, item):
        self.shared_list.append(item)

# 实例化两个对象
obj1 = MutableObject()
obj2 = MutableObject()

# 在第一个对象上添加一个元素
obj1.add_item(1)

# 第二个对象也会受到影响,因为它们共享同一个可变对象
print(obj2.shared_list)  # 输出 [1]

在这个例子中,shared_list 是一个可变的类级别属性。当我们在 obj1 上添加一个元素时,shared_list 发生了变化,而 obj2 也受到了影响,因为它们都共享同一个列表对象。

这种共享特性对于某些用途可能是有用的,但在某些情况下,它也可能导致上述提到的问题,如内存占用过高、重复初始化和对象状态混乱。因此,在设计类时,我们需要注意对象的可变性,并确保适当地使用可变和不可变对象,以避免潜在的问题。

文件template中,函数sell和cover注释代码不一致

bug说明:在文件template.py中
函数sell中
注释:Send sell order to close a long position.
代码:return self.send_order(
Direction.SHORT,
Offset.CLOSE,
price,
volume,
stop,
lock,
net
)
修改:这里的Direction.SHORT是不是应该改成Direction.LONG?
函数cover中
注释:Send cover order to close a short position.
代码:return self.send_order(
Direction.LONG,
Offset.CLOSE,
price,
volume,
stop,
lock,
net
)
修改:同上,这里Direction.LONG是不是应该改成Direction.SHORT?

需要一个“查找策略”或者“定位策略”的按钮

在左侧面板中,现在只有“添加策略”一个按钮。最好有一个“查找策略”或者“定位策略”的按钮,能通过策略的名字或者关键字,快速查找或者定位到某个具体的策略,这样使用者就可以继续对该策略做停止或者参数修改的动作了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.