Quantlab 4.1:基于Deap遗传算法多股票因子挖掘

原创文章第549篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。

遗传算法本身并不复杂,但gplearn的实现,把问题复杂化了,尤其在因子挖掘这个场景。

使用deap进行因子挖掘的代码在如下位置:

图片

import copy

from deap_patch import *  # noqa
from deap import base, creator, gp
from deap import tools
from datafeed.mining.deap_alpha.add_ops import *

def convert_inverse_prim(prim, args):
    """
    Convert inverse prims according to:
    [Dd]iv(a,b) -> Mul[a, 1/b]
    [Ss]ub(a,b) -> Add[a, -b]
    We achieve this by overwriting the corresponding format method of the sub and div prim.
    """
    prim = copy.copy(prim)

    converter = {
        'Add': lambda *args_: "{}+{}".format(*args_),
        'Mul': lambda *args_: "{}*{}".format(*args_),
        'fsub': lambda *args_: "{}-{})".format(*args_),
        'fdiv': lambda *args_: "{}*Pow({}, -1))".format(*args_),
        'fmul': lambda *args_: "{}*{}".format(*args_),
        'fadd': lambda *args_: "{}+{}".format(*args_),
        'fmax': lambda *args_: "max_({},{})".format(*args_),
        'fmin': lambda *args_: "min_({},{})".format(*args_),

        'isub': lambda *args_: "{}-{}".format(*args_),
        'idiv': lambda *args_: "{}/{}".format(*args_),
        'imul': lambda *args_: "{}*{}".format(*args_),
        'iadd': lambda *args_: "{}+{}".format(*args_),
        'imax': lambda *args_: "max_({},{})".format(*args_),
        'imin': lambda *args_: "min_({},{})".format(*args_),
    }

    #print(prim.name)
    #if prim.name == "imul":
        #print('命中:',prim.name)
        #print(prim)
    prim_formatter = converter.get(prim.name, prim.format)

    return prim_formatter(*args)

def stringify_for_sympy(f):
    """Return the expression in a human readable string.
    """
    string = ""
    stack = []
    for node in f:
        stack.append((node, []))
        while len(stack[-1][1]) == stack[-1][0].arity:
            prim, args = stack.pop()
            string = convert_inverse_prim(prim, args)
            if len(stack) == 0:
                break  # If stack is empty, all nodes should have been seen
            stack[-1][1].append(string)
    print(string)
    return string

def map_exprs(evaluate, invalid_ind, gen, label, split_date):
    #print(invalid_ind)
    sources = [f'GP_{i:04d}={stringify_for_sympy(expr)}' for i, expr in enumerate(invalid_ind)]
    print(sources)


def init_pset():
    pset = gp.PrimitiveSetTyped("MAIN", [], RET_TYPE)
    pset = add_constants(pset)
    pset = add_operators(pset)
    pset = add_factors(pset)
    return pset

def init_creator():
    # 可支持多目标优化
    # TODO 必须元组,1表示找最大值,-1表示找最小值
    FITNESS_WEIGHTS = (1.0, 1.0)
    creator.create("FitnessMulti", base.Fitness, weights=FITNESS_WEIGHTS)
    creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMulti)
    return creator

def init_toolbox(creator):
    toolbox = base.Toolbox()
    pset = init_pset()
    toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=2, max_=5)
    toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)
    toolbox.register("evaluate", print)  # 不单独做评估了,在map中一并做了

    from datetime import datetime
    dt1 = datetime(2021, 1, 1)
    LABEL_y = 'RETURN_OO_1'
    from itertools import count
    toolbox.register('map', map_exprs, gen=count(), label=LABEL_y, split_date=dt1)

    return toolbox

if __name__ == '__main__':
    random.seed(9527)
    creator = init_creator()
    toolbox = init_toolbox(creator)
    pop = toolbox.population(n=100)
    fitnesses = toolbox.map(toolbox.evaluate, pop)

重点看add_ops添加咱们自己的因子表达式引擎支持的函数:

# TODO: 请在此文件中添加算子和因子
# TODO: 由于部分算子计算过慢,这里临时屏蔽了
import random


class RET_TYPE:
    # 是什么不重要
    # 只要addPrimitive中in_types, ret_type 与 PrimitiveSetTyped("MAIN", [], ret_type)中
    # 这三种type对应即可
    pass


# 改个名,因为从polars_ta中默认提取的annotation是Expr
# TODO 如果用使用其它库,这里可能要修改
Expr = RET_TYPE


def _random_int_():
    return random.choice([1, 3, 5, 10, 20, 40, 60])


def add_constants(pset):
    """添加常量"""
    # !!! 名字一定不能与其它名字重,上次与int一样,结果其它地方报错 [<class 'deap.gp.random_int'>]
    pset.addEphemeralConstant('_random_int_', _random_int_, int)
    return pset


def add_operators_base(pset):
    """基础算子"""
    # 无法给一个算子定义多种类型,只好定义多个不同名算子,之后通过helper.py中的convert_inverse_prim修正
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fadd')
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fsub')
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fmul')
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fdiv')
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fmax')
    pset.addPrimitive(dummy, [Expr, Expr], Expr, name='fmin')

    pset.addPrimitive(dummy, [Expr, int], Expr, name='iadd')
    pset.addPrimitive(dummy, [Expr, int], Expr, name='isub')
    pset.addPrimitive(dummy, [Expr, int], Expr, name='imul')
    pset.addPrimitive(dummy, [Expr, int], Expr, name='idiv')

    return pset


def add_unary_ops(pset):
    from datafeed.expr_functions import unary_funcs
    for func in unary_funcs:
        pset.addPrimitive(dummy, [Expr], Expr, name=func)


def add_unary_rolling_ops(pset):
    from datafeed.expr_functions import unary_rolling_funcs
    for func in unary_rolling_funcs:
        pset.addPrimitive(dummy, [Expr, int], Expr, name=func)


def add_binary_ops(pset):
    from datafeed.expr_functions import binary_funcs
    for func in binary_funcs:
        pset.addPrimitive(dummy, [Expr, Expr], Expr, name=func)


def add_binary_rolling_ops(pset):
    from datafeed.expr_functions import binary_roilling_funcs
    for func in binary_roilling_funcs:
        pset.addPrimitive(dummy, [Expr, Expr, int], Expr, name=func)


def add_operators(pset):
    """添加算子"""
    pset = add_operators_base(pset)
    add_unary_ops(pset)
    add_binary_ops(pset)
    add_unary_rolling_ops(pset)
    add_binary_rolling_ops(pset)
    return pset


def add_factors(pset):
    pset.addTerminal(1, Expr, name='OPEN')
    pset.addTerminal(1, Expr, name='HIGH')
    pset.addTerminal(1, Expr, name='LOW')
    pset.addTerminal(1, Expr, name='CLOSE')
    pset.addTerminal(1, Expr, name='VOLUME')
    # pset.addTerminal(1, Expr, name='AMOUNT')

    return pset


def dummy(*args):
    # 由于生成后的表达计算已经被map和evaluate接管,所以这里并没有用到,可随便定义
    print('dummy')
    return 1

生成的因子,直接转化为咱们因子表达式可以兼容的表达式:

可以计算出因子值:

图片

明天继续对因子做ic分析,同时进行遗传算法的迭代。

代码每周五在星球更新,本周重点是deap+quantlab的因子表达式做因子挖掘。

AI量化实验室——2024量化投资的星辰大海

吾日三省吾身

听樊登讲雷殿生的《信念》。

他是世界徒步最远的人;十年风雨行,他先后走掉了19个脚趾甲,穿烂了52双鞋,行走八万一千多公里,经历19次抢劫,40多次野兽出没。他被评选为“首届中国十大徒步人物”,被誉为“当代徐霞客” 。

探险家,十年徒步走遍全中国。八万多公里,有涉及沙漠,无人区。

遇过十几次抢劫,狼群,吃过苍蝇,老鼠。。。

听完这些,首先是震撼,人之潜力无限。

然后,不自觉会开始探讨意义。

有人问珠峰攀登者,为什么要去冒险,答:因为它就在那里!

这里会回归到生命的本质与意义的问题。

生命没有意义,什么权情名利,百年之后都是过眼云烟。

生命是一场体验罢了,既然如此,体验某种程度是就是“折腾”。——但不是无意义,没有目标感的折腾,而是带着使命感、仪式感去努力做成一件事。

他受徐霞客启发和激励,花了十年时间做准备,然后花十年时间完成这一壮举。

普通人无法企及,只能仰慕。

于我们,有太多的负担,不允许我们去冒险,甚至“不允许”我们离开工作。

生活还在生存,这是一个问题。

但是人生真的具有无限潜力、惊喜。

无论生在何方,反正只来这么一趟,不要轻易就这么过去了。——无论你情不情愿,都会过去。

愿每个人都能跳出日常的琐碎,找到内心的信念,那个方向感,那个有召唤感的使命。

你若盛开,蝴蝶自来。

deap:多股票多维度遗传算法因子挖掘,可以整合chatGPT。

Quantlab4.1发布 | 新增一些策略,补充Metrics

AI量化实验室——2024量化投资的星辰大海

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/677523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JDBC 学习笔记(一)基础篇 - JDBC 搭建的六大步骤

JDK 版本使用&#xff1a;JDK 21 框架思想&#xff1a;实体类及ORM思想 反射技术&#xff1a;BaseDAO 封装的过程 解决现有问题的角度&#xff0c;主要是 JDBC的基础应用 一、、JDBC 可以解决的问题 1.1 数据存储的问题 解决数据长期的存储问题&#xff1a; 数据通过 I/O 流…

24.Labview移位寄存器的使用及数据流解析

本文讲解移位寄存器的常用场景及其数据流的方向解析。 在Labview中移位寄存器是存在于循环结构中的&#xff0c;也就是说for循环和while循环中&#xff0c;在了解移位寄存器之前首先要了解一下for循环和while循环的原理及其数据流的流动方向&#xff0c;题主之前讲过for循环的文…

使用python绘制华夫饼图

使用python绘制华夫饼图 华夫饼图效果代码 华夫饼图 华夫饼图&#xff08;Waffle Chart&#xff09;是一种数据可视化图表&#xff0c;用于显示数据在一个网格中的分布情况。它类似于饼图&#xff0c;通过将数据划分为等大小的方块来表示不同类别的比例。华夫饼图的优势在于它…

国联易安:网络反不正当竞争,要防患于未然

据市场监管总局官网消息&#xff0c;为预防和制止网络不正当竞争&#xff0c;维护公平竞争的市场秩序&#xff0c;鼓励创新&#xff0c;保护经营者和消费者的合法权益&#xff0c;促进数字经济规范健康持续发展&#xff0c;市场监管总局近日发布《网络反不正当竞争暂行规定》&a…

I2C通信协议

I2C通信协议 项目要求是&#xff0c;通过通信线&#xff0c;是实现单片机读写外挂模块寄存器的功能&#xff0c;至少实现&#xff0c;在指定位置写寄存器和在指定位置读寄存器&#xff0c;实现了读写寄存器&#xff0c;就实现对模块的控制。 MPU6050&#xff0c;OLED&#xf…

第六篇 移位寄存器

实验六 移位寄存器 6.1实验目的 掌握移位寄存器的工作原理&#xff1b; 掌握利用移位寄存器实现串行与并行的相互转换&#xff1b; 掌握使用移位寄存器实现乘除法运算&#xff1b; 6.2 原理介绍 6.2.1 基本移位寄存器 在实验四中&#xff0c;我们主要介绍了寄存器的结构…

QGIS 根据点图层上的点 画线生成线图层

使用节点捕捉功能 空白处鼠标右键---》勾选捕捉工具栏----》选中磁铁工具 创建线图层---》编辑模式---》点击新增线工具--》鼠标靠近点&#xff0c;会有高亮提醒&#xff0c;左键选中&#xff0c;右键结束当前线段绘制

千帆 AppBuilder 工作流编排功能直播总结

千帆 AppBuilder 工作流编排功能直播总结 ​ 上个月&#xff0c;千帆AppBuilder推出了一项引人瞩目的新功能——工作流编排。在官方直播中&#xff0c;百度产品经理不仅深入介绍了这项功能&#xff0c;而且还通过创建多个组件&#xff0c;生动展示了AppBuilder组件工作流的强大…

网络工程师---第四十六天

1、逻辑网络结构设计阶段中&#xff0c;要想实现核心层与汇聚层交换机全部互相连接&#xff0c;组网技术有哪些&#xff1f; 2、工作区子系统的通信布线规范有哪些&#xff1f; 3、综合布线中施工规范有哪些&#xff1f; 4、综合布线系统中核心机房通常包括哪些设备&#xff1f…

API商品数据接口(电商数据api)返回京东淘宝商品详情数据提高开发效率

众多品牌选择使用比价工具进行采购&#xff0c;主要是出于以下几个重要原因&#xff1a; 提高开发效率&#xff1a;电商数据采集API接口允许不同的应用程序之间高效地进行交互&#xff0c;节省了大量的人力物力成本&#xff0c;使得开发者可以将更多时间和精力集中于自身的核心…

分库分表方案

文章目录 分库分表设计思路hash取模和范围方案最终方案采用hash取模和rang范围两者相结合 分库分表设计思路 首先分库分表有两种方式&#xff0c;一种是垂直拆分&#xff0c;一种是水平拆分。 垂直拆分 垂直拆分比较简单&#xff0c;也就是本来一个数据库&#xff0c;数据量大…

小红书前端2轮面试期望22K,全程问低代码设计

一面&#xff08;通过&#xff09; 1、好&#xff0c;那我们开始把&#xff0c;先简单介绍一下自己的一个经历&#xff0c;以及自己有亮点的项目&#xff1f;balabala 2、你可以这样介绍&#xff1a;在这里边主要负责哪几个项目&#xff0c;哪些项目是比较有亮点的&#xff0…

超市管理系统设计1——基本功能设计

超市管理系统基础功能类设计 1. 概述 本设计文稿提供一个基础的超市管理系统&#xff0c;包含基本的功能设计。该系统将管理商品、顾客、员工和交易记录&#xff0c;不需要接入数据库&#xff0c;通过文件存储数据&#xff0c;并满足面向对象编程的基本要求&#xff08;继承、…

LabVIEW开发EOL功能测试系统

LabVIEW开发EOL功能测试系统 介绍了一种基于LabVIEW开发的EOL功能测试系统方案&#xff0c;涵盖软件架构、工作流程、模块化设计、低耦合性、易于修改与维护、稳定性及硬件选型。系统通过高效的CAN通信实现对电机控制器的全面测试&#xff0c;确保运行可靠并支持未来的升级需求…

媒体有入口,发稿有入口 是什么意思?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体有入口&#xff0c;发稿有入口是指在新闻媒体发稿时&#xff0c;稿件可以通过一定的路径被访问和浏览。具体来说&#xff0c;有入口的新闻稿件可以通过点击链接&#xff0c;逐步深入…

PyTorch深度学习实战(44)——基于 DETR 实现目标检测

PyTorch深度学习实战&#xff08;44&#xff09;——基于 DETR 实现目标检测 0. 前言1. Transformer1.1 Transformer 基础1.2 Transformer 架构 2. DETR2.1 DETR 架构2.2 实现 DETR 模型 3. 基于 DETR 实现目标检测3.1 数据加载与模型构建3.2 模型训练与测试 小结系列链接 0. 前…

第 10 章 动态参数(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 10.2动态参数 参数服务器的数据被修改时&#xff0c;如果节点不重新访问&#xff0c;那么就不能获取修改后的…

MySQL的组成与三种log

MySQL由几块组成 连接器分析器优化器执行器 MySQL的三大log blog 作用&#xff1a; 用于主从同步与数据恢复 记录内容&#xff1a; 已经完成的 DML(数据操作语句)&#xff0c;主要是用于数据备份 redolog<重试日志> 作用&#xff1a; 崩溃恢复&#xff0c;用于事…

Linux - 高级IO

目录 理解五种IO模型非阻塞IO的设置多路转接之select 实现一个简易的select服务器select服务器的优缺点 多路转接之poll 实现一个简易的poll服务器poll服务器的优缺点 多路转接之epoll epoll原理epoll的优势用epoll实现一个简易的echo服务器 epoll的LT和ET工作模式 什么是LT和…

【mysql】数据报错: incorrect datetime value ‘0000-00-00 00:00:00‘ for column

一、问题原因 时间字段在导入值0000-00-00 00:00:00或者添加 NOT NULL的时间字段时&#xff0c;会往mysql添加0值&#xff0c;此时可能出现此报错。 这是因为当前的MySQL不支持datetime为0&#xff0c;在MySQL5.7版本以上&#xff0c;默认设置sql_mode模式包含NO_ZERO_DATE, N…