金融机器学习:数据集划分与baseline模型

news2025/8/2 10:06:07

原创文章第115篇,专注“个人成长与财富自由、世界运作的逻辑, AI量化投资”。

在模型训练过程中,过拟合(overfitting)是非常常见的现象。所谓的overfitting,就是在训练集上表现很好,但是测试集上表现很差。为了减少过拟合,提高模型的泛化能力,实际中会有很多措施来缓解overfitting的问题。其中一个常见的方法就是将已有数据集中保留一部分数据作为测试集,即将原有数据分为X_train, X_test,X_train用来训练模型,X_test用来验证调整模型。

机器学习驱动的量化策略,与传统量化不同在于,它的交易信号是由模型给出,所以它需要遵守机器学习流程。机器学习需要对数据集进行划分:训练集、测试集。在训练集上“学习”模型,在测试集上评估训练的交易。

与传统机器学习随机抽样不同在于,由于我们需要在测试集在做“连续”的回测,所以不能把总体随机打乱取其中一部分,而是将期按比列分成两段。一段当训练集,一段当测试集。因此,我们不使用sklearn的train_test_split函数,而是自己实现一个金融时间序列的数据集切分函数。

最常用的是按日期来选择,比如“2017-01-01”这一天之前的数据都将作为训练集,用于训练模型,而这一天之后的数据都作为测试集,也就是未来回测使用的时间区间。

核心代码是下面的函数:

x_cols是所有的特征列,y_col的标签列,如果划分的日期为空的话,会按训练集80%计算出日期。

返回的数据格式类似sklearn的train_test_split。

import numpy as np
import datetime as dt
from engine.datafeed.dataloader import Dataloader


class OneStepTimeSeriesSplit:
    """Generates tuples of train_idx, test_idx pairs
    Assumes the index contains a level labeled 'date'"""

    def __init__(self, n_splits=3, test_period_length=1, shuffle=False):
        self.n_splits = n_splits
        self.test_period_length = test_period_length
        self.shuffle = shuffle

    @staticmethod
    def chunks(l, n):
        for i in range(0, len(l), n):
            print(l[i:i + n])
            yield l[i:i + n]

    def split(self, X, y=None, groups=None):
        unique_dates = (X.index
                        # .get_level_values('date')
                        .unique()
                        .sort_values(ascending=False)
        [:self.n_splits * self.test_period_length])

        dates = X.reset_index()[['date']]
        for test_date in self.chunks(unique_dates, self.test_period_length):
            train_idx = dates[dates.date < min(test_date)].index
            test_idx = dates[dates.date.isin(test_date)].index
            if self.shuffle:
                np.random.shuffle(list(train_idx))
            yield train_idx, test_idx

    def get_n_splits(self, X, y, groups=None):
        return self.n_splits


def get_date_by_percent(start_date, end_date, percent):
    days = (end_date - start_date).days
    target_days = np.trunc(days * percent)
    target_date = start_date + dt.timedelta(days=target_days)
    # print days, target_days,target_date
    return target_date


def split_df(df, x_cols, y_col, split_date=None, split_ratio=0.8):
    if not split_date:
        split_date = get_date_by_percent(df.index[0], df.index[df.shape[0] - 1], split_ratio)

    input_data = df[x_cols]
    output_data = df[y_col]

    # Create training and test sets
    X_train = input_data[input_data.index < split_date]
    X_test = input_data[input_data.index >= split_date]
    Y_train = output_data[output_data.index < split_date]
    Y_test = output_data[output_data.index >= split_date]

    return X_train, X_test, Y_train, Y_test


class Dataset:
    def __init__(self, symbols, feature_names, feature_fields, split_date, label_name='label', label_field=None):
        self.feature_names = feature_names
        self.feature_fields = feature_fields
        self.split_date = split_date
        self.label_name = label_name
        self.label_field = 'Sign(Ref($close,-1)/$close -1)' if label_field is None else label_field

        names = self.feature_names + [self.label_name]
        fields = self.feature_fields + [self.label_field]
        loader = Dataloader()
        self.df = loader.load_one_df(symbols, names, fields)

    def get_split_dataset(self):
        X_train, X_test, Y_train, Y_test = split_df(self.df, x_cols=self.feature_names, y_col=self.label_name,
                                                    split_date=self.split_date)
        return X_train, X_test, Y_train, Y_test

    def get_train_data(self):
        X_train, X_test, Y_train, Y_test = split_df(self.df, x_cols=self.feature_names, y_col=self.label_name,
                                                    split_date=self.split_date)
        return X_train, Y_train

    def get_test_data(self):
        X_train, X_test, Y_train, Y_test = split_df(self.df, x_cols=self.feature_names, y_col=self.label_name,
                                                    split_date=self.split_date)
        return X_test, Y_test

    def get_X_y_data(self):
        X = self.df[self.feature_names]
        y = self.df[self.label_name]
        return X, y




if __name__ == '__main__':
    codes = ['000300.SH', 'SPX']
    names = []
    fields = []
    fields += ["Corr($close/Ref($close,1), Log($volume/Ref($volume, 1)+1), 30)"]
    names += ["CORR30"]

    dataset = Dataset(codes, names, fields, split_date='2020-01-01')
    X_train, Y_train = dataset.get_train_data()
    print(X_train, Y_train)

模型训练:

codes = ['000300.SH', '399006.SZ']
names = []
fields = []

fields += ["Corr($close/Ref($close,1), Log($volume/Ref($volume, 1)+1), 30)"]
names += ["CORR30"]

fields += ["Corr($close/Ref($close,1), Log($volume/Ref($volume, 1)+1), 60)"]
names += ["CORR60"]

fields += ["Ref($close, 5)/$close"]
names += ["ROC5"]

fields += ["(2*$close-$high-$low)/$open"]
names += ['KSFT']

fields += ["($close-Min($low, 5))/(Max($high, 5)-Min($low, 5)+1e-12)"]
names += ["RSV5"]

fields += ["($high-$low)/$open"]
names += ['KLEN']

fields += ["$close"]
names += ['close']

fields += ['KF(Slope($close,20))']
names += ['KF']

fields += ['$close/Ref($close,20)-1']
names += ['ROC_20']

fields += ['KF($ROC_20)']
names += ['KF_ROC_20']

dataset = Dataset(codes, names, fields, split_date='2020-01-01')

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC, SVC
from sklearn.linear_model import LogisticRegression
from engine.ml.boosting_models import gb_clf

for model in [gb_clf, LogisticRegression(), RandomForestClassifier(), SVC()]:
    m = ModelRunner(model, dataset)
    m.fit()
    m.predict()

集成学习比传统机器学习对于表格数据结果还是好不少。同样的数据集,最好的是随机森森,其实是lightGBM(未调参版本)。

明天继续。

ETF轮动+RSRS择时,加上卡曼滤波:年化48.41%,夏普比1.89

etf动量轮动+大盘择时:年化30%的策略

我的开源项目及知识星球

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学弟:功能测试转测试开发容易吗?

最近看到后台留言问&#xff1a;功能测试转测试开发容易吗&#xff1f; 从这个问题&#xff0c;我能读出一些信息如下&#xff1a; 不知道你从事测试工作多久了&#xff0c;可以看出您特别羡慕测试开发工程师&#xff1b;你可能一直从事功能测试工作&#xff0c;工作模式或大…

关于对 DeferWindowPos 的理解

DeferWindowPos 这个 API 的目标是&#xff1a;同一时间&#xff0c;移动多个子窗口。这在一定程度上减少了窗户移动时进行的重绘工作量。 修改我们之前的例子代码&#xff0c;如下图所示&#xff1a; >> 请移步至 topomel.com 查看图片 << 请注意&#xff0c;我…

基于蚁群算法的时延Petri网(ACOTPN)路径规划算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

ImmunoChemistry艾美捷抗体涂层缓冲液解决方案

使用ImmunoChemistry艾美捷ICT的抗体涂层缓冲液来节省试剂&#xff0c;增强特定信号&#xff0c;并延长涂层板的保质期。抗体涂层缓冲液最大限度地将抗体吸附到聚苯乙烯板上&#xff0c;并稳定抗体的三维结构以获得最佳性能。 ImmunoChemistry抗体涂层缓冲液&#xff0c;5X通过…

Debian11.5安装Podman并以多容器方式搭建LEMP环境

起因&#xff1a;之前在CentOS系统时代&#xff0c;写过一篇采用docker搭建LEMP环境的博客。现在时过境迁&#xff0c;CentOS系统&#xff0c;CoreOS系统&#xff0c;Docker&#xff0c;Podman管理工具的地位和应用&#xff0c;都有了极大变化&#xff0c;而我也转到了更为自由…

3d-face-reconstruction比较

摘要&#xff1a;比较近3年&#xff0c;6篇顶会3d-face-reconstruction重建效果。 1:Deep3D **发表时间:**2020 成就&#xff1a; 1&#xff09;在REALY和REALY (side-view)两个Benchmark上取得 State-of-the-art。 2&#xff09;官方github上成绩&#xff1a; 3DMM&#xf…

【学习笔记27】JavaScript字符串方法的练习

JavaScript字符串方法的练习一、统计字符串中每个字符出现的次数(以对象的形式记录)1、拿到字符串所有的值2、累加统计次数3、小优化二、反转字符串三、替换违禁词1、需求:将字符串中的6666, 替换为 "****"2、需求: 批量替换违禁词 [6666, 777]四、查询字符串1、模拟…

安全自动化企业网络架构 (毕设分享)

一、前言&#xff1a; 前段时间完成了自己的毕设项目——安全自动化企业网络架构。总的来说&#xff0c;该项目是一个对自己的挑战&#xff0c;其中涉及到Kubernetes容器云的搭建以及安全加固&#xff0c;DevOps CI/CD部署容器化监控平台&#xff0c;Django自动化运维平台开发…

CSS3------盒模型

盒模型 每个标签在浏览器上都被渲染成一个矩形个盒子&#xff0c;这个盒子有一个标准都组成结构&#xff0c;我们称为标准盒模型 盒模型构成 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name&qu…

【MM小贴士】物料主数据的中止与后继(2)

【日常吐槽】项目要上线了&#xff0c;70w的物料主数据导完了&#xff0c;有一部分小伙伴被隔离了&#xff0c;没人陪我玩&#xff0c;所以再补充几点日常blog。 很久以前发票了一篇博客&#xff0c;是关于物料主数据的中止与后继&#xff0c; 前期的blog可以参考【MM小贴士】…

Euler diagram

An Euler diagram (/ˈɔɪlər/, OY-lər) is a diagrammatic means of representing sets and their relationships. They are particularly useful for explaining complex hierarchies and overlapping definitions. They are similar to another set diagramming techniqu…

使用css形变实现一个立方体

关于 Nuxt.js 2016 年 10 月 25 日&#xff0c;zeit.co 背后的团队对外发布了 Next.js &#xff0c;一个 React 的服务端渲染应用框架。几小时后&#xff0c;与 Next.js 异曲同工&#xff0c;一个基于 Vue.js 的服务端渲染应用框架应运而生&#xff0c;我们称之为&#xff1a;…

速卖通跨境智星,速卖通合理补单技法

1、测评的用途   提升店铺信誉等级和好评&#xff0c;最重要的是提升产品权重和搜索排名&#xff0c;因为如果产品没有曝光&#xff0c;就没有流量&#xff0c;当然当有了权重和搜索排名&#xff0c;好评也是必不可少的。 2、爆款打造   很多新人在测评的时候会关注店铺排名…

Git版本控制工具使用

文章目录1. CICD系统构成和流程1.1 CICD来源及概念1.2 Git版本控制系统2. Git操作和使用git config (基本配置操作)git clone <repo URL\> (创建仓库|拷贝已有仓库)git branch (分支相关操作- 创建|查看|删除)git checkout (操作文件和分支)git add/commit (提交和修改-保…

Unity导入URDF模型(turtlebot3 waffle pi为例)

本篇文章介绍Unity下如何导入机器人的URDF模型&#xff0c;主要参考官方教程&#xff1a;https://github.com/Unity-Technologies/Unity-Robotics-Hub/blob/main/tutorials/urdf_importer/urdf_tutorial.md   关于导入的机器人模型选择了turtlebot3 waffle pi作为示例 1.Uni…

Sa-Token

介绍 类似于Security的认证授权的解决方案&#xff0c;但是使用起来非常方便&#xff0c;1.支持登录认证&#xff0c;授权权限验证&#xff0c;踢人&#xff1b;2.支持自定义Token&#xff0c;并且能够结合Redis完成前后端分离认证方案&#xff1b;3.支持单点登录&#xff08;…

柯桥成人英语培训机构哪家好,新陈代谢到底是什么?

新陈代谢到底是什么? Metabolism is a combination of biochemical processes that your body uses to convert food into energy. These metabolic processes include breathing, eating and digesting food, the delivery of nutrients to your cells through the blood, th…

【Linux】(四)VS Code远程开发方式-实验室服务器使用VS Code远程开发

VS code 方式系列文章一、服务器情况简介1.1服务器及用户1.2 cuda1.3 conda环境二、VS code连接使用说明2.1 下载VS code2.2 配置2.3 调试文件附录&#xff1a;VS code调试复杂配置公共数据集系列文章 &#xff08;一&#xff09;服务器初次配置及安装vncserver &#xff08;二…

磨金石教育摄影技能干货分享|古风人像拍摄要注意哪些问题

古风人像与普通人像的拍摄略有不同&#xff0c;有三个要素需要做好准备。服装、妆容、道具。 服装有不少考究&#xff0c;不同的服装有不同的风格&#xff0c;侠士、温婉、清新、可爱等等&#xff0c;今天我们要拍摄的主题风格是侠女。所以选择的是魏晋风汉服。 妆 容 妆容也是…

【无人机】基于PID控制器和A星算法实现无人机路径规划附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …