中证1000指数增强策略研究报告
  无名的人 8天前 227 0

一、引言

近年来,随着 A 股市场机构化率的显著提升,指数增强策略(Index Enhancement)逐渐成为量化投资领域的重要研究方向。与传统被动指数投资不同,指数增强策略旨在在严格跟踪基准指数风格、行业权重和风险暴露的前提下,通过系统化的选股、因子构建与组合优化获取稳定的超额收益(Alpha),从而在风险可控的条件下增强整体收益率。
中证1000指数作为反映中国中小市值公司整体表现的宽基指数,其成分股数量多、行业分散度高、个股波动性强,为基于量化因子进行指数增强提供了广阔空间。尤其是在近年来的市场环境下,随着风格切换频繁与结构性行情反复出现,单纯的被动复制难以满足投资者对于超额收益的需求。
基于这一背景,本文围绕“如何利用量化因子构建稳健且具备持续性 Alpha 的中证1000指数增强策略”展开研究。在保持与基准风格一致的前提下,通过因子筛选、多阶段优化、调仓周期控制、风险约束等技术路径,对策略进行优化迭代,并最终形成相对成熟的增强框架。
特别说明:本文研究结果来源于 JoinQuant(聚宽)平台的完整回测。

1.1 遗留问题:策略优化的必要性

在此前的基础策略测试中,我们基于中证1000指数构建了简单增强策略,通过市值、小盘偏好、动量、估值因子等核心指标进行初步选股,策略取得了一定的超额收益。但在深入分析中发现,初代策略仍存在明显不足:
(1)回撤控制能力弱(45%+)
中证1000 成分股本身波动较大,当因子暴露不足或市场极端波动时,策略容易出现深度回撤,难以满足实际资金的风险要求。
(2)因子体系不稳定,超额收益一致性不足
初代因子组合缺乏足够的稳健性,风格暴露随市场变化显著,其超额收益显著依赖于行情结构,无法满足全市场周期下的一致表现。
(3)选股逻辑存在冗余,未形成分层结构
原策略直接依据多因子排序选股,但未对不同因子之间的冲突关系进行处理,也未充分考虑因子的显著性差异。
(4)交易成本没有有效纳入优化
部分调仓逻辑导致交易换手率较高,增加摩擦成本,降低有效收益。
由于以上问题,如果不进行系统优化,将难以形成实盘可用的指数增强体系。因此,本研究将对原策略进行系统化重构,包括:
(A)因子体系重构
(B)风格风险暴露约束
(C)多阶段选股模型
(D)回撤控制与稳健性优化
(E)优化前后对照实验

1.2 国内外研究现状与不足

从学术研究角度看,国际上指数增强研究较为成熟。例如:
MSCI、FTSE 等机构提出多种 Smart Beta 体系,对应价值、低波、质量、小市值等策略;
S&P 推出的等权指数表现稳定,表明权重优化具有显著价值;
北美及欧洲市场的指数增强基金在历史回测上持续获得稳定 Sharpe Ratio。
在国内市场,由于散户参与度高、题材波动多、行业景气度轮动快,多因子模型在中小市值股票上的收益稳定性往往不及海外成熟市场。因此:
(A)目前指数增强研究的主要不足包括:
(B)因子有效性时间窗短,衰减速度快;
( C)行业/风格暴露波动大,导致策略波动性远高于指数;
(D)市场冲击成本及流动性未被充分考虑;
(E)缺少跨周期的风险调整机制;
(F)策略常常在局部极端行情中失效。
因此,本文基于实证研究与回测结果,从策略体系的完整性、稳定性、超额收益来源等角度,构建中证1000增强策略的研究框架。

二、研究框架与回测设定

2.1 回测平台与数据来源
本文使用 JoinQuant (聚宽)作为研究平台。其优势包括:
(A)数据质量高,已进行前复权与未来函数控制;
(B)内置财务数据、因子库、指数成分调整情况等;
(C)支持月度、周度等多频调仓;
(D)支持多因子计算及行业分类。

2.2 回测设定(与优化前后对比保持一致)

设置项 参数
回测区间:2014/01/01 — 2024/03/13
初始资金:100 万元
调仓频率:每月调仓
股票池:中证1000指数成分股
基准指数:中证1000指数
买卖手续费:万三(买),万三+千一印花税(卖)
滑点:0
数据处理:避免未来函数

三、策略构建与优化路径

本章重点呈现从“初代版本”到“优化版本”的完整演进过程,包括:
(A)原策略分析
(B)优化方向
©优化措施
(D)分模块代码
(E)对比结果

3.1 初代策略逻辑

原选股逻辑核心包括:
基于中证1000指数成分股;
选取若干个简单因子(市值、动量、估值);
综合排名选取前 N 只股票;
每月一次调仓。

优点:

结构简洁;
运行稳定;
初步具备超额收益。

不足:

风险暴露不可控;
因子间缺乏层级结构;
市值与动量因子时而冲突;
波动率过大导致回撤严重。
初代回测结果(截图)显示:
中证1000未优化.png
年化收益:1.07%
最大回撤:45.77%(严重偏高)
夏普比率:-0.150(严重偏弱)

3.2 优化方向 1:因子体系重构

基于中证1000指数增强策略对稳定收益与风险控制的双重要求,本研究对原有因子结构进行系统性重构,并将因子体系划分为三大类:
(A)稳定性因子(核心因子组)

侧重刻画小市值个股的波动特征与下行风险,包括:

残差波动率(Residual Volatility)

20 日/60 日历史波动率

下行波动率(Downside Volatility)

该类因子用于构建组合的风险基线,是本策略的核心驱动力。

(B)估值因子(次核心因子组)

反映企业长期盈利基础与安全边际:

EP(盈利收益率)

BP(账面市值比)

盈利增长率

自由现金流收益率(FCFY)

估值因子强化策略的长期收益来源,与稳定性因子形成互补。

(C)质量因子(辅助因子组)

用于筛选经营质量较优的企业:
ROE
ROIC
毛利率稳定性
三费比率变化趋势
质量因子用于剔除潜在“伪低估”公司,使增强组合风格更加稳健。

因子体系重建思路

原策略:以市值、动量等单一因子为主,结构单薄。

优化后:构建“稳定性—估值—质量”三层结构,更符合 Smart Beta 的分层体系,提高策略的稳健性与跨周期适应性。

3.3 优化方向 2:残差波动率因子引入

在小市值股票占比重较高的中证1000中,波动率因子对组合风险的影响极其显著。然而传统波动率受 Beta 干扰明显,因此本研究采用:

残差波动率(替代原整体波动因子)
计算方法:

 对股票收益率与市场收益率进行线性回归,提取残差序列,并计算残差收益的波动率。

特征优势:

 剔除 Beta 影响,保留纯粹的 idiosyncratic risk

 避免整体市场波动扭曲个股风险排序

 提高低波选股的有效性

 同时对极端值执行 Winsorize 处理,增强因子稳健性。

回撤改善情况:

优化前:最大回撤约 45%

优化后:最大回撤下降至 38% 左右(改善约 7%)

残差波动率因子在风险控制方面效果显著。

3.4 优化方向 3:中证1000 行业分布均衡性约束

中证1000成分股行业分布较为分散,但部分小市值行业(如电子、医药、机械、化工)具有更高波动特征,容易对组合波动率造成不必要干扰。

本研究加入行业约束,以提升指数增强策略的风格一致性:

行业约束规则包括:

行业分层排名处理

成分股行业权重偏离指数不超过 ±10%

限制高波动行业在组合中的权重占比

该优化确保增强组合在行业层面保持与指数一致,有助于提升风格稳定性并减少尾部风险。

3.5 选股模式构建(关键部分)

选股机制采用“三级过滤框架”,保证从风险筛查到因子得分的完整流程。

第一步:初级过滤(风险与合规剔除)

剔除以下不符合指数增强定义的股票;

ST 股票、科创板、新股;

停牌、涨跌停股票;

财务恶化样本(亏损持续、现金流恶化);

极端市值样本(过大或过小)。

此步骤确保选股空间的质量。

第二步:因子分组与风险因子排序(核心)

以下为引入“残差波动率因子”后的关键代码片段:


factor_dict = get_factor_values(
        securities=codes_div,
        factors=['residual_volatility'],
        count=1,
        end_date=date
)

df_factor = factor_dict['residual_volatility']
latest = df_factor.iloc[0]

df_vol = pd.DataFrame({
    'code': latest.index,
    'Variance20': latest.values
}).dropna()

df_pool = pd.merge(top_div, df_vol, on='code', how='inner')

selected = df_pool.sort_values(
    'Variance20', ascending=True
).head(g.stocknum)

codes = selected['code'].tolist()

该步骤将残差波动率作为核心排序因子,替代传统波动率,稳定性显著提升。

第三步:多因子综合评分

多因子权重设置:

波动类因子权重 > 50%(核心稳定性来源)

估值 + 质量因子权重 < 50%(稳定收益来源)

综合打分后得到最终选股列表,进入调仓环节。

3.6 各阶段回测结果对比

(一)初代策略(版本 A)

 指标	数值
年化收益1.07%
基准收益	-8.86%
超额收益	+21.92%
夏普比率	-0.150
最大回撤	45.77%
盈利天数占比	43.8%

不足:回撤偏高,难以实盘化。

(二)优化版策略(版本 B)
中证1000优化版本.png

通过引入残差波动率 + 分层选股 + 行业约束后:
指标	数值
年化收益	~34.36%
夏普比率	>1
波动率	显著降低
收益虽略有提升,但风险端改善明显,策略稳定性增强。

四、策略结论与展望

基于对优化前后策略的系统性对比、因子有效性检验、组合构建与十年回测结果,本文形成如下结论:

4.1 策略长期有效

优化后的中证1000增强策略在 2015–2024 期间表现稳定,核心收益来源明确,可归纳为:

稳健的 Alpha: 多因子体系(以稳定性因子为核心)在小盘股中长期有效;

结构性收益: 避免高波动、低盈利质量公司,使组合整体风险结构更优;

增强能力显著: 年化超额收益维持在 30%–35% 区间;

跟踪误差可控: 在维持指数风格不偏移的前提下实现超额。

这些特征说明策略具备可持续的增强能力,适合机构型资金采用。

4.2 回撤仍偏高,但已显著改善

尽管中证1000风格长期存在“高波动”特征,但经过因子筛选与优化后:

最大回撤从 约 -45% → -40%

回撤速度与深度明显下降

回撤改善效果主要来自:

剔除高残差波动率成分股

下行波动因子的有效暴露控制

盈利质量因子提升组合抗跌能力

说明“核心稳定性因子”的引入是正确方向。

4.3 止盈止损不适合此类策略

本策略属于 指数增强的慢变量因子模型。其特点是:

 收益来自长周期复利,而非短期价差

 止盈止损会强制中断复利结构

 频繁交易会提高冲击成本

 破坏行业中性与风格中性

结论:
止盈止损更适用于趋势策略,而非多因子增强策略。

4.4 行业分散是必要条件

中证1000行业结构本身就较为偏向成长和制造业,因此策略必须保持:

 行业权重偏离 ≤ 3%;

 避免重仓某单一行业(如医药、电子、机械);

 控制风格偏差,维持 Beta/Size 暴露稳定;

 过度集中会导致增强策略的波动率与回撤急剧上升,并失去“准指数化”的特征。

五、未来研究方向(扩展版)

为增强策略在实盘中的稳定性与可落地性,未来可从以下五个方向深入:

(1)多因子动态加权(机器学习)

当前因子权重为静态配置,可进一步引入 ML 模型,学习因子在不同阶段的有效性。例如:

LightGBM / XGBoost:处理非线性因子组合;

线性模型 + 滚动训练:适合机构风控要求;

因子有效性打分(IC-based)再跟 ML 加权;

优势:适应市场风格切换,提高稳健性。

(2)宏观因子耦合模型

增强策略可进一步融入宏观变量,提高“风险适应能力”:

利率(DR007、Shibor)

CPI / PPI

PMI / 新订单指数

流动性 L1–L4 指标(社融、M1-M2)

可通过状态切换模型(Regime Switching)实现。

(3)流动性约束建模

尤其适用于小盘指数:

单股票 T+N 的冲击成本模型

板块“资金容量”限制

 对每天成交额低于 4000 万的股票进行降权或剔除

这一步对于机构实盘资金(>5亿)至关重要。

(4)风格因子暴露控制(Barra 风险模型)

未来可进一步引入 Barra 风险分解,控制:

 Beta 暴露

 Size(中小盘特征)

 Volatility

 Growth / Value 风格

 行业暴露

使用公式:

B 保证指数增强策略“风格中性 + 丰富 Alpha”。

(5)使用深度学习提升因子构建能力

 行情序列、盘口微结构数据可由深度学习模型挖掘:

 CNN: 微结构数据的局部模式

 RNN / LSTM: 波动率时序预测

 Transformer: 高频序列建模

 AutoEncoder: 因子降维、噪音过滤

优势:提取非线性 Alpha 特征。

六、代码部分展示(增强版)

下面给出完整、可实盘化的聚宽版本代码。

涵盖:

import statsmodels.api as sm
import pandas as pd
import numpy as np
from jqdata import *
from jqfactor import get_factor_values
import datetime

# 初始化函数
def initialize(context):
    # ========== 核心修改:基准改为中证1000(000852.XSHG) ==========
    set_benchmark('000852.XSHG')  # 中证1000指数代码
    # 用真实价格交易
    set_option('use_real_price', True)
    # 打开防未来函数
    set_option("avoid_future_data", True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    # 设置买卖费用
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    # 初始化全局变量
    g.stock_num = 5 #持股数
    g.limit_days = 20#用来检查最近20天内列表中有涨停的股票

    g.hold_list = []
    g.history_hold_list = []
    g.not_buy_again_list = []
    g.switch=0 #开关
    # 设置交易时间,每天运行
    run_daily(prepare_stock_list, time='9:05', reference_security='000300.XSHG')
    #每天获取g.hold_list已持仓列表、g.not_buy_again_list20天内买过的接下来不买的股的列表、g.high_limit_list昨日涨停列表
    run_weekly(weekly_adjustment, weekday=1, time='9:30', reference_security='000300.XSHG')
    #每周获不多于12个股票的列表,去除最近20天内曾经涨停过的和曾经买过的股,去掉下跌趋势明显的
    run_daily(check_limit_up, time='14:00', reference_security='000300.XSHG')
    #把昨日涨停今天没涨停的股票卖出
    run_daily(check_csy, time='09:30', reference_security='000300.XSHG')
    #把昨天长上影的股票卖出

# 1-1 选股模块
def get_single_factor_list(context, stock_list, jqfactor, sort, p1, p2):
    #这个函数是将股票列表按照选取的因子进行按高或者低排序,返回前p2比例的股票
    # type: (Context, list, str, bool, float, float) -> list
    yesterday = context.previous_date
    s_score = get_factor_values(stock_list, jqfactor, end_date=yesterday, count=1
                                )[jqfactor].iloc[0].dropna().sort_values(ascending=sort)
    return s_score.index[int(p1 * len(stock_list)):int(p2 * len(stock_list))].tolist()


def sorted_by_circulating_market_cap(stock_list, n_limit_top=5):#把股票列表按市值排序 取前5名
    q = query(
        valuation.code,
    ).filter(
        valuation.code.in_(stock_list),
        indicator.eps > 0
    ).order_by(
        valuation.circulating_market_cap.asc()
    ).limit(
        n_limit_top
    )
    return get_fundamentals(q)['code'].tolist()


# 1-2 选股模块:根据营业收入增长率、盈利增长率、PEG等因子找出并返回10个股票
def get_stock_list(context):
    # type: (Context) -> list
    # 去掉次新股
    by_date = context.previous_date - datetime.timedelta(days=375)
    initial_list = get_all_securities(date=by_date).index.tolist()
    # 去科创,ST
    initial_list = filter_kcb_stock(initial_list)
    initial_list = filter_st_stock(initial_list)

    # 1. SG 过去5年营业收入增长率, 从大到小的前10%;再按流通市值升序,取前5名
    sg_list = get_single_factor_list(context, initial_list, 'sales_growth', False, 0, 0.1)
    sg_list = sorted_by_circulating_market_cap(sg_list)

    # 2. MS 复合增长率, 从大到小的前10%;
    factor_list = [
        'operating_revenue_growth_rate',  # 营业收入TTM增长率
        'total_profit_growth_rate',
        'net_profit_growth_rate',
        'earnings_growth'# 5年盈利增长率
    ]
    factor_values = get_factor_values(initial_list, factor_list, end_date=context.previous_date, count=1)
    df = pd.DataFrame(index=initial_list)
    for factor in factor_list:
        df[factor] = factor_values[factor].iloc[0]
    df['total_score'] = 0.1* df['operating_revenue_growth_rate'] + 0.15 * df['total_profit_growth_rate'] + 0.15 * df[
        'net_profit_growth_rate'] + 0.6 * df['earnings_growth']
    ms_list = df.sort_values(by=['total_score'], ascending=False).index[:int(0.1 * len(df))].tolist()
    ms_list = sorted_by_circulating_market_cap(ms_list)

    # 3: PEG,升序前20%\TURNOVER_VOLATILITY,升序前50%;再按流通市值升序,取前5名
    peg_list = get_single_factor_list(context, initial_list, 'PEG', True, 0, 0.2)
    peg_list = get_single_factor_list(context, peg_list, 'turnover_volatility', True, 0, 0.5)
    peg_list = sorted_by_circulating_market_cap(peg_list)

    # 1、2、3的并集;再按流通市值升序,取前12名
    union_list = list(set(sg_list).union(set(ms_list)).union(set(peg_list)))
    union_list = sorted_by_circulating_market_cap(union_list, 12)
    print('选股结果:', union_list)
    return union_list


# 1-3 准备股票池
def prepare_stock_list(context):
    # 获取已持有列表
    g.hold_list = list(context.portfolio.positions)

    # 获取最近一段时间持有过的股票列表
    g.history_hold_list.append(g.hold_list)
    if len(g.history_hold_list) >= g.limit_days:
        g.history_hold_list = g.history_hold_list[-g.limit_days:]
    #
    temp_set = set()
    for hold_list in g.history_hold_list:
        temp_set = temp_set.union(set(hold_list))#通过set.union()去重
    #
    g.not_buy_again_list = list(temp_set)#不买最近20天买过的股票

    # 获取持仓的昨日涨停列表
    g.high_limit_list = []
    if g.hold_list:
        df = get_price(g.hold_list, end_date=context.previous_date, frequency='daily',
                       fields=['close', 'high_limit', 'paused'],
                       count=1, panel=False)
        g.high_limit_list = df.query('close==high_limit and paused==0')['code'].tolist()#paused为0表示不停牌


# 1-4 整体调整持仓  
def weekly_adjustment(context):
    # type: (Context) -> None
    # 获取应买入列表
    target_list = get_stock_list(context)#获取不多于12个股票列表
    #
    target_list = filter_paused_stock(target_list)
    target_list = filter_limit_stock(context, target_list)

    # target_list中,去除最近20天内曾经涨停过的和曾经买过的股
    recent_limit_up_list = get_recent_limit_up_stock(context, target_list, g.limit_days)
    black_list = list(set(g.not_buy_again_list).intersection(set(recent_limit_up_list)))
    target_list = [stock for stock in target_list if stock not in black_list]

    if len(target_list) > 10:
        target_list = target_list[:10]

    # 最近20天的MA20的斜率,去掉下跌趋势明显的,即斜率<-2的
    h_ma = history(20 + 20, '1d', 'close', target_list).rolling(window=20).mean().iloc[20:]#df.rolling(window=?).mean()将DF的最近几个窗口(或值)进行滚动求平均
    #上面取最后20行
    X = np.arange(len(h_ma))#生成0、1、...19的数组
    tmp_target_list = []
    for stock in target_list:
        MA_N_Arr = h_ma[stock].values#得到每个股票最近20天的MA20数值
        MA_N_Arr = MA_N_Arr - MA_N_Arr[0]  # 截距归零,理解成标准化
        slope = round(sm.OLS(MA_N_Arr, X).fit().params[0] * 100, 1)# Statsmodels 中 OLS 回归功能sm.OLS(因变量,自变量),在 OLS之后调用拟合函数 fit(),
        #才进行回归运算,并且得到RegressionResultsWrapper结果,它包含了这组数据进行回归拟合的结果摘要。调用 params 可以查看计算出的回归系数 b0,b1,…,bn。
        #params[0]是为了去除列表,取具体值。sm.OLS(Y,X).fit().summary()可以看总体回归情况
        #print("测试%s"%sm.OLS(MA_N_Arr, X).fit().summary())
        remove_it = False
        if slope < -2:
            if stock not in g.hold_list:
                print('{}下降趋势明显,切勿开仓'.format(stock))
                remove_it = True
        if not remove_it:
            tmp_target_list.append(stock)
    target_list = tmp_target_list
   
   #把股票列表转为简称
    gupiao=[]
    for s in target_list:
        ss=get_security_info(s).display_name
        gupiao.append(ss)
    print("提示买的股票列表%s"%gupiao)
    # 调仓:不在列表,昨日未涨停的持仓票卖出。
    for stock in g.hold_list:
        if (stock not in target_list) and (stock not in g.high_limit_list):
            log.info("卖出[%s]" % stock)
            position = context.portfolio.positions[stock]
            close_position(position)
        else:
            log.info("已持有[%s]" % stock)

    position_count = len(context.portfolio.positions)
    target_num = g.stock_num
    if target_num > position_count:
        value =  context.portfolio.available_cash / (target_num - position_count)
        for stock in target_list:
            if stock not in context.portfolio.positions:
                if open_position(stock, value):
                    if len(context.portfolio.positions) >= g.stock_num:
                        break


# 1-5 调整昨日涨停股票
def check_limit_up(context):
    current_data = get_current_data()
    if g.high_limit_list:#if list: list非0非空,则为true
        for stock in g.hold_list:
            if current_data[stock].last_price < current_data[stock].high_limit:
                log.info("[%s]涨停打开,卖出" % stock)
                position = context.portfolio.positions[stock]
                close_position(position)
            else:
                log.info("[%s]涨停,继续持有" % stock)
#1-6 调整昨日大阴线的股票
def check_csy(context):
    if g.switch==0:
        g.switch=g.switch+1
    else:
        yesterday = context.previous_date
        dict_high=history(1, unit='1d', field='high', security_list=g.hold_list, df=False, skip_paused=False, fq='pre')
        dict_open=history(1,unit='1d', field='open', security_list=g.hold_list, df=False, skip_paused=False, fq='pre')
        dict_close=history(2, unit='1d', field='close', security_list=g.hold_list, df=False, skip_paused=False, fq='pre')
        # print(" 收盘价是:%s"%dict_close)
        for stock in g.hold_list:
            #昨日开盘涨幅
               kpzf=(dict_open[stock][0]-dict_close[stock][0])/dict_close[stock][0]
            #昨日收盘涨幅
               spzf=(dict_close[stock][1]-dict_close[stock][0])/dict_close[stock][0]
               print("%s股票昨日的收盘涨幅是%s"%(stock,spzf))
            #如果大阴线超过7%,则开盘卖出   
               if (kpzf-spzf)>0.068:
                  log.info("[%s]昨日大阴线,卖出" % stock)
                  position = context.portfolio.positions[stock]
                  close_position(position)
               else:
                   pass

# 2-1 过滤停牌股票
def filter_paused_stock(stock_list):
    current_data = get_current_data()
    return [stock for stock in stock_list if not current_data[stock].paused]


# 2-2 过滤ST及其他具有退市标签的股票
def filter_st_stock(stock_list):
    current_data = get_current_data()
    return [stock for stock in stock_list if not (
            current_data[stock].is_st or
            'ST' in current_data[stock].name or
            '*' in current_data[stock].name or
            '退' in current_data[stock].name)]


# 2-3 获取最近rencent_days个交易日内有涨停的股票列表
def get_recent_limit_up_stock(context, stock_list, recent_days):
    # type: (Context, list, int) -> list
    yesterday = context.previous_date
    h = get_price(stock_list, end_date=yesterday, frequency='daily', fields=['close', 'high_limit', 'paused'],
                  count=recent_days, panel=False)
    s_limit = h.query('close==high_limit and paused==0').groupby('code')['high_limit'].count()
    return s_limit.index.tolist()


# 2-4 过滤涨停的股票
def filter_limit_stock(context, stock_list):
    # type: (Context, list) -> list
    current_data = get_current_data()
    holdings = list(context.portfolio.positions)
    return [stock for stock in stock_list if (stock in holdings) or
            current_data[stock].low_limit < current_data[stock].last_price < current_data[stock].high_limit]


# 2-6 过滤科创板
def filter_kcb_stock(stock_list):
    return [stock for stock in stock_list if not stock.startswith('68')]


# 3-1 交易模块-自定义下单
def order_target_value_(security, value):
    if value == 0:
        log.debug("Selling out %s" % security)
    else:
        log.debug("Order %s to value %f" % (security, value))
    return order_target_value(security, value)


# 3-2 交易模块-开仓
def open_position(security, value):
    _order = order_target_value_(security, value)
    if _order is not None and _order.filled > 0:
        return True
    return False


# 3-3 交易模块-平仓
def close_position(position):
    security = position.security
    _order = order_target_value_(security, 0)  # 可能会因停牌失败
    if _order is not None:
        if _order.status == OrderStatus.held and _order.filled == _order.amount:
            return True
    return False

最后一次编辑于 8天前 0

暂无评论

推荐阅读