量化交易 实战之回归法选股 part 2

# 可以自己 import 我们平台支持的第三方 python 模块,比如 pandas numpy 等。

import numpy as np

import pandas as pd

from sklearn.linear_model import LinearRegression

# 在这个方法中编写任何的初始化逻辑。 context 对象将会在你的算法策略的任何方法之间做传递。

def init(context):

    # 初始化股票因子权重

    context.weights = np.array([0.04549957, 0.01249463, -0.02397849, 0.06077185, -0.00195205, -0.00892116, -0.04641399, -0.05644752, -0.08393869])

    # 定义股票池数量

    context.stocknum = 20

    # 定时每月运行函数

    scheduler.run_monthly(regression_select, tradingday=1)

def regression_select(context, bar_dict):

    """ 回归预测选股逻辑 """

    # 获取沪深 300

    context.hs300 = index_components("000300.XSHG")

    # 1. 查询因子

    q = query(

        fundamentals.eod_derivative_indicator.pe_ratio,

        fundamentals.eod_derivative_indicator.pb_ratio,

        fundamentals.eod_derivative_indicator.market_cap,

        fundamentals.financial_indicator.ev,

        fundamentals.financial_indicator.return_on_asset_net_profit,

        fundamentals.financial_indicator.du_return_on_equity,

        fundamentals.financial_indicator.earnings_per_share,

        fundamentals.income_statement.revenue,

        fundamentals.income_statement.total_expense

        ).filter(

            fundamentals.stockcode.in_(context.hs300)

        )

    fund = get_fundamentals(q)

    context.factors_data = fund.T

    # 2. 数据预处理

    process_data(context)

    # 3. 根据每月预测下月的收益率

    select_stocklist(context)

    # 4. 调仓

    reblance(context)

def process_data(context):

    """ 删除空值 , 去极值 , 标准化 , 因子的市值中性化 """

    # 删除空值

    context.factors_data = context.factors_data.dropna()

    # 市值因子不进行去极值 , 标准化处理

    market_cap_factor = context.factors_data["market_cap"]

    # 去极值化 , U 型你换对每个因子进行处理

    for name in context.factors_data.columns:

        context.factors_data[name] = mad(context.factors_data[name])

        context.factors_data[name] = stand(context.factors_data[name])

        # 对因子 ( 除了市值因子 ) 中性化处理

        if name == "market_cap":

            continue

        # 建立回归方程 , 市值中性化

        lr = LinearRegression()

        x = market_cap_factor.values

        y = context.factors_data[name]

        # x: 要求二维 , y: 要求一维

        lr.fit(x.reshape(-1, 1), y)

        y_predict = lr.predict(x.reshape(-1, 1))

        # 得出误差进行替换原有因子值

        context.factors_data[name] = y - y_predict

def select_stocklist(context):

    """ 回归计算预测得出收益率结果 , 筛选收益率高的股票 """

    # 特征值是 : context.factors_Date (300, 9) 系数 : 因子权重

    # 进行矩阵运算外汇跟单gendan5.com  (300, 9) * (9, 1) = (300, 1)

    stock_return = np.dot(context.factors_data.values, context.weights)

    logger.info(stock_return)

    # 赋值给因子数据 , 注意都是默认对应的股票代码和收益率

    context.factors_data["stock_return"] = stock_return

    # 进行收益率排序

    ordered = context.factors_data.sort_values(by="stock_return", ascending=False)

    # 加入股票池

    context.stock_list = ordered.index[:context.stocknum]

def reblance(context):

    # ---------------- 卖出 ----------------

# 遍历股票池

    for stock in context.portfolio.positions.keys():

        # 判断是否还在股票池

        if stock not in context.stock_list:

            # 如果不在 , 卖出

            order_target_percent(stock, 0)

    # ---------------- 买入 -----------------

# 买入的百分比

    weight = 1.0 / len(context.stock_list)

    # 遍历股票池

    for stock in context.stock_list:

        # 等比例买入

        order_target_percent(stock, weight)

# before_trading 此函数会在每天策略交易开始前被调用,当天只会被调用一次

def before_trading(context):

    pass

# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新

def handle_bar(context, bar_dict):

    # 开始编写你的主要的算法逻辑

    pass

# after_trading 函数会在每天交易结束后被调用,当天只会被调用一次

def after_trading(context):

    pass

def mad(factor):

    """3 倍中位数去极值 """

    # 求出因子值的中位数

    median = np.median(factor)

    # 求出因子值与中位数的差值 , 进行绝对值

    mad = np.median(abs(factor - median))

    # 定义几倍的中位数上下限

    high = median + (3 * 1.4826 * mad)

    low = median - (3 * 1.4826 * mad)

    # 替换上下限

    factor = np.where(factor > high, high, factor)

    factor = np.where(factor < low, low, factor)

    return factor

def stand(factor):

    """ 数据标准化 """

    mean = factor.mean()

    std = factor.std()

    return (factor - mean) / std

 


请使用浏览器的分享功能分享到微信等