返回列表 发布新帖

场景_如何用Python回测时获取vba指标?(支持内置/原生Py,并行计算速度提升10-100倍)

3615 6
发表于 2024-4-8 15:24:58 | 显示全部楼层 阅读模式

问题

<span style="color:#FF0000;">大家常常在问,有些函数python没有,但vba有(先建一个vba公式使用这个函数,再用py去调这个公式的变量),或者py单线程计算速度慢,怎么把计算机多核资源用满提升速度,那就用 python 实时调用 vba 指标,在投研软件里面,调用一个接口就能解决:

# 内置Python
# 初始化传入参数
g_context['stocks'] = ['000001.SZ']  
g_context['formula_name'] = 'MA'  # 指标名称
g_context['period'] = '1d'  
g_context['start_time'] = '20230320'  # %Y%m%d 或%Y%m%d%H%M%S
g_context['end_time'] = ''  # %Y%m%d 或%Y%m%d%H%M%S
g_context['count'] = -1  
g_context['dividend_type'] = 'back'  # 复权方式

for s in g_context['stocks']:  
            formula_results = call_formula(  
                g_context['formula_name'],  
                s,  
                period=g_context['period'],  
                start_time=g_context['start_time'],  
                end_time=g_context['end_time'],  
                count=g_context['count'],  
                dividend_type=g_context['dividend_type']  
            )


# 原生Python
# 初始化传入参数
stocks = ['000001.SZ']
formula_name  = 'MA'  # 指标名称
period        = '1d' 
start_time    = '20230320'    # %Y%m%d 或%Y%m%d%H%M%S
end_time      = ''    # %Y%m%d 或%Y%m%d%H%M%S
count         = -1
dividend_type ='back' # 复权方式

for s in stocks:
    formula_results = xtdata.call_formula(
                              formula_name,
                              s,
                              period=period,
                              start_time=start_time,
                              end_time=end_time,
                              count=count,
                              dividend_type=dividend_type
             )

而这里的 formula_name (指标名称)可以改成任何希望获取的指标,同样 start_timeend_time 的选择也取决于需求。

解答

内置Python

image.png

# coding:gbk

'''
内置python,调用技术指标
'''

g_context = {
    'stocks': [],
    'formula_name': '',
    'period': '',
    'start_time': '',
    'end_time': '',
    'count': 0,
    'dividend_type': ''
}

def init(C):
    g_context['stocks'] = ['000001.SZ']
    g_context['formula_name'] = 'MA'  # 指标名称
    g_context['period'] = '1d'
    g_context['start_time'] = '20230320'  # %Y%m%d 或%Y%m%d%H%M%S
    g_context['end_time'] = ''  # %Y%m%d 或%Y%m%d%H%M%S
    g_context['count'] = -1
    g_context['dividend_type'] = 'back'  # 复权方式
    return

def after_init(C):
    for s in g_context['stocks']:
        # 订阅后,call_formula可以获取到盘中动态结果
        id = C.subscribe_quote(s, g_context['period'], '', '', -1)
    while 1:
        for s in g_context['stocks']:
            formula_results = call_formula(
                g_context['formula_name'],
                s,
                period=g_context['period'],
                start_time=g_context['start_time'],
                end_time=g_context['end_time'],
                count=g_context['count'],
                dividend_type=g_context['dividend_type']
            )
            for k in formula_results['outputs']:
                print(s, k, formula_results['outputs'][k][-5:])
        time.sleep(3)
    return

def handlebar(C):
    return

返回结果

000001.SZ ma1 [1778.1509890467864, 1785.2430974660224, 1783.7655748786815, 1781.6970432564044, 1779.9240161515959]
000001.SZ ma2 [1773.4229167672934, 1774.900439354634, 1777.1167232356452, 1777.2644754943794, 1776.673466459443]
000001.SZ ma3 [1768.1038354528669, 1770.393995463245, 1771.2805090156494, 1772.240898697421, 1772.6102793442562]
000001.SZ ma4 [1687.1602230430458, 1690.0906428412716, 1692.9471865101305, 1696.0253585670905, 1699.0542798711392]

原生Python

image.png

'''
原生python,调用技术指标
'''
from xtquant import xtdata
xtdata.connect(port=58622)
stocks = ['000001.SZ']
formula_name  = 'MA'  # 指标名称
period        = '1d' 
start_time    = '20230320'    # %Y%m%d 或%Y%m%d%H%M%S
end_time      = ''    # %Y%m%d 或%Y%m%d%H%M%S
count         = -1
dividend_type ='back' # 复权方式

import time
for s in stocks:
    # 订阅后,call_formula可以获取到盘中动态结果
    id = xtdata.subscribe_quote(s, period, '', '', -1)
while 1:
    for s in stocks:
        formula_results = xtdata.call_formula(
                                formula_name,
                                s,
                                period=period,
                                start_time=start_time,
                                end_time=end_time,
                                count=count,
                                dividend_type=dividend_type
                            )
        for k in formula_results['outputs']:
            print(s, k, formula_results['outputs'][k][-5:])

    time.sleep(3)

返回结果

000001.SZ ma1 [1778.1509890467864, 1785.2430974660224, 1783.7655748786815, 1781.6970432564044, 1779.9240161515959]
000001.SZ ma2 [1773.4229167672934, 1774.900439354634, 1777.1167232356452, 1777.2644754943794, 1776.673466459443]
000001.SZ ma3 [1768.1038354528669, 1770.393995463245, 1771.2805090156494, 1772.240898697421, 1772.6102793442562]
000001.SZ ma4 [1687.1602230430458, 1690.0906428412716, 1692.9471865101305, 1696.0253585670905, 1699.0542798711392]

传递参数 extend_param

更高阶的应用,就是我们给指标设置了相应的参数之后,如何在调用的时候,把我们想要的参数传进去呢?

image.png

我们需要分别做两个设置:

1、在指标的参数选项中,设置你要的变量和对应的值,比如我这里设置的参数名是 s,参数值是 沪深300

2、接下来,在你的 call_formula 函数中,参数 extend_param 可以以字典的形式,一一对应设置你想要的参数,它就会把参数传入到指标对应参数名的地方

3、 这里你要确保指标名字写准确,同时 stock_code 是你要跑的主图代码,比如计算板块涨跌幅,我们尽量用指数作为主图,确保时间长度足够

具体代码如下:

from xtquant import xtdata
# import pandas as pd

stock = '000300.SH'

formula_results = xtdata.call_formula(
    formula_name='板块走势中国2023', stock_code=stock, period='1d'
    , start_time='', end_time='', count=-1
    , dividend_type='front_ratio'
    , extend_param={'s': '沪深300'})

# print(formula_results['outputs'].keys())
# exit()

outputs = formula_results['outputs']
x, y, z = outputs['单边'], outputs['超额500'], outputs['dbdt']
dates = formula_results['timelist']
dates = [xtdata.timetag_to_datetime(t, '%Y%m%d') for t in dates]
df = pd.DataFrame({
    'stock': [stock] * len(x),
    'date': dates,
    '单边': x,
    '超额500': y,
    'dbdt': z
})

print(df.tail())

$\color{red}{tips:}$

1.调用 call_formula 接口前不要忘记先调用一次 subscribe_quote 接口订阅,这样可以获取到盘中动态的结果。 2. 在示例中,程序用了 while 1 的死循环,需要在终端敲击 CTRL + C 或是手动终止程序。 3. 原生Python调用 call_formula 接口时,不能使用 token 连接。需要直接连接投研客户端,方法如下:

1. 在投研软件内,设置-模型设置里可以改投研监听的端口
2. from xtquant import xtdata
   xtdata.connect(port=58622)    # 在第一步中设置的端口号

不清楚的内容可添加下方助理微信咨询,有其他 QMT 小技巧想学习的吗?欢迎在下方留言,笔者将根据大家的留言持续更新哦!

欢迎和我一起加入迅投组建的 QMT 实战交流社群,交流群内有许多做量化交易的高手和大佬,具有良好的分享和互助氛围。且迅投官方会不定期为多次分享、乐于助人的群友申请送投研专业版的机会。

只需扫描下方的二维码,名额有限,限时加入。一起分享见解、交换信息、并共同进步,就像群友说的:“就算周末,晚上也有地方沟通交流!”

企业微信截图_17235220909173.png

评论6

心如止水
发表于 2024-4-9 13:39:04 | 显示全部楼层
还有其他想学习的 QMT 小技巧吗?欢迎大家在下方留言,版主将根据大家的留言持续更新哦!没有进群的伙伴们记得添加迅投微信,实时交流
*******1285
发表于 2024-4-9 21:57:11 | 显示全部楼层
bdeba8cc87978748238f83df63be16f.png
这个函数只能在投研端用?可以在原生python中用吗?
柯昌林
发表于 2024-4-10 09:21:22 | 显示全部楼层
原生Python中,第17行写的是subscribe_quote,这里不应该是subscribe_formula 吗? 写成subscribe_quote 也可以?
*******9017楼主
发表于 2024-4-10 17:23:19 | 显示全部楼层
柯昌林 发表于 2024-4-10 09:21
原生Python中,第17行写的是subscribe_quote,这里不应该是subscribe_formula 吗? 写成subscribe_quote 也 ...

首先,原生python代码片段中的第17行调用的是call_formula接口,利用这个接口调用了技术指标。

然后,如果你指的是第14行中的subscribe_quote接口的话,这个接口只是提供了订阅的功能,在调用了subscribe_quote接口订阅后,我们的call_formula接口就可以获取到盘中动态结果。

最后,你提到的subscribe_formula接口是另外一个与call_formula接口类似的接口,在这个帖子中没有出现,所以subscribe_formula 和 subscribe_quote这两个接口名称并不可以互相替换。
*******9017楼主
发表于 2024-4-10 17:41:28 | 显示全部楼层
*******1285 发表于 2024-4-9 21:57
这个函数只能在投研端用?可以在原生python中用吗?

只能在内置中使用
柯昌林
发表于 2024-4-10 21:29:39 | 显示全部楼层
:handshake

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2025 迅投QMT社区 版权所有 All Rights Reserved. 蜀ICP备19002686号-2
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表