//------------------------------------------------------------------------
// 简称: Vip19全品种资金流截面策略
// 名称: Vip19全品种资金流截面策略
// 类别: 公式应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// 策略名称: Vip19全品种资金流截面策略
// 策略类型: 截面多空策略
// 原创：松鼠Quant
// 主页：quant789.com
// 公众号：松鼠Quant
// 禁止转发售卖。
// 策略解读:
// 1. 策略思路：
//    该策略是一个基于资金流向和持仓量变化的多品种截面交易策略。通过分析
//    不同品种的持仓量效应和成交量效应，构建综合得分进行多空操作。
//
// 2. 核心指标：
//    - 持仓量效应(oieffct)：反映持仓量变化对价格的影响力
//    - 成交量效应(voleffect)：衡量成交量对价格变动的推动作用
//    - 综合得分(score)：通过权重整合两个效应指标
//
// 3. 交易逻辑：
//    - 对所有品种计算综合得分
//    - 买入得分最高的品种
//    - 做空得分最低的品种
//    - 其他品种平仓
//
// 4. 参数说明：
//    - N(14): 标准化周期，用于计算移动平均和标准差
//    - length(14): 因子指标计算周期
//    - weights(0.5): 持仓量效应和成交量效应的权重
//
// 5. 风险控制：
//    - 通过标准化处理降低异常值影响
//    - 多空对冲设计，降低系统性风险
//    - 自动换月设置，避免交割风险
//
// 6. 适用市场：
//    - 适合流动性好、成交活跃的期货品种
//    - 建议在波动率适中的市场环境下运行
//
// 7. 注意事项：
//    - 需要注意换月期间的持仓处理
//    - 权重参数需要根据不同品种特性调整
//    - 建议进行充分的历史回测验证
//------------------------------------------------------------------------
// 策略参数定义
Params
    Numeric N(14);        // 标准化周期，用于计算移动平均和标准差
    Numeric length(14);   // 因子指标计算的周期长度
    Numeric weights(0.5); // 持仓量效应和成交量效应的权重参数，范围0-1

// 变量声明
Vars
    Series<Numeric> oi_ma;            // 持仓量移动平均
    Series<Numeric> oi_chg;           // 持仓量变化率
    Series<Numeric> oieffct;          // 持仓量效应因子
    Series<Numeric> returns;          // 收益率序列
    Series<Numeric> money_flow;       // 资金流量指标
    Series<Numeric> score;            // 多因子综合得分
    Series<Numeric> score_scaled;     // 标准化后的综合得分
    Series<Numeric> oieffct_scaled;   // 标准化后的持仓量效应
    Series<Numeric> voleffect_scaled; // 标准化后的成交量效应
    Series<Numeric> quote_chg;        // 价格涨跌幅
    Series<Numeric> NetChg;           // 净价格变化
    Series<Numeric> TotChg;           // 总价格变化
    Series<Numeric> voleffect;        // 成交量效应因子
    Series<array<Numeric>> array_chg; // 存储各品种得分的数组
    Series<array<Numeric>> array_mfc; // 资金流数组
    Array<Integer> id1;               // 用于排序的索引数组
    Numeric actual_length;            // 实际计算周期
    global Numeric i;                 // 全局循环计数器
    
// 事件处理
Events
    // 初始化事件
    OnInit()
    {
        //=========除权换月相关设置==============
        AddDataFlag(Enum_Data_RolloverBackWard());     // 设置后复权处理
        AddDataFlag(Enum_Data_RolloverRealPrice());    // 设置映射真实价格
        AddDataFlag(Enum_Data_AutoSwapPosition());     // 设置自动换仓
        /*AddDataFlag(Enum_Data_IgnoreSwapSignalCalc());    //设置忽略换仓信号计算*/
    }

    // K线处理事件
    OnBar(ArrayRef<Integer> indexs)
    {
        // 遍历所有数据点
        Range[i=0:datacount-1] //range[0:datacount-1]
        {
            // 计算实际使用的周期长度，不超过当前可用的数据量
            actual_length = Min(length, CurrentBar + 1);
            Commentary("actual_length"+Text(actual_length));

            // 计算持仓量变化率（当前持仓量与N周期前的差值）
            oi_chg = openint - openint[actual_length-1];

            // 计算效率系数相关指标
            NetChg = (close - close[actual_length-1]);  // 计算净价格变化
            TotChg = Summation(Abs(close - close[1]), actual_length-1-1);  // 计算总价格变化
            
            // 计算成交量效应因子（价格变化效率 * 成交量）
            voleffect = IIF(TotChg > 0, NetChg/ TotChg*vol, 0);    
            
            // 计算持仓量效应因子（价格变化效率 * 持仓量变化）
            oieffct = IIF(TotChg > 0, NetChg/ TotChg*oi_chg, 0);    
            
            Commentary("Average(oi_chg, N)"+Text(Average(oi_chg, N)));
            Commentary("StandardDev(oi_chg, N,2)"+Text(StandardDev(oi_chg, N,2)));

			// 标准化持仓量效应因子
			// 使用Z-Score标准化方法：(x - μ) / σ
			// 其中：x为原始值，μ为均值，σ为标准差
			If (StandardDev(oieffct, N,2) <> 0)  // 检查标准差是否为0，避免除零错误
			{
				// 计算标准化分数：
				// 1. Average(oieffct, N) 计算N周期的持仓量效应均值
				// 2. StandardDev(oieffct, N,2) 计算N周期的标准差，2表示使用无偏估计
				// 3. 将原始值减去均值后除以标准差，得到标准化后的分数
				oieffct_scaled = (oieffct - Average(oieffct, N)) / StandardDev(oieffct, N,2);
			}
			Else
			{
				oieffct_scaled = 0;  // 当标准差为0时，设置标准化值为0，表示该周期内无显著变化
			}

			// 标准化成交量效应因子
			// 使用相同的Z-Score标准化方法处理成交量效应因子
			// 标准化后的值通常在[-3,3]区间内，可以更好地进行跨品种比较
			If (StandardDev(voleffect, N,2) <> 0)  // 检查标准差是否为0
			{
				// 计算标准化分数：
				// 1. Average(voleffect, N) 计算N周期的成交量效应均值
				// 2. StandardDev(voleffect, N,2) 计算N周期的标准差
				// 3. 标准化处理使得不同品种的成交量效应具有可比性
				voleffect_scaled = (voleffect - Average(voleffect, N)) / StandardDev(voleffect, N,2);
			}
			Else
			{
				voleffect_scaled = 0;  // 当标准差为0时，说明该周期内成交量效应无明显变化
			}

            // 计算综合得分（加权平均）
            score = average(weights * oieffct_scaled + (1 - weights) * voleffect_scaled);
            Commentary("综合得分: " + Text(score));  
            data0.array_chg[0][i] = score;  // 存储当前品种的得分
        }

        // 基于得分进行排序和交易
        array<Integer> id1;
        // 初始化排序索引数组
        for i = 0 to GetArraySize(array_chg[1])-1
        {
            print("array_chg[0]["+text(i)+"]="+text(array_chg[1][i]));
            id1[i]=i;  // 初始化排序索引，0,1,2,3,4,5...
        }

        // 获取上一周期的得分数组并排序
        array<Numeric> q1 = array_chg[1];  // 获取上一周期的得分数组
        Na1Sort2(q1,id1,1,GetArraySize(q1)-1,false);  // 对得分进行排序

        // 根据排序结果执行交易
        for i=1 to GetArraySize(id1)-1
        {
            if(i==1)  // 得分最高的品种
            {                
                if(data[id1[i]].MarketPosition <=0)  // 如果没有持多仓
                {
                    data[id1[i]].buy(1,open);  // 买入开仓
                }
            }
            else if(i == GetArraySize(id1)-1 )  // 得分最低的品种
            {
                if(data[id1[i]].MarketPosition >=0)  // 如果没有持空仓
                {
                    data[id1[i]].sellshort(1,open);  // 卖出开仓
                }
            }
            else  // 其他品种
            {
                data[id1[i]].sell(0,open);       // 平多仓
                data[id1[i]].BuyToCover(0,open); // 平空仓
                print("else date+time:"+text(date+time));
            }
        }
    }

//------------------------------------------------------------------------
// 原创：松鼠Quant
// 主页：quant789.com
// 公众号：松鼠Quant
// 编译版本    2025/02/24 120137
// 版权所有    songshu123
// 更改声明    TradeBlazer Software保留对TradeBlazer平台
//            每一版本的TradeBlazer公式修改和重写的权利
//------------------------------------------------------------------------
