向量回归策略

发布于:2025-09-09 ⋅ 阅读:(16) ⋅ 点赞:(0)

本策略基于Python编写,利用聚宽平台进行股票交易。策略主要通过支持向量回归(SVR)模型来预测股票市值,并根据预测结果进行买卖操作。

 

策略核心思想

 

1. 数据收集与预处理:策略首先收集市场指数成分股的基本面数据,包括市值、总资产、总负债、净利润等,并对这些数据进行对数化处理和归一化处理。

2. 特征工程:除了基本财务指标外,策略还考虑了行业因素,将股票按照行业进行分类,并生成相应的行业特征。

3. 模型训练:使用支持向量回归(SVR)模型对处理后的数据进行训练,以预测股票的市值变化。

4. 交易执行:根据模型的预测结果,策略决定买入或卖出股票,以优化投资组合的表现。

 

交易逻辑与原理

 

1. 初始化与参数设置:

   - 在`initialize`函数中,策略设置了初始参数,如刷新频率、持仓数量等,并定义了每日执行的交易函数`trade`。

   - `set_params`函数用于设置全局变量,如天数计数器和持仓数量。

   - `set_backtest`函数用于设置回测基准、使用真实价格以及日志级别。

 

2. 数据获取与处理:

   - 在`trade`函数中,策略首先检查是否达到了数据更新的时间点(每10天一次)。如果是,则获取市场指数的成分股列表,并查询这些股票的基本面数据。

   - 数据经过一系列预处理步骤,包括对数化、归一化和缺失值填充,以确保数据的质量和一致性。

 

3. 特征构建:

   - 策略构建了一个包含财务指标和行业特征的复合特征集。这些特征包括市值的对数、净资本的对数、资产负债率、净利润等。

   - 行业特征通过将股票按照行业分类并生成相应的二进制向量来表示。

 

4. 模型训练与预测:

   - 使用支持向量回归(SVR)模型对特征集进行训练。SVR是一种适用于回归问题的监督学习算法,能够处理非线性关系并具有良好的泛化能力。

   - 训练完成后,模型用于预测股票的市值变化。

 

5. 交易决策与执行:

   - 根据模型的预测结果,策略计算每只股票的预期市值变化,并生成一个排序后的股票列表。

   - 策略首先卖出不在预期表现前10名的股票,以确保投资组合的更新和优化。

   - 如果当前持仓数量低于目标数量,则买入剩余数量的股票,以保持投资组合的规模。

 

6. 循环执行:

   - 策略在每个交易日结束时更新数据并重新训练模型,以确保交易决策始终基于最新的市场信息。

 

策略特点

1. 数据驱动:策略依赖于基本面数据和行业特征来做出交易决策,避免了单纯依赖价格波动的交易信号。

2. 机器学习应用:通过引入支持向量回归模型,策略能够捕捉数据中的复杂模式和非线性关系,提高预测准确性。

3. 动态调整:策略定期更新数据和模型,以适应市场环境的变化,保持交易策略的有效性。

4. 风险管理:通过设定止损点和止盈点,以及动态调整持仓数量,策略能够在追求收益的同时控制风险。

 

注意事项

1. 数据质量:策略的性能高度依赖于输入数据的质量。因此,确保数据的准确性和完整性至关重要。

2. 模型过拟合:由于使用了复杂的机器学习模型,需要注意防止过拟合现象的发生。可以通过交叉验证、正则化等方法来降低过拟合风险。

3. 交易成本:频繁的交易操作可能导致较高的交易成本。在实际应用中,需要考虑这些成本对策略收益的影响。

4. 市场适应性:策略在不同的市场环境下可能表现出不同的效果。因此,在实际应用前需要进行充分的回测和验证。

 

该策略结合了基本面分析与机器学习技术,旨在通过预测股票市值变化来实现投资收益的最大化。

然而,任何投资策略都存在一定的风险,投资者在使用前应充分了解其原理和潜在风险,并根据自身情况进行适当调整。

策略思维导图:

 

 

策略源码如下(pyrhon版):

 

import pandas as pd

import numpy as np

import math

from sklearn.svm import SVR  

from sklearn.model_selection import GridSearchCV  

from sklearn.model_selection import learning_curve

from sklearn.linear_model import LinearRegression

from sklearn.ensemble import RandomForestRegressor

import jqdata

 

def initialize(context):

    set_params()

    set_backtest()

    run_daily(trade, 'every_bar')

    

def set_params():

    g.days = 0

    g.refresh_rate = 10

    g.stocknum = 10

    

def set_backtest():

    set_benchmark('000001.XSHG')

    set_option('use_real_price', True)

    log.set_level('order', 'error')

    

def trade(context):

    if g.days % 10 == 0:

        sample = get_index_stocks('000001.XSHG', date = None)

        q = query(valuation.code, valuation.market_cap, balance.total_assets - balance.total_liability,

                  balance.total_assets / balance.total_liability, income.net_profit, income.net_profit + 1,

                  indicator.inc_revenue_year_on_year, balance.development_expenditure).filter(valuation.code.in_(sample))

        df = get_fundamentals(q, date = None)

        df.columns = ['code', 'log_mcap', 'log_NC', 'LEV', 'NI_p', 'NI_n', 'g', 'log_RD']

        

        df['log_mcap'] = np.log(df['log_mcap'])

        df['log_NC'] = np.log(df['log_NC'])

        df['NI_p'] = np.log(np.abs(df['NI_p']))

        df['NI_n'] = np.log(np.abs(df['NI_n'][df['NI_n']<0]))

        df['log_RD'] = np.log(df['log_RD'])

        df.index = df.code.values

        del df['code']

        df = df.fillna(0)

        df[df>10000] = 10000

        df[df<-10000] = -10000

        industry_set = ['801010', '801020', '801030', '801040', '801050', '801080', '801110', '801120', '801130',

                  '801140', '801150', '801160', '801170', '801180', '801200', '801210', '801230', '801710',

                  '801720', '801730', '801740', '801750', '801760', '801770', '801780', '801790', '801880','801890']

        

        for i in range(len(industry_set)):

            industry = get_industry_stocks(industry_set[i], date = None)

            s = pd.Series([0]*len(df), index=df.index)

            s[set(industry) & set(df.index)]=1

            df[industry_set[i]] = s

            

        X = df[['log_NC', 'LEV', 'NI_p', 'NI_n', 'g', 'log_RD','801010', '801020', '801030', '801040', '801050',

                '801080', '801110', '801120', '801130', '801140', '801150', '801160', '801170', '801180', '801200',

                '801210', '801230', '801710', '801720', '801730', '801740', '801750', '801760', '801770', '801780',

                '801790', '801880', '801890']]

        Y = df[['log_mcap']]

        X = X.fillna(0)

        Y = Y.fillna(0)

        

        svr = SVR(kernel='rbf', gamma=0.1)

        model = svr.fit(X, Y)

        factor = Y - pd.DataFrame(svr.predict(X), index = Y.index, columns = ['log_mcap'])

        factor = factor.sort_index(by = 'log_mcap')

        stockset = list(factor.index[:10])

        sell_list = list(context.portfolio.positions.keys())

        for stock in sell_list:

            if stock not in stockset[:g.stocknum]:

                stock_sell = stock

                order_target_value(stock_sell, 0)

            

        if len(context.portfolio.positions) < g.stocknum:

            num = g.stocknum - len(context.portfolio.positions)

            cash = context.portfolio.cash/num

        else:

            cash = 0

            num = 0

        for stock in stockset[:g.stocknum]:

            if stock in sell_list:

                pass

            else:

                stock_buy = stock

                order_target_value(stock_buy, cash)

                num = num - 1

                if num == 0:

                    break

        g.days += 1

    else:

        g.days = g.days + 1    

          

 

 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到