一、前言
在量化研究中,快速生成因子并持续维护因子数据是基础环境的关键。相比于使用Python调用数据计算,我们推荐使用简单高效的VBA语法来维护和生成因子。它有3大优点:
优点1:VBA语言简洁高效,无需处理数据对齐和数据类型;
优点2:生成的数据可以同步展示在界面端,便于获取截面和时序数据;
优点3:自由度高,因子完全在本地进行生成,充分利用电脑性能。
操作步骤如下:
1.使用VBA语句编写所需的因子公式,以MACD、KDJ指标为示例。
2.使用Python文件进行统一调度运行因子计算。
3.通过界面或策略函数调用因子值。
二、具体操作指引:
1.在系统中利用VBA语法编写经典的MACD和KDJ因子,可根据实际情况修改参数。(详见代码)
macd
s:= 12;
p:= 26;
m:= 9;
DIF: EMA(C,s) - EMA(C,p);
DEA: EMA(DIF,m);
MACD:DIF - DEA;
kdj
input : n(9, 1, 100, 10), p1(3, 2, 40,4), p2(3,2,40,4);
RSV:IF((HHV(HIGH,N)-LLV(LOW,N)),(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100,0);
K:SMA(RSV,P1,1);
D:SMA(K,P2,1);
J:3*K-2*D
2.通过Python脚本实现统一调度。(详见代码)
#coding:gbk
import traceback
import time
def after_init(C):
#扩展数据
#字典格式 extend_data_dict vba模型名称 : 其中的指标名列表
extend_data_dict = {'atr': ['atr'],'macd':['macd'],'kdj':['k','d','j']}
hsa = C.get_stock_list_in_sector('沪深A股')
hsa_market_first = [stock[-2:] + stock[:-3] for stock in hsa]
#basket = {i[-2:]+ i[:6] : 1 for i in hsa}
total, count = sum([len(v) for k,v in extend_data_dict.items()]), 0
failed_list = []
for extend_name in extend_data_dict:
_data = extend_data_dict[extend_name]
try:
t0 = time.time()
data_list = call_formula([extend_name], hsa ,'1d', 'front_ratio', {}, [],"20140101","",-1)
print(f"{extend_name} {_data} 调用vba耗时 ", time.time() - t0)
_t = time.time()
#按股票品种 取出结果
for key in extend_data_dict[extend_name]:
result_dict = {}
# print(x)
for d in data_list:
stock = d['stock']
result = d['result']
result = {i : result[i][key] for i in result}
result_dict[stock] = result
extend_dict = {}
for stock in result_dict:
code = stock[-2:] + stock[:-3]
for date in result_dict[stock]:
#时间字符串 转为毫秒时间戳
t = int(time.mktime(time.strptime(date,'%Y%m%d')) *1000)
if t not in extend_dict:
extend_dict[t] = {}
extend_dict[t][code] = result_dict[stock][date]
print('转换用时', time.time() - _t)
# print(222222, extend_name, extend_name in extend_data_dict)
name = create_extend_data('扩展数据', key, True)
reset_extend_data_stock_list(key, hsa_market_first)
set_extend_data(name, extend_dict)
count += 1
print(f"{key} 保存扩展数据 总用时 {time.time() - t0}秒 进度 {count} / {total} ")
except:
print(traceback.format_exc())
print(f"{extend_name} 扩展数据 生成失败")
failed_list.append(extend[1])
#外部数据
#数据#datas = {timetag : value} 时间戳与扩展数据相同 为毫秒级的
datas = {1579881600000 : 25, 1579968000000 : 26, 1580054400000 : 27}
#生成外部数据
#参数依次为(父节点, 名称, 周期, 数据集, 是否覆盖)
#周期是对应秒数 日线为86400000 五分钟 300 一分钟 60
ext_name = create_external_data('单值数据', '测试扩展数据名称', 86400000, datas, False)
print('生成完成 外部数据名称', ext_name)
3.回测时使用因子值。(详见代码)
# coding:gbk
def init(C):
C.stock_list = get_stock_list_in_sector("沪深A股")
# 以上面生成后的MACD指标值为例
def handlebar(C):
_time = timetag_to_datetime(C.get_bar_timetag(C.barpos), "%Y%m%d")
for i in C.stock_list:
MACD = ext_data('macd',i,0,C)
print(_time,f"MACD -- {i}:{MACD}")

4.在界面端查看历史截面因子数据(示例图)

投研端导入外部数据进行展示
若本地已有计算好的因子值或外部行情源,投研端支持对接展示。以下示例展示将外部数据导入到投研端,并在界面展示的过程。(详见代码)
#coding:gbk
import traceback
import time
def after_init(C):
#外部数据
#数据#datas = {timetag : value} 时间戳与扩展数据相同 为毫秒级的
datas = {1579881600000 : 25, 1579968000000 : 26, 1580054400000 : 27}
#生成外部数据
#参数依次为(父节点, 名称, 周期, 数据集, 是否覆盖)
#周期是对应秒数 日线为86400000 五分钟 300 一分钟 60
ext_name = create_external_data('单值数据', '测试扩展数据名称', 86400000, datas, False)
print('生成完成 外部数据名称', ext_name)
运行这段代码后,我们可以在 扩展 - 外部数据 - 单值数据
中找到生成的数据图像

一起来试试打造自己的因子库吧!投资无秘密,全靠执行力!
不清楚的内容可添加下方助理微信咨询,有其他 QMT 小技巧想学习的吗?欢迎在下方留言,笔者将根据大家的留言持续更新哦!
欢迎和我一起加入迅投组建的 QMT 实战交流社群,交流群内有许多做量化交易的高手和大佬,具有良好的分享和互助氛围。且迅投官方会不定期为多次分享、乐于助人的群友申请送投研专业版的机会。
只需扫描下方的二维码,名额有限,限时加入。一起分享见解、交换信息、并共同进步,就像群友说的:“就算周末,晚上也有地方沟通交流!”
