← Back to skills
extension
Category: Data & AnalyticsNo API key required

小果量化因子库

小果量化因子库是一个集成了数百个技术指标、Alpha 因子和交易信号的 Python 量化因子计算系统。 以 `xg_factor_trader` 为顶层命名空间,提供批量引擎 `xg_factor_trader`、底层因子计算类 `xg_factor` (600+ 方法,含 WorldQuant alpha001~alpha191)、通达信底层函数库 `xg_tdx_func`、Alpha 批量函数版 `alpha`,以及远程数据/回测客户端 `xg_quant_backtrader_data`。支持股票、ETF、基金、可转债多品种的 单股因子计算与全市场批量并行计算,内置 608 因子配置表,可直接对接排序多因子 / 条件多因子 / Alpha 选股等下游策略。 适用人群:量化研究员、因子挖掘者、多因子选股开发、技术指标研究者、WorldQuant Alpha 研究者、ETF/基金轮动投资者。 触发关键词:小果因子、量化因子、因子计算、xg_factor、xg_factor_trader、xg_tdx_func、alpha101、alpha191、 WorldQuant、技术指标、因子选股、全市场因子、批量因子、因子表、单因子、多因子。

personAuthor: user_676c825dhubcommunity

小果量化因子库 专家

教程 https://gitcode.com/qq_50882340/xg_factor_trader

一、系统概述

小果量化因子库把「数百个技术指标 / 191 个 WorldQuant Alpha / 交易信号」封装成一套方法 + 一份因子表 + 一个批量引擎的统一形态。它做三件事:

  1. 算因子:给行情 → 得到数十~数百列因子;
  2. 批量管理:按 因子表.json 清单,对单只或全市场并行计算并落盘 parquet;
  3. 供下游:产出可直接喂给排序多因子 / 条件多因子 / Alpha 轮动等策略。

1.1 五大库/模块 + 一份配置

| 模块 | 类型 | 一句话职责 | |---|---|---| | xg_factor.py | 类 xg_factor | 底层因子计算类,600+ 因子实现为方法,含 alpha001~alpha191 | | xg_factor_trader.py | 类 xg_factor_trader | 批量调度引擎:读 parquet→按因子表→并行算→落盘 | | xg_tdx_func.py | 纯函数集 | 通达信语义指标函数,被 xg_factor 依赖 | | alpha.py | 纯函数集 | WorldQuant 官方风格的 191 个 alphaXXX(data, deps, win) | | xg_quant_backtrader_data.py | 类 | 远程小果后端 API:取行情/因子/财务/分钟 + 调策略回测 | | 因子表.json | 数据 | 608 条「因子名→调用串」,是批量清单 & 因子速查表 |

1.2 调用主链

数据源:本地 data/*.parquet (或远程 xg_quant_backtrader_data)
   ↓
xg_factor_trader(调度/并行/落盘)  ──(方法内)──>  xg_factor(算因子)
                                                        └── 依赖 ──> xg_tdx_func(通达信底层函数)
Alpha:路线A = xg_factor.alphaXXX() ; 路线B = alpha.py 官方批量版

二、安装与运行环境

依赖:pandas numpy scipy statsmodels empyrical pyarrow openpyxl tqdm requests scikit-learn。

pip install pandas numpy scipy statsmodels empyrical pyarrow openpyxl tqdm requests scikit-learn

源码目录 path 约定(引擎用 __file__ 定位,脚本必须与 data/ 同级):

<代码目录>/
├─ xg_factor.py / xg_factor_trader.py / xg_tdx_func.py / alpha.py / xg_quant_backtrader_data.py
├─ 因子表.json / 因子计算测试.py
└─ data/
   ├─ 历史数据/{证券代码}.parquet     # 输入行情(date/open/high/low/close/volume/amount)
   ├─ 指数数据/{指数}.parquet         # 可选:相对大盘因子
   ├─ 基金代码/基金代码.xlsx          # 可选:批量范围
   ├─ 可转债代码/可转债代码.xlsx       # 可选:批量范围
   ├─ 全部因子数据/{证券代码}.parquet # 输出:每只一个因子文件
   └─ 全部因子/全部因子.xlsx|json     # 输出:因子清单

规范导入(顶层包 xg_factor_trader):

from xg_factor_trader.xg_factor_trader import xg_factor_trader          # 引擎
from xg_factor_trader.xg_factor import xg_factor                        # 底层类
from xg_factor_trader.xg_tdx_func.xg_tdx_func import *                  # 通达信函数(可选)
from xg_factor_trader.alpha import alpha101                             # Alpha批量(可选)
from xg_factor_trader.xg_quant_backtrader_data import xg_quant_backtrader_data  # 远程API(可选)

同目录(未打成包)退化:from xg_factor import xg_factor / from xg_factor_trader import xg_factor_trader。

三、核心库一:xg_factor(底层因子计算类)

3.1 构造

models = xg_factor(df=<行情DataFrame>, index_df=<指数DataFrame可选>)

构造自动把列 close/open/high/low/volume/amount 重命名为 closePrice/openPrice/lowestPrice/highestPrice/turnoverVol/turnoverValue,并建立简写 C/H/L/O/V/AMOUNT(等价 close/high/low/open/volume/amount)。此后任意因子方法直接用简写取数。

3.2 调用(因子=方法)

df['MACD金叉'] = models.MACD_金叉()    # 信号→0/1/布尔
df['KDJ_K']    = models.KDJ_K()       # 数值序列
df['alpha101'] = models.alpha101()    # WorldQuant
df['beta5']    = models.roll_beta(n=5)  # 依赖 index_df

3.3 因子分类总览(逐族)

| 分类 | 代表方法 | |---|---| | 超卖超买 | RSI1/2/3、MARSI1/2、KDJ_K/D/J、SKDJ_K/D、WR1/2、LWR1/2、BIAS1/2/3、BIAS36_*、MTM_MTM、MTM_MTMMA、ACCER、CCI、MFI、UDL_*、VRSI1/2/3 | | 趋势类 | MACD_DIF/DEA/MACD、VMACD_*、SMACD_*、QACD_*、DMI_PDI/MDI/ADX/ADXR、TRIX_*、UOS_*、ASI_*、CHO_*、DMA_*、DPO_*、EMV_*、VTP_*、WVAD_*、JS_*、CYE_*、GDX_*、JLHB_*、BBI | | 能量/量能 | OBV_*、VR_*、AMO_*、VOL_XT_MAVOL1/2、HSL_*、BRAR_*、CR_*、MASS_*、WAD_*、PCNT_*、CYR_*、PSY_* | | 均线系统 | MA_XT_MA1~4、EXPMA_EXP1/2、HMA_HMA1~5、LMA_LMA1~5、VMA_VMA1~5、AMV_AMV1~4、ACD_*、BBIBOLL_*、ALLIGAT_*、GMMA_MA3~MA60 | | 路径类 | BOLL_BOLL/UB/LB、PBX_PBX1~6、ENE_*、MIKE_*、XS_*、TQN_* | | 停损/交易 | SAR、MA_交易_*、MACD_交易_*、KDJ_交易_*(含平空开多/平多开空) | | 神系 | SG_XDT_QR、SG_NDB_DK、SG_SMX_ZY1~3、SG_LB_*、SG_PF | | 龙系 | RAD_*、LON_*、SHT_*、ZLJC_JCS/JCM/JCL、ZLMM_*、SLZT_白龙~蓝龙、ADVOL_* | | 鬼系 | CYS、CYW | | 其他系 | JAX_J/A/X、XJDX_J/D/K、ZJTJ_*、BDZX_*、LHXJ_*、LYJH_*、JFZX_*、CYHT_*、BSQJ_*、CDP_STD_* | | Alpha | alpha001()~alpha191() | | 涨跌幅/统计 | cacal_zdf(n)、cacal_price_line_zdf(n)、cacal_line_line_zdf(n1,n2)、cacal_skew(n)、cacal_kurt(n)、SLOPE、STD、calculate_momentum_score(n)、HHVBARS、LLVBARS | | 滚动风险(依赖指数) | roll_alpha/beta/sharpe_ratio/annual_volatility/max_drawdown/up_capture/down_capture(n) | | 金叉/特色信号 | MACD_金叉/死叉、KDJ_KD金叉/死叉、RSI_金叉/死叉、WR_金叉、PSY_金叉/死叉、CROSS_UP/DOWN、六脉神剑、小波段交易、大波段交易、波段超级买卖 |

608 因子的精确「中文名→调用串」:因子表.json(value 即合法调用,如 "cacal_zdf(n=5)"、"KDJ_K()"),或 api.get_all_factor_table() 导出 Excel。

四、核心库二:xg_factor_trader(批量引擎)

4.1 初始化

api = xg_factor_trader(
    index_stock='000300.SH', start_date='20200101', end_date='20500101',
    max_workers=None, verbose=False, use_multiprocess=True,
    chunk_size=30, stage_size=200, use_async_io=True, force_recalc=False)

要点:

  • 构造时读 因子表.json → self.text;缺表会警告并 self.text={};
  • 自动建 data/全部因子数据/;
  • 批量范围优先级:基金代码.xlsx(合并可转债) > 历史数据/ 全部 parquet;
  • force_recalc=True = 强制覆盖重算;False = 增量(跳过 全部因子数据/ 已存在者)。

4.2 主要方法

| 方法 | 作用 | |---|---| | get_all_factor_table() | 导出 全部因子.xlsx/.json | | cacal_stock_factor(stock) | 单只算全部因子 → 全部因子数据/{stock}.parquet | | cacal_all_stock_factor() | 自动多进程/单进程算全市场 | | cacal_all_stock_factor_single() | 强制单进程分阶段 | | cacal_all_stock_factor_multiprocess() | 强制多进程分阶段 | | get_stock_data(code) / get_index_data() | 读单只行情 / 指数 | | get_factor_data(code) | 读某只已算好因子 parquet | | get_all_factor_data() | 合并全部已算因子(加 stock 列,慎用) | | adjust_price(df) | 复权 | | run_all_func() | 一键:清单→批量→因子例子参考 |

4.3 极简全流程

api = xg_factor_trader(index_stock='000300.SH', start_date='20240101',
                       max_workers=8, force_recalc=False)
api.get_all_factor_table()       # (可选)导出因子清单
api.cacal_all_stock_factor()     # 批量计算
df = api.get_factor_data('000001.SZ')
print(df.shape, df.columns.tolist())

五、核心库三:xg_tdx_func(通达信底层函数库)

对任意 Series/标量提供通达信语义函数(xg_factor 内部已 import *)。直接引:

from xg_factor_trader.xg_tdx_func.xg_tdx_func import *
MA(s,5) EMA(s,5) HHV(s,20) LLV(s,20) REF(s,1) RET(s,1) DIFF(s)
STD(s,5) SUM(s,5) CROSS(s, MA(s,5)) COUNT(s>m,10) EVERY(s>m,3)
EXIST(s>m,5) BARSLAST(s>m) VALUEWHEN(s>m, s) IF(cond,a,b) ABS/MAX/MIN
SLOPE(s,5) FORCAST(s,5) BACKSET(cond,1) ZIG / PEAK / TROUGH / SAR

(完整函数族见源码 xg_tdx_func.py。)

六、Alpha 两条路(WorldQuant)

  • 路线 A(推荐、可独立运行):xg_factor 内置 models.alpha001()…models.alpha191()(三位补零)。只需行情,依赖大盘者传 index_df。
  • 路线 B(官方批量函数版):alpha.py 提供 alphaXXX(data, dependencies=[...], max_window=N),语义同 WorldQuant 官方 alpha101 工程,返回多为标量。

    注意:alpha.py 调用的 MEAN/STD/TSRANK… 大写算子未随文件提供(官方工程配套)。生产请以路线 A为主;alpha.py 用于对照公式/校验口径。

七、数据层:xg_quant_backtrader_data(远程 API,可选)

连接小果服务器拉数据/调回测,非本地因子必需:

api = xg_quant_backtrader_data(url='服务器', port=8888, user=..., password=..., auth_code=...)
api.get_stock_hist_data(...)          # 行情
api.get_stock_factor_data(...)        # 因子
api.query_profit_data(...)            # 利润表(财务五表)
api.get_mini_data_5/15/30/60(...)     # 分钟线
api.xg_rank_factor_backtrader(...)    # 服务器端跑排序多因子回测
api.health()

(方法全清单与各签名见源码与教程「九」。)

八、输出数据结构

  • 每只因子文件 全部因子数据/{stock}.parquet:基础列 date,证券代码,证券名称,open,high,low,close,volume,amount(,zdf) + 每个因子一列(列名 = 因子表 key)。
  • 因子清单 全部因子.xlsx/.json:列 因子名称 / 因子函数。
  • 失败列表 全部因子数据/失败列表.xlsx。
  • 计算失败/窗口不足自动填 NaN,不影响其他因子。

九、常见问题

| 问题 | 处理 | |---|---| | 因子表.json 不存在 | 先准备/生成;否则 self.text={} 算不出 | | get_factor_data 空 | 先 cacal_stock_factor(code) | | 某股「数据文件不存在」 | 确认 历史数据/{code}.parquet 存在且 close/open>0 | | 相对大盘因子 NaN | 放 指数数据/{index_stock}.parquet 并传 index_df | | 想续跑 | force_recalc=False 自动跳过已算 | | 想重算 | force_recalc=True 覆盖 | | alpha.py 报 MEAN 未定义 | 走路线 A:models.alphaXXX() |

十、自定义因子 / 接入引擎

  1. 临时组合:models.C 做 pandas 计算,len==len(df) 即可;
  2. 通达信信号:CROSS(MA(models.C,5), MA(models.C,20));
  3. 进批量:在 xg_factor 加 def my_signal(self,n1=5,n2=20),再在 因子表.json 加 {"我的信号":"my_signal(n1=5,n2=20)"}。

十一、与下游策略对接

  • 因子 parquet 可直接作为排序多因子 / 条件多因子 / 动量 / Alpha 轮动的输入;
  • 或经 xg_quant_backtrader_data.xg_*_backtrader() 在服务器端回测。

全部源代码

以下收录本因子库全部源码模块,可直接查阅/复刻: xg_factor.py、xg_factor_trader.py、xg_tdx_func.py、alpha.py、xg_quant_backtrader_data.py、因子计算测试.py,以及 因子表.json。

源码模块:xg_factor.py

小果量化因子库底层因子计算类

from xg_tdx_func.xg_tdx_func import *
import empyrical as ep
import pandas as pd
import numpy as np
import os
from datetime import datetime, timedelta
import json
import warnings
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
from scipy import stats
import statsmodels.api as sm
import math
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning, module="pandas")

class xg_factor:
    '''
    小果因子库计算系统
    '''
    def __init__(self,
                df='',
                index_df='',):
        self.path = os.path.dirname(os.path.abspath(__file__))
        self.df = df.copy() if df is not None and not isinstance(df, str) and hasattr(df, 'copy') else df
        self.index_df = index_df.copy() if index_df is not None and not isinstance(index_df, str) and hasattr(index_df, 'copy') else index_df
        
        # 数据重命名(一次性完成)
        if isinstance(self.df, pd.DataFrame) and not self.df.empty:
            rename_dict = {
                "close": "closePrice",
                "open": "openPrice",
                "low": "lowestPrice",
                "high": "highestPrice",
                "volume": "turnoverVol",
                "amount": "turnoverValue"
            }
            # 只重命名存在的列
            self.df.rename(columns={k: v for k, v in rename_dict.items() if k in self.df.columns}, inplace=True)
            
            # 提取核心数据列(使用重命名后的列名)
            self.closePrice = self.df['closePrice'] if 'closePrice' in self.df.columns else pd.Series()
            self.openPrice = self.df['openPrice'] if 'openPrice' in self.df.columns else pd.Series()
            self.lowestPrice = self.df['lowestPrice'] if 'lowestPrice' in self.df.columns else pd.Series()
            self.highestPrice = self.df['highestPrice'] if 'highestPrice' in self.df.columns else pd.Series()
            self.turnoverVol = self.df['turnoverVol'] if 'turnoverVol' in self.df.columns else pd.Series()
            self.turnoverValue = self.df['turnoverValue'] if 'turnoverValue' in self.df.columns else pd.Series()
            
            # 统一简写命名(方便调用)
            self.C = self.closePrice
            self.H = self.highestPrice
            self.L = self.lowestPrice
            self.O = self.openPrice
            self.V = self.turnoverVol
            self.AMOUNT = self.turnoverValue
            
            # 保留原始简写(兼容旧代码)
            self.close = self.closePrice
            self.high = self.highestPrice
            self.low = self.lowestPrice
            self.open = self.openPrice
            self.volume = self.turnoverVol
            self.amount = self.turnoverValue
        else:
            # 空数据时的默认值
            self.closePrice = pd.Series()
            self.openPrice = pd.Series()
            self.lowestPrice = pd.Series()
            self.highestPrice = pd.Series()
            self.turnoverVol = pd.Series()
            self.turnoverValue = pd.Series()
            self.C = pd.Series()
            self.H = pd.Series()
            self.L = pd.Series()
            self.O = pd.Series()
            self.V = pd.Series()
            self.AMOUNT = pd.Series()
            self.close = pd.Series()
            self.high = pd.Series()
            self.low = pd.Series()
            self.open = pd.Series()
            self.volume = pd.Series()
            self.amount = pd.Series()

    # ========== 辅助函数 ==========
    def _sma(self, series, n, m):
        """SMA: 移动平均,alpha = m/n"""
        return series.ewm(adjust=False, alpha=m/n, min_periods=0, ignore_na=False).mean()
    
    def _tsrank(self, series, n):
        """TSRANK: 时间序列排名"""
        def rank_last(x):
            return stats.rankdata(x)[-1] / len(x) if len(x) > 0 else np.nan
        return series.rolling(window=n, min_periods=n).apply(rank_last)
    
    def _tsrank_fixed(self, series, n):
        """改进的TSRANK函数"""
        result = pd.Series(index=series.index, dtype=float)
        for i in range(len(series)):
            start = max(0, i - n + 1)
            window_data = series.iloc[start:i+1]
            valid_data = window_data.dropna()
            if len(valid_data) >= max(2, n // 2):
                current_val = series.iloc[i]
                rank = (valid_data < current_val).sum() + 1
                result.iloc[i] = rank / len(valid_data)
            else:
                result.iloc[i] = np.nan
        return result.fillna(method='ffill').fillna(method='bfill')
    
    def _decaylinear(self, series, n):
        """DECAYLINEAR: 线性衰减加权和"""
        w = np.arange(1, n + 1)
        return series.rolling(window=n, min_periods=n).apply(lambda x: np.dot(x, w))
    
    def _regbeta(self, y, x):
        """REGBETA: 回归beta"""
        y_vals = y.values
        x_vals = x.values if isinstance(x, pd.Series) else np.array(x)
        x_vals = sm.add_constant(x_vals)
        try:
            result = sm.OLS(y_vals, x_vals).fit()
            return result.params[1]
        except:
            return np.nan
    def six_pulse_excalibur_hist(self):
        '''
        六脉神剑
        '''
        
        markers=0
        signal=0
        #df=self.data.get_hist_data_em(stock=stock)
        CLOSE=self.C
        LOW=self.L
        HIGH=self.H
        DIFF=EMA(CLOSE,8)-EMA(CLOSE,13)
        DEA=EMA(DIFF,5)
        #如果满足DIFF>DEA 在1的位置标记1的图标
        #DRAWICON(DIFF>DEA,1,1);
        markers+=IF(DIFF>DEA,1,0)
        #如果满足DIFF<DEA 在1的位置标记2的图标
        #DRAWICON(DIFF<DEA,1,2);
        markers+=IF(DIFF<DEA,1,0)
        #DRAWTEXT(ISLASTBAR=1,1,'. MACD'),COLORFFFFFF;{微信公众号:尊重市场}
        ABC1=DIFF>DEA
        signal+=IF(ABC1,1,0)
        尊重市场1=(CLOSE-LLV(LOW,8))/(HHV(HIGH,8)-LLV(LOW,8))*100
        K=SMA(尊重市场1,3,1)
        D=SMA(K,3,1)
        #如果满足k>d 在2的位置标记1的图标
        markers+=IF(K>D,1,0)
        #DRAWICON(K>D,2,1);
        markers+=IF(K<D,1,0)
        #DRAWICON(K<D,2,2);
        #DRAWTEXT(ISLASTBAR=1,2,'. KDJ'),COLORFFFFFF;
        ABC2=K>D
        signal+=IF(ABC2,1,0)
        指标营地=REF(CLOSE,1)
        RSI1=(SMA(MAX(CLOSE-指标营地,0),5,1))/(SMA(ABS(CLOSE-指标营地),5,1))*100
        RSI2=(SMA(MAX(CLOSE-指标营地,0),13,1))/(SMA(ABS(CLOSE-指标营地),13,1))*100
        markers+=IF(RSI1>RSI2,1,0)
        #DRAWICON(RSI1>RSI2,3,1);
        markers+=IF(RSI1<RSI2,1,0)
        #DRAWICON(RSI1<RSI2,3,2);
        #DRAWTEXT(ISLASTBAR=1,3,'. RSI'),COLORFFFFFF;
        ABC3=RSI1>RSI2
        signal+=IF(ABC3,1,0)
        尊重市场=-(HHV(HIGH,13)-CLOSE)/(HHV(HIGH,13)-LLV(LOW,13))*100
        LWR1=SMA(尊重市场,3,1)
        LWR2=SMA(LWR1,3,1)
        #DRAWICON(LWR1>LWR2,4,1);
        markers+=IF(LWR1>LWR2,1,0)
        #DRAWICON(LWR1<LWR2,4,2);
        markers+=IF(LWR1<LWR2,1,0)
        #DRAWTEXT(ISLASTBAR=1,4,'. LWR'),COLORFFFFFF;
        ABC4=LWR1>LWR2
        signal+=IF(ABC4,1,0)
        BBI=(MA(CLOSE,3)+MA(CLOSE,5)+MA(CLOSE,8)+MA(CLOSE,13))/4
        #DRAWICON(CLOSE>BBI,5,1);
        markers+=IF(CLOSE>BBI,1,0)
        #DRAWICON(CLOSE<BBI,5,2);
        markers+=IF(CLOSE<BBI,1,0)
        #DRAWTEXT(ISLASTBAR=1,5,'. BBI'),COLORFFFFFF;
        ABC10=7
        ABC5=CLOSE>BBI
        signal+=IF(ABC5,1,0)
        MTM=CLOSE-REF(CLOSE,1)
        MMS=100*EMA(EMA(MTM,5),3)/EMA(EMA(ABS(MTM),5),3)
        MMM=100*EMA(EMA(MTM,13),8)/EMA(EMA(ABS(MTM),13),8)
        markers+=IF(MMS>MMM,1,0)
        #DRAWICON(MMS>MMM,6,1);
        markers+=IF(MMS<MMM,1,0)
        #DRAWICON(MMS<MMM,6,2);
        #DRAWTEXT(ISLASTBAR=1,6,'. ZLMM'),COLORFFFFFF;
        ABC6=MMS>MMM
        signal+=IF(ABC6,1,0)
        return signal
    def small_fruit_band_trading_1(self):
        '''
        小波段交易
        '''
        df=self.df
        CLOSE=self.C
        C=self.C
        LOW=self.L
        L=self.L
        HIGH=self.H
        H=self.H
        OPEN=self.O
        O=self.O
        volume=self.V
        V=self.V
        N1=7
        N2=5
        N3=3
        ABC1=(((HIGH + LOW)+(CLOSE*2)) / 4)
        ABC3=EMA(ABC1,N1)
        ABC4=STD(ABC1,N1)
        ABC5=((ABC1 - ABC3)*100) / ABC4
        ABC6=EMA(ABC5,N2)
        RK7=EMA(ABC6,N1)
        UP=(EMA(ABC6,10)+(100 / 2)) - 5
        DOWN=EMA(UP,N3)
        ACB1=EMA(DOWN,N3)
        ACB2=EMA(ACB1,N3)
        ACB3=EMA(ACB2,N3)
        ACB4=EMA(ACB3,N3)
        #STICKLINE(UP < REF(UP,1),UP,MA(UP,3),5,0),COLORBLUE;
        #STICKLINE(UP > REF(UP,1),UP,EMA(UP,3),5,0),COLORMAGENTA;
        df['柱子']=IF(UP > REF(UP,1),'红色','蓝色')
        df['买']=IF(AND(UP > REF(UP,1),REF(UP,1) < REF(UP,2)),'买',None)
        df['卖']=IF(AND(UP < REF(UP,1),REF(UP,1) > REF(UP,2)),'卖',None)
        #DRAWTEXT(UP > REF(UP,1)  AND  REF(UP,1) < REF(UP,2) ,UP,'买'),COLORRED;
        #DRAWTEXT(UP < REF(UP,1)  AND  REF(UP,1) > REF(UP,2) ,UP,'卖'),COLORGREEN;
        stats_list=[]
        for buy,sell in zip(df['买'].tolist(),df['卖'].tolist()):
            if buy=='买':
                stats_list.append(True)
            elif sell=='卖':
                stats_list.append(False)
            else:
                stats_list.append(None)
        df['stats']=stats_list
        df['stats']=df['stats'].fillna(method='ffill')
        return df['stats']
    def small_fruit_band_trading_2(self):
        '''
        大波段交易
        '''
        df=self.df
        CLOSE=self.C
        C=self.C
        LOW=self.L
        L=self.L
        HIGH=self.H
        H=self.H
        OPEN=self.O
        O=self.O
        volume=self.V
        V=self.V
        N1=18
        N2=15
        N3=12
        ABC1=(((HIGH + LOW)+(CLOSE*2)) / 4)
        ABC3=EMA(ABC1,N1)
        ABC4=STD(ABC1,N1)
        ABC5=((ABC1 - ABC3)*100) / ABC4
        ABC6=EMA(ABC5,N2)
        RK7=EMA(ABC6,N1)
        UP=(EMA(ABC6,10)+(100 / 2)) - 5
        DOWN=EMA(UP,N3)
        ACB1=EMA(DOWN,N3)
        ACB2=EMA(ACB1,N3)
        ACB3=EMA(ACB2,N3)
        ACB4=EMA(ACB3,N3)
        #STICKLINE(UP < REF(UP,1),UP,MA(UP,3),5,0),COLORBLUE;
        #STICKLINE(UP > REF(UP,1),UP,EMA(UP,3),5,0),COLORMAGENTA;
        df['柱子']=IF(UP > REF(UP,1),'红色','蓝色')
        df['买']=IF(AND(UP > REF(UP,1),REF(UP,1) < REF(UP,2)),'买',None)
        df['卖']=IF(AND(UP < REF(UP,1),REF(UP,1) > REF(UP,2)),'卖',None)
        #DRAWTEXT(UP > REF(UP,1)  AND  REF(UP,1) < REF(UP,2) ,UP,'买'),COLORRED;
        #DRAWTEXT(UP < REF(UP,1)  AND  REF(UP,1) > REF(UP,2) ,UP,'卖'),COLORGREEN;
        stats_list=[]
        for buy,sell in zip(df['买'].tolist(),df['卖'].tolist()):
            if buy=='买':
                stats_list.append(True)
            elif sell=='卖':
                stats_list.append(False)
            else:
                stats_list.append(None)
        df['stats']=stats_list
        df['stats']=df['stats'].fillna(method='ffill')
        return df['stats']
    def band_supe_buy_sell(self):
        '''
        波段超级买卖
        尊重市场1赋值:收盘价的6.5日[1日权重]移动平均
        尊重市场2赋值:收盘价的13.5日[1日权重]移动平均
        尊重市场11赋值:收盘价的3日[1日权重]移动平均
        尊重市场21赋值:收盘价的8日[1日权重]移动平均
        当满足条件尊重市场1>尊重市场2时,在尊重市场1和尊重市场2位置之间画柱状线,宽度为2.5,0不为0则画空心柱.,画红色,线宽为2
        当满足条件尊重市场2>尊重市场1时,在尊重市场1和尊重市场2位置之间画柱状线,宽度为2.5,0不为0则画空心柱.,画蓝色,线宽为2
        当满足条件尊重市场1上穿尊重市场2时,在最低价*0.98位置画5号图标
        当满足条件尊重市场21上穿尊重市场11时,在最高价*1.02位置书写文字,画黄色
        BBI赋值:(收盘价的3日简单移动平均+收盘价的6日简单移动平均+收盘价的12日简单移动平均+收盘价的24日简单移动平均)/4
        UPR赋值:BBI+3*BBI的13日估算标准差,线宽为2
        DWN赋值:BBI-3*BBI的13日估算标准差
        安全赋值:收盘价的60日简单移动平均,线宽为2
        LC赋值:1日前的收盘价
        RSI赋值:收盘价-LC和0的较大值的6日[1日权重]移动平均/收盘价-LC的绝对值的6日[1日权重]移动平均*100
        A7赋值:(2*收盘价+最高价+最低价)/4
        输出操作线:A7的5日简单移动平均,线宽为1
        操作线1赋值:A7的5日简单移动平均*1.03,线宽为2
        操作线2赋值:A7的5日简单移动平均*0.97,线宽为2
        输出ABC1:21日内A7的最低值
        输出ABC2:21日内A7的最高值
        SK赋值:(A7-ABC1)/(ABC2-ABC1)*100的7日指数移动平均
        SD赋值:0.667*1日前的SK+0.333*SK的5日指数移动平均
        当满足条件如果统计8日中满足收盘价<1日前的收盘价的天数/8>6/10ANDVOL>=1.5*成交量(手)的5日简单移动平均ANDCOUNT(SK>=SD,3)ANDREF(最低价,1)=120日内最低价的最低值,返回1,否则返回0时,在最低价*0.98位置画9号图标
        当满足条件如果统计13日中满足收盘价<1日前的收盘价的天数/13>6/10ANDCOUNT(SK>SD,6)ANDREF(最低价,5)=120日内最低价的最低值ANDREF(收盘价>=开盘价,4)ANDREF(收阳线,3)ANDREF(收阳线,2)ANDREF(开盘价>CLOS,返回?,否则返回?时,在,1)ANDOPEN>1日前的收盘价,1,0)位置书写文字 ,画黄色
        当满足条件如果统计13日中满足收盘价<1日前的收盘价的天数/13>6/10ANDCOUNT(SK>SD,6)ANDREF(最低价,5)=120日内最低价的最低值ANDREF(收盘价>=开盘价,4)ANDREF(收阳线,3)ANDREF(收阳线,2)ANDREF(开盘价>CLOS,返回?,否则返回?时,在,1)ANDOPEN>1日前的收盘价,1,0)位置画最低价*0.98号图标
        '''
        df=self.df
        CLOSE=self.C
        C=self.C
        LOW=self.L
        L=self.L
        HIGH=self.H
        H=self.H
        OPEN=self.O
        O=self.O
        volume=self.V
        V=self.V
        尊重市场1=SMA(C,6.5,1)
        尊重市场2=SMA(C,13.5,1)
        尊重市场11=SMA(C,3,1)
        尊重市场21=SMA(C,8,1)
        '''
        STICKLINE(尊重市场1>尊重市场2 , 尊重市场1,尊重市场2 ,2.5, 0),COLORRED,LINETHICK2;
        STICKLINE(尊重市场2>尊重市场1,尊重市场1,尊重市场2,2.5,0),COLORBLUE,LINETHICK2;
        '''
        df['柱子']=IF(尊重市场1>尊重市场2,'红色','蓝色')
        #DRAWICON( CROSS(尊重市场1,尊重市场2),L*0.98,5);
        df['笑脸']=CROSS(尊重市场1,尊重市场2)
        #DRAWTEXT(CROSS(尊重市场21,尊重市场11),H*1.02,''),COLORYELLOW;
        df['标记文字']=CROSS(尊重市场21,尊重市场11)
        BBI=(MA(CLOSE,3)+MA(CLOSE,6)+MA(CLOSE,12)+MA(CLOSE,24))/4
        UPR=BBI+3*STD(BBI,13)
        DWN=BBI-3*STD(BBI,13)
        安全=MA(CLOSE,60)
        LC=REF(CLOSE,1)
        RSI=SMA(MAX(CLOSE-LC,0),6,1)/SMA(ABS(CLOSE-LC),6,1)*100
        A7=(2*C+H+L)/4
        操作线=MA(A7,5)
        df['操作线']=操作线
        操作线1=MA(A7,5)*1.03
        df['操作线1']=操作线1
        操作线2=MA(A7,5)*0.97
        df['操作线2']=操作线2
        ABC1=LLV(A7,21)
        ABC2=HHV(A7,21)
        SK=EMA((A7-ABC1)/(ABC2-ABC1)*100,7)
        SD=EMA(0.667*REF(SK,1)+0.333*SK,5)
        '''
        DRAWICON(IF(COUNT(CLOSE<REF(CLOSE,1),8)/8>6/10 AND VOL>=1.5*MA(VOL,5) AND
        COUNT(SK>=SD,3) AND REF(LOW,1)=LLV(LOW,120),1,0),L*0.98,9);
        {DRAWTEXT(IF(COUNT(CLOSE<REF(CLOSE,1),8)/8>6/10 AND VOL>=1.5*MA(VOL,5) AND
        COUNT(SK>=SD,3) AND REF(LOW,1)=LLV(LOW,120),1,0),LOW*0.98,'底买') ,COLOR0099FF;}
        DRAWTEXT(IF(COUNT(CLOSE<REF(CLOSE,1),13)/13>6/10 AND
        COUNT(SK>SD,6) AND REF(LOW,5)=LLV(LOW,120) AND REF(CLOSE>=OPEN,4) AND
        REF(CLOSE>OPEN,3) AND REF(CLOSE>OPEN,2) AND REF(OPEN>CLOSE,1) AND
        OPEN>REF(CLOSE,1),1,0),LOW*0.98,'底买') ,COLORYELLOW;
        DRAWICON(IF(COUNT(CLOSE<REF(CLOSE,1),13)/13>6/10 AND
        COUNT(SK>SD,6) AND REF(LOW,5)=LLV(LOW,120) AND REF(CLOSE>=OPEN,4) AND
        REF(CLOSE>OPEN,3) AND REF(CLOSE>OPEN,2) AND REF(OPEN>CLOSE,1) AND
        OPEN>REF(CLOSE,1),1,0),L*0.98,9);
        '''
        趋势=CLOSE>=操作线
        df['趋势']=CLOSE>=操作线
        df['stats']=IF(AND(趋势,尊重市场1>尊重市场2),True,False)
        return df['stats']
    def KDJ_KD金叉(self):
        '''
        KDJ_KD金叉 的 Docstring
        '''
        K,D,J=KDJ(CLOSE=self.C,HIGH=self.H,LOW=self.L)
        result=CROSS(K,D)
        #result=IF(result==True,0,1)
        return result
    def KDJ_KD死叉(self):
        '''
        KDJ_KD金叉 的 Docstring
        '''
        K,D,J=KDJ(CLOSE=self.C,HIGH=self.H,LOW=self.L)
        result=CROSS(D,K)
        #result=IF(result==True,0,1)
        return result
    def RSI_金叉(self):
        '''
        RSI_金叉 的 Docstring
        '''
        RSI1,RSI2,RSI3=RSI(CLOSE=self.C)
        result=CROSS(RSI1,RSI2)
        #result=IF(result==True,0,1)
        return result
    def RSI_死叉(self):
        '''
        RSI_金叉 的 Docstring
        '''
        RSI1,RSI2,RSI3=RSI(CLOSE=self.C)
        result=CROSS(RSI2,RSI1)
        #result=IF(result==True,0,1)
        return result

    def WR_金叉(self):
        '''
        WR_金叉 的 Docstring
        '''
        WR1,WR2=WR(CLOSE=self.C,LOW=self.L,HIGH=self.H)
        result=CROSS(WR1,WR2)
        #result=IF(result==True,0,1)
        return result
    def WR_金叉(self):
        '''
        WR_金叉 的 Docstring
        '''
        WR1,WR2=WR(CLOSE=self.C,LOW=self.L,HIGH=self.H)
        result=CROSS(WR1,WR2)
        #result=IF(result==True,0,1)
        return result
    def MACD_金叉(self):
        '''
        MACD_金叉 的 Docstring
        '''
        DIF,DEA,MACD_1=MACD(CLOSE=self.C)
        result=CROSS(DIF,DEA)
        #result=IF(result==True,0,1)
        return result
    def MACD_死叉(self):
        '''
        MACD_金叉 的 Docstring
        '''
        DIF,DEA,MACD_1=MACD(CLOSE=self.C)
        result=CROSS(DEA,DIF)
        #result=IF(result==True,0,1)
        return result
    def PSY_金叉(self):
        '''
        PSY_金叉 的 Docstring
        '''
        PSY_1,PSYMA=PSY(CLOSE=self.C)
        result=CROSS(PSY_1,PSYMA)
        #result=IF(result==True,0,1)
        return result
    def PSY_死叉(self):
        '''
        PSY_金叉 的 Docstring
        '''
        PSY_1,PSYMA=PSY(CLOSE=self.C)
        result=CROSS(PSYMA,PSY_1)
        #result=IF(result==True,0,1)  
        return result
    def roll_alpha(self,n=5):
        '''
        5日alpha
        '''
        result=ep.roll_alpha(self.C.pct_change(),self.index_df['close'].pct_change(),window=n)
        return result
    def roll_beta(self,n=5):
        '''
        5日beta
        '''
        result=ep.roll_beta(self.C.pct_change(),self.index_df['close'].pct_change(),window=n)
        return result
    def roll_sharpe_ratio(self,n=5):
        '''
        5日夏普
        '''
        result=ep.roll_sharpe_ratio(self.C.pct_change(),window=n)
        return result
    def roll_annual_volatility(self,n=5):
        '''
        5日年华波动率
        '''
        result=ep.roll_annual_volatility(self.C.pct_change(),window=n)
        return result
    def roll_max_drawdown(self,n=5):
        '''
        5日最大回撤
        '''
        result=ep.roll_max_drawdown(self.C.pct_change(),window=n)
        return result
    def roll_up_capture(self,n=5):
        '''
        5日上涨捕获率
        '''
    
        result=ep.roll_up_capture(self.C.pct_change(),self.index_df['close'].pct_change(),window=n)
        return result
    def roll_down_capture(self,n=5):
        '''
        5日下跌捕获率
        '''
        result=ep.roll_down_capture(self.C.pct_change(),self.index_df['close'].pct_change(),window=n)
        return result
    
    
    




    






    # ========== 因子方法 ==========
    def SMA(self, period=5):
        """
        SMA
        """
        return MA(self.C, N=period)
    
    def CROSS_UP(self, n1=5, n2=10):
        """
        金叉判断
        """
        result = CROSS(MA(self.C, n1), MA(self.C, n2))
        return result
    
    def CROSS_DOWN(self, n1=10, n2=5):
        """
        死叉判断
        """
        result = CROSS(MA(self.C, n1), MA(self.C, n2))
        return result
    
    def BARSLASTCOUNT_UP(self):
        """
        连续上涨
        """
        return BARSLASTCOUNT(self.C > self.O)
    
    def BARSLASTCOUNT_DOWN(self):
        """
        连续下跌
        """
        return BARSLASTCOUNT(self.C < self.O)
    
    def PRICE_MA_LINE_ANAL(self, n=5):
        """
        价格在5均线上
        """
        #IF(self.C >= MA(self.C, n), 0, 1)
        return self.C >= MA(self.C, n)
    
    def MA_LINE_ANAL(self, n1=5, n2=10):
        """
        5均线在10均线上
        """
        #IF(MA(self.C, n1) >= MA(self.C, n2), 0, 1)
        return MA(self.C, n1) >= MA(self.C, n2)
    
    def HHVBARS(self, n=5):
        """
        5日最高值到当前周期
        """
        return HHVBARS(self.C, n)
    
    def LLVBARS(self, n=5):
        """
        5日最低值到当前周期
        """
        return LLVBARS(self.C, n)
    
    def cacal_zdf(self, n=5):
        """
        5日涨跌幅
        """
        return (self.C / REF(self.C, n) - 1) * 100
    def cacal_price_line_zdf(self, n=5):
        """
        价格距离5日均线涨跌幅
        """
        result=((self.C-MA(self.C,n))/MA(self.C,n))*100
        return result
    def cacal_line_line_zdf(self, n1=5,n2=10):
        """
        5日均线距离10日均线涨跌幅
        """
        result=((MA(self.C,n1)-MA(self.C,n2))/MA(self.C,n2))*100
        return result
    def cacal_skew(self,n=5):
        '''
        5日偏度
        '''
        result=self.C.rolling(window=n).skew()
        return result
    def cacal_kurt(self,n=5):
        '''
        5日峰度
        '''
        result=self.C.rolling(window=n).kurt()
        return result
    
    def calculate_momentum_score(self, n=3):
        """
        n日回归动量 - 返回时间序列
        """
        df = self.df.copy()
        mom_daily = n
        
        # 创建与df相同索引的Series,初始全部为NaN
        result = pd.Series(index=df.index, dtype=float)
        
        # 从 n-1 开始,因为需要至少 n 个数据点来计算
        for i in range(mom_daily - 1, len(df)):
            # 获取从 i-n+1 到 i 的窗口数据 (共 n 个数据点)
            start_idx = i - mom_daily + 1
            df_sub = df.iloc[start_idx:i+1].copy()
            
            # 检查数据是否足够
            if len(df_sub) < mom_daily:
                continue
            
            # 检查价格数据是否有效
            close_data = df_sub['closePrice'].values
            if np.any(np.isnan(close_data)) or np.any(np.isinf(close_data)) or np.any(close_data <= 0):
                continue
            
            try:
                y = np.log(close_data)
                y_len = len(y)
                weights = np.linspace(1, 2, y_len)
                x = np.arange(y_len)
                slope, intercept = np.polyfit(x, y, 1, w=weights)
                annualized_returns = math.pow(math.exp(slope), 250) - 1
                residuals = y - (slope * x + intercept)
                weighted_residuals = weights * residuals**2
                y_mean = np.mean(y)
                r_squared = 1 - (np.sum(weighted_residuals) / np.sum(weights * (y - y_mean)**2))
                score = annualized_returns * r_squared
                result.iloc[i] = score
            except Exception as e:
                continue
        
        return result
    
    def SLOPE(self, n=5):
        '''
        5日回归斜率
        '''
        result = SLOPE(self.close, N=n)
        return result
    
    def STD(self, n=5):
        '''
        5日标准差
        '''
        result = STD(self.close, N=n)
        return result

    # ===== 超卖超买类 =====

    def CCI(self):
        '''
        CCI商品路径指标
        '''
        TYP = (self.H + self.L + self.C) / 3
        result = (TYP - MA(TYP, 14)) * 1000 / (15 * AVEDEV(TYP, 14))
        return result

    def MFI(self):
        '''
        最近流量指标
        '''
        return MFI(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V, N=14)

    def MTM_MTM(self):
        '''动量线 - MTM值'''
        mtm_val, mtmma_val = MTM(CLOSE=self.C, N=12, M=6)
        return mtm_val

    def MTM_MTMMA(self):
        '''动量线 - MTMMA值'''
        mtm_val, mtmma_val = MTM(CLOSE=self.C, N=12, M=6)
        return mtmma_val


    def RSI1(self):
        '''相对强弱指标 - RSI1'''
        rsi1_val, rsi2_val, rsi3_val = RSI(CLOSE=self.C, N1=6, N2=12, N3=24)
        return rsi1_val

    def RSI2(self):
        '''相对强弱指标 - RSI2'''
        rsi1_val, rsi2_val, rsi3_val = RSI(CLOSE=self.C, N1=6, N2=12, N3=24)
        return rsi2_val

    def RSI3(self):
        '''相对强弱指标 - RSI3'''
        rsi1_val, rsi2_val, rsi3_val = RSI(CLOSE=self.C, N1=6, N2=12, N3=24)
        return rsi3_val

    def KDJ_K(self):
        '''KDJ指标 - K值'''
        k_val, d_val, j_val = KDJ(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3, M2=3)
        return k_val

    def KDJ_D(self):
        '''KDJ指标 - D值'''
        k_val, d_val, j_val = KDJ(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3, M2=3)
        return d_val

    def KDJ_J(self):
        '''KDJ指标 - J值'''
        k_val, d_val, j_val = KDJ(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3, M2=3)
        return j_val

    def SKDJ_K(self):
        '''慢速随机指标 - K值'''
        k_val, d_val = SKDJ(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=9, M=3)
        return k_val

    def SKDJ_D(self):
        '''慢速随机指标 - D值'''
        k_val, d_val = SKDJ(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=9, M=3)
        return d_val

    def UDL_UDL(self):
        '''引力线 - UDL值'''
        udl_val, maudl_val = UDL(CLOSE=self.C, N1=3, N2=5, N3=10, N4=20, M=6)
        return udl_val

    def UDL_MAUDL(self):
        '''引力线 - MAUDL值'''
        udl_val, maudl_val = UDL(CLOSE=self.C, N1=3, N2=5, N3=10, N4=20, M=6)
        return maudl_val

    def WR1(self):
        '''威廉指标 - WR1'''
        wr1_val, wr2_val = WR(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=10, N1=6)
        return wr1_val

    def WR2(self):
        '''威廉指标 - WR2'''
        wr1_val, wr2_val = WR(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=10, N1=6)
        return wr2_val

    def LWR1(self):
        '''LWR指标 - LWR1'''
        lwr1_val, lwr2_val = LWR(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=9, M1=3, M2=3)
        return lwr1_val

    def LWR2(self):
        '''LWR指标 - LWR2'''
        lwr1_val, lwr2_val = LWR(CLOSE=self.C, LOW=self.L, HIGH=self.H, N=9, M1=3, M2=3)
        return lwr2_val

    def MARSI1(self):
        '''相对强弱平均线 - RSI1'''
        rsi1_val, rsi2_val = MARSI(CLOSE=self.C, M1=10, M2=6)
        return rsi1_val

    def MARSI2(self):
        '''相对强弱平均线 - RSI2'''
        rsi1_val, rsi2_val = MARSI(CLOSE=self.C, M1=10, M2=6)
        return rsi2_val

    def BIAS1(self):
        '''乖离率 - BIAS1(6日)'''
        bias1_val, bias2_val, bias3_val = BIAS(CLOSE=self.C, N1=6, N2=12, N3=24)
        return bias1_val

    def BIAS2(self):
        '''乖离率 - BIAS2(12日)'''
        bias1_val, bias2_val, bias3_val = BIAS(CLOSE=self.C, N1=6, N2=12, N3=24)
        return bias2_val

    def BIAS3(self):
        '''乖离率 - BIAS3(24日)'''
        bias1_val, bias2_val, bias3_val = BIAS(CLOSE=self.C, N1=6, N2=12, N3=24)
        return bias3_val

    def BIAS_QL_BIAS(self):
        '''乖离率-传统版 - BIAS值'''
        bias_val, biasma_val = BIAS_QL(CLOSE=self.C, N=6, M=6)
        return bias_val

    def BIAS_QL_BIASMA(self):
        '''乖离率-传统版 - BIASMA值'''
        bias_val, biasma_val = BIAS_QL(CLOSE=self.C, N=6, M=6)
        return biasma_val

    def BIAS36_BIAS36(self):
        '''三六乖离 - BIAS36'''
        bias36_val, bias612_val, mabias_val = BIAS36(CLOSE=self.C, M=6)
        return bias36_val

    def BIAS36_BIAS612(self):
        '''三六乖离 - BIAS612'''
        bias36_val, bias612_val, mabias_val = BIAS36(CLOSE=self.C, M=6)
        return bias612_val

    def BIAS36_MABIAS(self):
        '''三六乖离 - MABIAS'''
        bias36_val, bias612_val, mabias_val = BIAS36(CLOSE=self.C, M=6)
        return mabias_val

    def ACCER(self):
        '''幅度涨速'''
        return ACCER(CLOSE=self.C, N=8)

    # ===== 趋势类型 =====

    def ASI_ASI(self):
        '''振动升降指标 - ASI'''
        asi_val, asit_val = ASI(OPEN=self.O, CLOSE=self.C, HIGH=self.H, LOW=self.L, M1=26, M2=10)
        return asi_val

    def ASI_ASIT(self):
        '''振动升降指标 - ASIT'''
        asi_val, asit_val = ASI(OPEN=self.O, CLOSE=self.C, HIGH=self.H, LOW=self.L, M1=26, M2=10)
        return asit_val

    def CHO_CHO(self):
        '''佳庆指标 - CHO'''
        cho_val, macho_val = CHO(CLOSE=self.C, OPEN=self.O, LOW=self.L, HIGH=self.H, VOL=self.V, N1=10, N2=20, M=6)
        return cho_val

    def CHO_MACHO(self):
        '''佳庆指标 - MACHO'''
        cho_val, macho_val = CHO(CLOSE=self.C, OPEN=self.O, LOW=self.L, HIGH=self.H, VOL=self.V, N1=10, N2=20, M=6)
        return macho_val

    def DMA_XT_DIF(self):
        '''平均差 - DIF'''
        dif_val, difma_val = DMA_XT(CLOSE=self.C, N1=10, N2=50, M=10)
        return dif_val

    def DMA_XT_DIFMA(self):
        '''平均差 - DIFMA'''
        dif_val, difma_val = DMA_XT(CLOSE=self.C, N1=10, N2=50, M=10)
        return difma_val

    def DMI_PDI(self):
        '''趋向指标 - PDI'''
        pdi_val, mdi_val, adx_val, adxr_val = DMI(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=14, M=6)
        return pdi_val

    def DMI_MDI(self):
        '''趋向指标 - MDI'''
        pdi_val, mdi_val, adx_val, adxr_val = DMI(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=14, M=6)
        return mdi_val

    def DMI_ADX(self):
        '''趋向指标 - ADX'''
        pdi_val, mdi_val, adx_val, adxr_val = DMI(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=14, M=6)
        return adx_val

    def DMI_ADXR(self):
        '''趋向指标 - ADXR'''
        pdi_val, mdi_val, adx_val, adxr_val = DMI(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=14, M=6)
        return adxr_val

    def DPO_DPO(self):
        '''区间震荡线 - DPO'''
        dpo_val, madpo_val = DPO(CLOSE=self.C, N=21, M=6)
        return dpo_val

    def DPO_MADPO(self):
        '''区间震荡线 - MADPO'''
        dpo_val, madpo_val = DPO(CLOSE=self.C, N=21, M=6)
        return madpo_val

    def EMV_EMV(self):
        '''简易波动指标 - EMV'''
        emv_val, maemv_val = EMV(HIGH=self.H, LOW=self.L, VOL=self.V, N=14, M=9)
        return emv_val

    def EMV_MAEMV(self):
        '''简易波动指标 - MAEMV'''
        emv_val, maemv_val = EMV(HIGH=self.H, LOW=self.L, VOL=self.V, N=14, M=9)
        return maemv_val

    def MACD_DIF(self):
        '''平滑异同平均线 - DIF'''
        dif_val, dea_val, macd_val = MACD(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return dif_val

    def MACD_DEA(self):
        '''平滑异同平均线 - DEA'''
        dif_val, dea_val, macd_val = MACD(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return dea_val

    def MACD_MACD(self):
        '''平滑异同平均线 - MACD'''
        dif_val, dea_val, macd_val = MACD(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return macd_val

    def VMACD_DIF(self):
        '''量平滑异同平均线 - DIF'''
        dif_val, dea_val, macd_val = VMACD(VOL=self.V, SHORT=12, LONG=26, MID=9)
        return dif_val

    def VMACD_DEA(self):
        '''量平滑异同平均线 - DEA'''
        dif_val, dea_val, macd_val = VMACD(VOL=self.V, SHORT=12, LONG=26, MID=9)
        return dea_val

    def VMACD_MACD(self):
        '''量平滑异同平均线 - MACD'''
        dif_val, dea_val, macd_val = VMACD(VOL=self.V, SHORT=12, LONG=26, MID=9)
        return macd_val

    def SMACD_DEA(self):
        '''单线平滑异同平均线 - DEA'''
        dea_val, macd_val = SMACD(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return dea_val

    def SMACD_MACD(self):
        '''单线平滑异同平均线 - MACD'''
        dea_val, macd_val = SMACD(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return macd_val

    def QACD_DIF(self):
        '''快速异同平均线 - DIF'''
        dif_val, macd_val, ddif_val = QACD(CLOSE=self.C, N1=12, N2=12, M=9)
        return dif_val

    def QACD_MACD(self):
        '''快速异同平均线 - MACD'''
        dif_val, macd_val, ddif_val = QACD(CLOSE=self.C, N1=12, N2=12, M=9)
        return macd_val

    def QACD_DDIF(self):
        '''快速异同平均线 - DDIF'''
        dif_val, macd_val, ddif_val = QACD(CLOSE=self.C, N1=12, N2=12, M=9)
        return ddif_val

    def TRIX_TRIX(self):
        '''三重指数平均线 - TRIX'''
        trix_val, matrix_val = TRIX(CLOSE=self.C, N=12, M=9)
        return trix_val

    def TRIX_MATRIX(self):
        '''三重指数平均线 - MATRIX'''
        trix_val, matrix_val = TRIX(CLOSE=self.C, N=12, M=9)
        return matrix_val

    def UOS_UOS(self):
        '''终极指标 - UOS'''
        uos_val, mauos_val = UOS(CLOSE=self.C, HIGH=self.H, LOW=self.L, N1=7, N2=14, N3=28, M=6)
        return uos_val

    def UOS_MAUOS(self):
        '''终极指标 - MAUOS'''
        uos_val, mauos_val = UOS(CLOSE=self.C, HIGH=self.H, LOW=self.L, N1=7, N2=14, N3=28, M=6)
        return mauos_val

    def VTP_VPT(self):
        '''量价曲线 - VPT'''
        vpt_val, mavp_val = VTP(CLOSE=self.C, VOL=self.V, N=51, M=6)
        return vpt_val

    def VTP_MAVP(self):
        '''量价曲线 - MAVP'''
        vpt_val, mavp_val = VTP(CLOSE=self.C, VOL=self.V, N=51, M=6)
        return mavp_val

    def WVAD_WVAD(self):
        '''威廉变异离散量 - WVAD'''
        wvad_val, mawvad_val = WVAD(CLOSE=self.C, OPEN=self.O, HIGH=self.H, LOW=self.L, VOL=self.V, N=24, M=6)
        return wvad_val

    def WVAD_MAWVAD(self):
        '''威廉变异离散量 - MAWVAD'''
        wvad_val, mawvad_val = WVAD(CLOSE=self.C, OPEN=self.O, HIGH=self.H, LOW=self.L, VOL=self.V, N=24, M=6)
        return mawvad_val

    def JS_JS(self):
        '''加数线 - JS'''
        js_val, majs1_val, majs2_val, majs3_val = JS(CLOSE=self.C, N=5, M1=5, M2=10, M3=20)
        return js_val

    def JS_MAJS1(self):
        '''加数线 - MAJS1'''
        js_val, majs1_val, majs2_val, majs3_val = JS(CLOSE=self.C, N=5, M1=5, M2=10, M3=20)
        return majs1_val

    def JS_MAJS2(self):
        '''加数线 - MAJS2'''
        js_val, majs1_val, majs2_val, majs3_val = JS(CLOSE=self.C, N=5, M1=5, M2=10, M3=20)
        return majs2_val

    def JS_MAJS3(self):
        '''加数线 - MAJS3'''
        js_val, majs1_val, majs2_val, majs3_val = JS(CLOSE=self.C, N=5, M1=5, M2=10, M3=20)
        return majs3_val

    def CYE_CYEL(self):
        '''市场趋势 - CYEL'''
        cyel_val, cyes_val = CYE(CLOSE=self.C)
        return cyel_val

    def CYE_CYES(self):
        '''市场趋势 - CYES'''
        cyel_val, cyes_val = CYE(CLOSE=self.C)
        return cyes_val

    def GDX_轨道(self):
        '''轨道线 - 轨道'''
        轨道_val, 压力线_val, 支撑线_val = GDX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30, M=9)
        return 轨道_val

    def GDX_压力线(self):
        '''轨道线 - 压力线'''
        轨道_val, 压力线_val, 支撑线_val = GDX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30, M=9)
        return 压力线_val

    def GDX_支撑线(self):
        '''轨道线 - 支撑线'''
        轨道_val, 压力线_val, 支撑线_val = GDX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30, M=9)
        return 支撑线_val

    def JLHB_B(self):
        '''绝路航标 - B'''
        b_val, var2_val, 绝路航标_val = JLHB(CLOSE=self.C, LOW=self.L,HIGH=self.H, N=7, M=5)
        return b_val

    def JLHB_VAR2(self):
        '''绝路航标 - VAR2'''
        b_val, var2_val, 绝路航标_val = JLHB(CLOSE=self.C, LOW=self.L,HIGH=self.H, N=7, M=5)
        return var2_val

    def JLHB_绝路航标(self):
        '''绝路航标 - 绝路航标'''
        b_val, var2_val, 绝路航标_val = JLHB(CLOSE=self.C, LOW=self.L,HIGH=self.H, N=7, M=5)
        return 绝路航标_val

    # ===== 能量类型 =====

    def BRAR_BR(self):
        '''情绪指标 - BR'''
        br_val, ar_val = BRAR(OPEN=self.O, HIGH=self.H, LOW=self.L,CLOSE=self.C, N=26)
        return br_val

    def BRAR_AR(self):
        '''情绪指标 - AR'''
        br_val, ar_val = BRAR(OPEN=self.O, HIGH=self.H, LOW=self.L,CLOSE=self.C, N=26)
        return ar_val

    def CR_CR(self):
        '''带状能量线 - CR'''
        cr_val, ma1_val, ma2_val, ma3_val, ma4_val = CR(HIGH=self.H, LOW=self.L, N=26, M1=10, M2=20, M3=40, M4=60)
        return cr_val

    def CR_MA1(self):
        '''带状能量线 - MA1'''
        cr_val, ma1_val, ma2_val, ma3_val, ma4_val = CR(HIGH=self.H, LOW=self.L, N=26, M1=10, M2=20, M3=40, M4=60)
        return ma1_val

    def CR_MA2(self):
        '''带状能量线 - MA2'''
        cr_val, ma1_val, ma2_val, ma3_val, ma4_val = CR(HIGH=self.H, LOW=self.L, N=26, M1=10, M2=20, M3=40, M4=60)
        return ma2_val

    def CR_MA3(self):
        '''带状能量线 - MA3'''
        cr_val, ma1_val, ma2_val, ma3_val, ma4_val = CR(HIGH=self.H, LOW=self.L, N=26, M1=10, M2=20, M3=40, M4=60)
        return ma3_val

    def CR_MA4(self):
        '''带状能量线 - MA4'''
        cr_val, ma1_val, ma2_val, ma3_val, ma4_val = CR(HIGH=self.H, LOW=self.L, N=26, M1=10, M2=20, M3=40, M4=60)
        return ma4_val

    def MASS_MASS(self):
        '''梅斯线 - MASS'''
        mass_val, mamass_val = MASS(HIGH=self.H, LOW=self.L, N1=9, N2=25, M=6)
        return mass_val

    def MASS_MAMASS(self):
        '''梅斯线 - MAMASS'''
        mass_val, mamass_val = MASS(HIGH=self.H, LOW=self.L, N1=9, N2=25, M=6)
        return mamass_val

    def PSY_PSY(self):
        '''心理线 - PSY'''
        psy_val, psyma_val = PSY(CLOSE=self.C, N=12, M=6)
        return psy_val

    def PSY_PSYMA(self):
        '''心理线 - PSYMA'''
        psy_val, psyma_val = PSY(CLOSE=self.C, N=12, M=6)
        return psyma_val

    def VR_VR(self):
        '''成交量变异率 - VR'''
        vr_val, mavr_val = VR(CLOSE=self.C,VOL=self.V, N=26, M=6)
        return vr_val

    def VR_MAVR(self):
        '''成交量变异率 - MAVR'''
        vr_val, mavr_val = VR(CLOSE=self.C,VOL=self.V, N=26, M=6)
        return mavr_val

    def WAD_WAD(self):
        '''威廉多空力度线 - WAD'''
        wad_val, mawad_val = WAD(CLOSE=self.C, LOW=self.L,HIGH=self.H, M=30)
        return wad_val

    def WAD_MAWAD(self):
        '''威廉多空力度线 - MAWAD'''
        wad_val, mawad_val = WAD(CLOSE=self.C, LOW=self.L,HIGH=self.H, M=30)
        return mawad_val

    def PCNT_PCNT(self):
        '''幅度比 - PCNT'''
        pcnt_val, mapcnt_val = PCNT(CLOSE=self.C, M=5)
        return pcnt_val

    def PCNT_MAPCNT(self):
        '''幅度比 - MAPCNT'''
        pcnt_val, mapcnt_val = PCNT(CLOSE=self.C, M=5)
        return mapcnt_val

    def CYR_CYR(self):
        '''市场强弱 - CYR'''
        cyr_val, macyr_val = CYR(AMOUNT=self.AMOUNT,VOL=self.V, N=13, M=5)
        return cyr_val

    def CYR_MACYR(self):
        '''市场强弱 - MACYR'''
        cyr_val, macyr_val = CYR(AMOUNT=self.AMOUNT,VOL=self.V, N=13, M=5)
        return macyr_val

    # ===== 能量型 =====

    def AMO_AMOW(self):
        '''成交金额 - AMOW'''
        amow_val, amo1_val, amo2_val = AMO(AMOUNT=self.AMOUNT, M1=5, M2=10)
        return amow_val

    def AMO_AMO1(self):
        '''成交金额 - AMO1'''
        amow_val, amo1_val, amo2_val = AMO(AMOUNT=self.AMOUNT, M1=5, M2=10)
        return amo1_val

    def AMO_AMO2(self):
        '''成交金额 - AMO2'''
        amow_val, amo1_val, amo2_val = AMO(AMOUNT=self.AMOUNT, M1=5, M2=10)
        return amo2_val

    def OBV_OBV(self):
        '''累积能量线 - OBV'''
        obv_val, maobv_val = OBV(VOL=self.V, CLOSE=self.C, M=30)
        return obv_val

    def OBV_MAOBV(self):
        '''累积能量线 - MAOBV'''
        obv_val, maobv_val = OBV(VOL=self.V, CLOSE=self.C, M=30)
        return maobv_val

    def VOL_XT_MAVOL1(self):
        '''成交量 - MAVOL1'''
        mavol1_val, mavol2_val = VOL_XT(VOL=self.V, M1=5, M2=10)
        return mavol1_val

    def VOL_XT_MAVOL2(self):
        '''成交量 - MAVOL2'''
        mavol1_val, mavol2_val = VOL_XT(VOL=self.V, M1=5, M2=10)
        return mavol2_val

    def VRSI1(self):
        '''相对强弱量 - RSI1'''
        rsi1_val, rsi2_val, rsi3_val = VRSI(VOL=self.V, N1=6, N2=12, N3=24)
        return rsi1_val

    def VRSI2(self):
        '''相对强弱量 - RSI2'''
        rsi1_val, rsi2_val, rsi3_val = VRSI(VOL=self.V, N1=6, N2=12, N3=24)
        return rsi2_val

    def VRSI3(self):
        '''相对强弱量 - RSI3'''
        rsi1_val, rsi2_val, rsi3_val = VRSI(VOL=self.V, N1=6, N2=12, N3=24)
        return rsi3_val

    def HSL_HSL(self):
        '''换手线 - HSL'''
        hsl_val, mahsl_val = HSL(HSL=self.V, N=5)
        return hsl_val

    def HSL_MAHSL(self):
        '''换手线 - MAHSL'''
        hsl_val, mahsl_val = HSL(HSL=self.V, N=5)
        return mahsl_val

    # ===== 均线系统 =====

    def MA_XT_MA1(self):
        '''均线 - MA1(5日)'''
        ma1_val, ma2_val, ma3_val, ma4_val = MA_XT(CLOSE=self.C, M1=5, M2=10, M3=20, M4=60)
        return ma1_val

    def MA_XT_MA2(self):
        '''均线 - MA2(10日)'''
        ma1_val, ma2_val, ma3_val, ma4_val = MA_XT(CLOSE=self.C, M1=5, M2=10, M3=20, M4=60)
        return ma2_val

    def MA_XT_MA3(self):
        '''均线 - MA3(20日)'''
        ma1_val, ma2_val, ma3_val, ma4_val = MA_XT(CLOSE=self.C, M1=5, M2=10, M3=20, M4=60)
        return ma3_val

    def MA_XT_MA4(self):
        '''均线 - MA4(60日)'''
        ma1_val, ma2_val, ma3_val, ma4_val = MA_XT(CLOSE=self.C, M1=5, M2=10, M3=20, M4=60)
        return ma4_val

    def ACD_ACD(self):
        '''升降线 - ACD'''
        acd_val, maacd_val = ACD(CLOSE=self.C, HIGH=self.H, LOW=self.L, M=20)
        return acd_val

    def ACD_MAACD(self):
        '''升降线 - MAACD'''
        acd_val, maacd_val = ACD(CLOSE=self.C, HIGH=self.H, LOW=self.L, M=20)
        return maacd_val

    def BBI(self):
        '''多空均线'''
        return BBI(CLOSE=self.C, M1=3, M2=6, M3=12, M4=24)

    def EXPMA_EXP1(self):
        '''指数平均线 - EXP1(12日)'''
        exp1_val, exp2_val = EXPMA(CLOSE=self.C, M1=12, M2=50)
        return exp1_val

    def EXPMA_EXP2(self):
        '''指数平均线 - EXP2(50日)'''
        exp1_val, exp2_val = EXPMA(CLOSE=self.C, M1=12, M2=50)
        return exp2_val

    def HMA_HMA1(self):
        '''高价平均线 - HMA1'''
        hma1_val, hma2_val, hma3_val, hma4_val, hma5_val = HMA(HIGH=self.H, M1=6, M2=12, M3=30, M4=70, M5=90)
        return hma1_val

    def HMA_HMA2(self):
        '''高价平均线 - HMA2'''
        hma1_val, hma2_val, hma3_val, hma4_val, hma5_val = HMA(HIGH=self.H, M1=6, M2=12, M3=30, M4=70, M5=90)
        return hma2_val

    def HMA_HMA3(self):
        '''高价平均线 - HMA3'''
        hma1_val, hma2_val, hma3_val, hma4_val, hma5_val = HMA(HIGH=self.H, M1=6, M2=12, M3=30, M4=70, M5=90)
        return hma3_val

    def HMA_HMA4(self):
        '''高价平均线 - HMA4'''
        hma1_val, hma2_val, hma3_val, hma4_val, hma5_val = HMA(HIGH=self.H, M1=6, M2=12, M3=30, M4=70, M5=90)
        return hma4_val

    def HMA_HMA5(self):
        '''高价平均线 - HMA5'''
        hma1_val, hma2_val, hma3_val, hma4_val, hma5_val = HMA(HIGH=self.H, M1=6, M2=12, M3=30, M4=70, M5=90)
        return hma5_val

    def LMA_LMA1(self):
        '''低价平均线 - LMA1'''
        lma1_val, lma2_val, lma3_val, lma4_val, lma5_val = LMA(LOW=self.L, M1=6, M2=12, M3=30, M4=70, M5=90)
        return lma1_val

    def LMA_LMA2(self):
        '''低价平均线 - LMA2'''
        lma1_val, lma2_val, lma3_val, lma4_val, lma5_val = LMA(LOW=self.L, M1=6, M2=12, M3=30, M4=70, M5=90)
        return lma2_val

    def LMA_LMA3(self):
        '''低价平均线 - LMA3'''
        lma1_val, lma2_val, lma3_val, lma4_val, lma5_val = LMA(LOW=self.L, M1=6, M2=12, M3=30, M4=70, M5=90)
        return lma3_val

    def LMA_LMA4(self):
        '''低价平均线 - LMA4'''
        lma1_val, lma2_val, lma3_val, lma4_val, lma5_val = LMA(LOW=self.L, M1=6, M2=12, M3=30, M4=70, M5=90)
        return lma4_val

    def LMA_LMA5(self):
        '''低价平均线 - LMA5'''
        lma1_val, lma2_val, lma3_val, lma4_val, lma5_val = LMA(LOW=self.L, M1=6, M2=12, M3=30, M4=70, M5=90)
        return lma5_val

    def VMA_VMA1(self):
        '''变异平均线 - VMA1'''
        vma1_val, vma2_val, vma3_val, vma4_val, vma5_val = VMA(HIGH=self.H, OPEN=self.O, LOW=self.L, CLOSE=self.C, M1=6, M2=12, M3=30, M4=70, M5=90)
        return vma1_val

    def VMA_VMA2(self):
        '''变异平均线 - VMA2'''
        vma1_val, vma2_val, vma3_val, vma4_val, vma5_val = VMA(HIGH=self.H, OPEN=self.O, LOW=self.L, CLOSE=self.C, M1=6, M2=12, M3=30, M4=70, M5=90)
        return vma2_val

    def VMA_VMA3(self):
        '''变异平均线 - VMA3'''
        vma1_val, vma2_val, vma3_val, vma4_val, vma5_val = VMA(HIGH=self.H, OPEN=self.O, LOW=self.L, CLOSE=self.C, M1=6, M2=12, M3=30, M4=70, M5=90)
        return vma3_val

    def VMA_VMA4(self):
        '''变异平均线 - VMA4'''
        vma1_val, vma2_val, vma3_val, vma4_val, vma5_val = VMA(HIGH=self.H, OPEN=self.O, LOW=self.L, CLOSE=self.C, M1=6, M2=12, M3=30, M4=70, M5=90)
        return vma4_val

    def VMA_VMA5(self):
        '''变异平均线 - VMA5'''
        vma1_val, vma2_val, vma3_val, vma4_val, vma5_val = VMA(HIGH=self.H, OPEN=self.O, LOW=self.L, CLOSE=self.C, M1=6, M2=12, M3=30, M4=70, M5=90)
        return vma5_val

    def AMV_AMV1(self):
        '''成本均线 - AMV1(5日)'''
        amv1_val, amv2_val, amv3_val, amv4_val = AMV(OPEN=self.O, CLOSE=self.C, VOL=self.V, M1=5, M2=13, M3=34, M4=60)
        return amv1_val

    def AMV_AMV2(self):
        '''成本均线 - AMV2(13日)'''
        amv1_val, amv2_val, amv3_val, amv4_val = AMV(OPEN=self.O, CLOSE=self.C, VOL=self.V, M1=5, M2=13, M3=34, M4=60)
        return amv2_val

    def AMV_AMV3(self):
        '''成本均线 - AMV3(34日)'''
        amv1_val, amv2_val, amv3_val, amv4_val = AMV(OPEN=self.O, CLOSE=self.C, VOL=self.V, M1=5, M2=13, M3=34, M4=60)
        return amv3_val

    def AMV_AMV4(self):
        '''成本均线 - AMV4(60日)'''
        amv1_val, amv2_val, amv3_val, amv4_val = AMV(OPEN=self.O, CLOSE=self.C, VOL=self.V, M1=5, M2=13, M3=34, M4=60)
        return amv4_val

    def BBIBOLL_BBIBOLL(self):
        '''多空布林线 - BBIBOLL'''
        bbiboll_val, upr_val, dwn_val = BBIBOLL(CLOSE=self.C, N=11, M=6)
        return bbiboll_val

    def BBIBOLL_UPR(self):
        '''多空布林线 - UPR'''
        bbiboll_val, upr_val, dwn_val = BBIBOLL(CLOSE=self.C, N=11, M=6)
        return upr_val

    def BBIBOLL_DWN(self):
        '''多空布林线 - DWN'''
        bbiboll_val, upr_val, dwn_val = BBIBOLL(CLOSE=self.C, N=11, M=6)
        return dwn_val

    def ALLIGAT_上唇(self):
        '''鳄鱼线 - 上唇'''
        上唇_val, 牙齿_val, 下颚_val = ALLIGAT(HIGH=self.H, LOW=self.L)
        return 上唇_val

    def ALLIGAT_牙齿(self):
        '''鳄鱼线 - 牙齿'''
        上唇_val, 牙齿_val, 下颚_val = ALLIGAT(HIGH=self.H, LOW=self.L)
        return 牙齿_val

    def ALLIGAT_下颚(self):
        '''鳄鱼线 - 下颚'''
        上唇_val, 牙齿_val, 下颚_val = ALLIGAT(HIGH=self.H, LOW=self.L)
        return 下颚_val

    def GMMA_MA3(self):
        '''顾比均线 - MA3'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma3_val

    def GMMA_MA5(self):
        '''顾比均线 - MA5'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma5_val

    def GMMA_MA8(self):
        '''顾比均线 - MA8'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma8_val

    def GMMA_MA10(self):
        '''顾比均线 - MA10'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma10_val

    def GMMA_MA12(self):
        '''顾比均线 - MA12'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma12_val

    def GMMA_MA15(self):
        '''顾比均线 - MA15'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma15_val

    def GMMA_MA30(self):
        '''顾比均线 - MA30'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma30_val

    def GMMA_MA35(self):
        '''顾比均线 - MA35'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma35_val

    def GMMA_MA40(self):
        '''顾比均线 - MA40'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma40_val

    def GMMA_MA45(self):
        '''顾比均线 - MA45'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma45_val

    def GMMA_MA50(self):
        '''顾比均线 - MA50'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma50_val

    def GMMA_MA60(self):
        '''顾比均线 - MA60'''
        ma3_val, ma5_val, ma8_val, ma10_val, ma12_val, ma15_val, ma30_val, ma35_val, ma40_val, ma45_val, ma50_val, ma60_val = GMMA(CLOSE=self.C)
        return ma60_val

    # ===== 路径类 =====

    def BOLL_BOLL(self):
        '''布林线 - BOLL'''
        boll_val, ub_val, lb_val = BOLL(CLOSE=self.C, M=20)
        return boll_val

    def BOLL_UB(self):
        '''布林线 - UB'''
        boll_val, ub_val, lb_val = BOLL(CLOSE=self.C, M=20)
        return ub_val

    def BOLL_LB(self):
        '''布林线 - LB'''
        boll_val, ub_val, lb_val = BOLL(CLOSE=self.C, M=20)
        return lb_val

    def PBX_PBX1(self):
        '''瀑布线 - PBX1'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx1_val

    def PBX_PBX2(self):
        '''瀑布线 - PBX2'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx2_val

    def PBX_PBX3(self):
        '''瀑布线 - PBX3'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx3_val

    def PBX_PBX4(self):
        '''瀑布线 - PBX4'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx4_val

    def PBX_PBX5(self):
        '''瀑布线 - PBX5'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx5_val

    def PBX_PBX6(self):
        '''瀑布线 - PBX6'''
        pbx1_val, pbx2_val, pbx3_val, pbx4_val, pbx5_val, pbx6_val = PBX(CLOSE=self.C, M1=4, M2=6, M3=9, M4=13, M5=18, M6=24)
        return pbx6_val

    def ENE_UPPER(self):
        '''轨道线 - UPPER'''
        upper_val, lower_val, ene_val = ENE(CLOSE=self.C, N=25, M1=6, M2=6)
        return upper_val

    def ENE_LOWER(self):
        '''轨道线 - LOWER'''
        upper_val, lower_val, ene_val = ENE(CLOSE=self.C, N=25, M1=6, M2=6)
        return lower_val

    def ENE_ENE(self):
        '''轨道线 - ENE'''
        upper_val, lower_val, ene_val = ENE(CLOSE=self.C, N=25, M1=6, M2=6)
        return ene_val

    def MIKE_STOR(self):
        '''麦克支撑压力 - STOR'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return stor_val

    def MIKE_MIDR(self):
        '''麦克支撑压力 - MIDR'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return midr_val

    def MIKE_WEKR(self):
        '''麦克支撑压力 - WEKR'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return wekr_val

    def MIKE_WEKS(self):
        '''麦克支撑压力 - WEKS'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return weks_val

    def MIKE_MIDS(self):
        '''麦克支撑压力 - MIDS'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return mids_val

    def MIKE_STOS(self):
        '''麦克支撑压力 - STOS'''
        stor_val, midr_val, wekr_val, weks_val, mids_val, stos_val = MIKE(HIGH=self.H, LOW=self.L, CLOSE=self.C, N=10)
        return stos_val

    def XS_SUP(self):
        '''薛斯通道 - SUP'''
        sup_val, sdn_val, lup_val, ldn_val = XS(CLOSE=self.C, VOL=self.V, N=13)
        return sup_val

    def XS_SDN(self):
        '''薛斯通道 - SDN'''
        sup_val, sdn_val, lup_val, ldn_val = XS(CLOSE=self.C, VOL=self.V, N=13)
        return sdn_val

    def XS_LUP(self):
        '''薛斯通道 - LUP'''
        sup_val, sdn_val, lup_val, ldn_val = XS(CLOSE=self.C, VOL=self.V, N=13)
        return lup_val

    def XS_LDN(self):
        '''薛斯通道 - LDN'''
        sup_val, sdn_val, lup_val, ldn_val = XS(CLOSE=self.C, VOL=self.V, N=13)
        return ldn_val

    def TQN_周期高点(self):
        '''唐奇安通道 - 周期高点'''
        周期高点_val, 周期低点_val, 平空开多_val, 平多开空_val = TQN(HIGH=self.H, LOW=self.L, X1=20, X2=20)
        return 周期高点_val

    def TQN_周期低点(self):
        '''唐奇安通道 - 周期低点'''
        周期高点_val, 周期低点_val, 平空开多_val, 平多开空_val = TQN(HIGH=self.H, LOW=self.L, X1=20, X2=20)
        return 周期低点_val

    def TQN_平空开多(self):
        '''唐奇安通道 - 平空开多信号'''
        周期高点_val, 周期低点_val, 平空开多_val, 平多开空_val = TQN(HIGH=self.H, LOW=self.L, X1=20, X2=20)
        return 平空开多_val

    def TQN_平多开空(self):
        '''唐奇安通道 - 平多开空信号'''
        周期高点_val, 周期低点_val, 平空开多_val, 平多开空_val = TQN(HIGH=self.H, LOW=self.L, X1=20, X2=20)
        return 平多开空_val

    # ===== 停损 =====

    def SAR(self):
        '''抛物线指标'''
        return SAR(HIGH=self.H, LOW=self.L, M=10, af=2, amax=20)

    # ===== 交易类型 =====

    def MA_交易_MA1(self):
        '''MA交易 - MA1(短期均线)'''
        ma1_val, ma2_val, 平空开多_val, 平多开空_val = MA_交易(CLOSE=self.C, SHORT=5, LONG=20)
        return ma1_val

    def MA_交易_MA2(self):
        '''MA交易 - MA2(长期均线)'''
        ma1_val, ma2_val, 平空开多_val, 平多开空_val = MA_交易(CLOSE=self.C, SHORT=5, LONG=20)
        return ma2_val

    def MA_交易_平空开多(self):
        '''MA交易 - 平空开多信号'''
        ma1_val, ma2_val, 平空开多_val, 平多开空_val = MA_交易(CLOSE=self.C, SHORT=5, LONG=20)
        return 平空开多_val

    def MA_交易_平多开空(self):
        '''MA交易 - 平多开空信号'''
        ma1_val, ma2_val, 平空开多_val, 平多开空_val = MA_交易(CLOSE=self.C, SHORT=5, LONG=20)
        return 平多开空_val

    def MACD_交易_DIFF(self):
        '''MACD交易 - DIFF'''
        diff_val, dea_val, macd_val, 平空开多_val, 平多开空_val = MACD_交易(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return diff_val

    def MACD_交易_DEA(self):
        '''MACD交易 - DEA'''
        diff_val, dea_val, macd_val, 平空开多_val, 平多开空_val = MACD_交易(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return dea_val

    def MACD_交易_MACD(self):
        '''MACD交易 - MACD'''
        diff_val, dea_val, macd_val, 平空开多_val, 平多开空_val = MACD_交易(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return macd_val

    def MACD_交易_平空开多(self):
        '''MACD交易 - 平空开多信号'''
        diff_val, dea_val, macd_val, 平空开多_val, 平多开空_val = MACD_交易(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return 平空开多_val

    def MACD_交易_平多开空(self):
        '''MACD交易 - 平多开空信号'''
        diff_val, dea_val, macd_val, 平空开多_val, 平多开空_val = MACD_交易(CLOSE=self.C, SHORT=12, LONG=26, MID=9)
        return 平多开空_val

    def KDJ_交易_K(self):
        '''KDJ交易 - K值'''
        k_val, d_val, j_val, 平空开多_val, 平多开空_val = KDJ_交易(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3)
        return k_val

    def KDJ_交易_D(self):
        '''KDJ交易 - D值'''
        k_val, d_val, j_val, 平空开多_val, 平多开空_val = KDJ_交易(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3)
        return d_val

    def KDJ_交易_J(self):
        '''KDJ交易 - J值'''
        k_val, d_val, j_val, 平空开多_val, 平多开空_val = KDJ_交易(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3)
        return j_val

    def KDJ_交易_平空开多(self):
        '''KDJ交易 - 平空开多信号'''
        k_val, d_val, j_val, 平空开多_val, 平多开空_val = KDJ_交易(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3)
        return 平空开多_val

    def KDJ_交易_平多开空(self):
        '''KDJ交易 - 平多开空信号'''
        k_val, d_val, j_val, 平空开多_val, 平多开空_val = KDJ_交易(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=9, M1=3)
        return 平多开空_val

    # ===== 神系 =====

    def SG_XDT_QR(self):
        '''心电图 - QR强弱指标'''
        qr_val, mqr1_val, mqr2_val = SG_XDT(CLOSE=self.C, INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return qr_val

    def SG_XDT_MQR1(self):
        '''心电图 - MQR1(5日均线)'''
        qr_val, mqr1_val, mqr2_val = SG_XDT(CLOSE=self.C, INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return mqr1_val

    def SG_XDT_MQR2(self):
        '''心电图 - MQR2(10日均线)'''
        qr_val, mqr1_val, mqr2_val = SG_XDT(CLOSE=self.C, INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return mqr2_val

    def SG_NDB_DK(self):
        '''脑电波 - DK'''
        dk_val, mdk1_val, mdk2_val = SG_NDB(CLOSE=self.C, HIGH=self.H, LOW=self.L, P1=5, P2=10)
        return dk_val

    def SG_NDB_MDK1(self):
        '''脑电波 - MDK1'''
        dk_val, mdk1_val, mdk2_val = SG_NDB(CLOSE=self.C, HIGH=self.H, LOW=self.L, P1=5, P2=10)
        return mdk1_val

    def SG_NDB_MDK2(self):
        '''脑电波 - MDK2'''
        dk_val, mdk1_val, mdk2_val = SG_NDB(CLOSE=self.C, HIGH=self.H, LOW=self.L, P1=5, P2=10)
        return mdk2_val

    def SG_SMX_ZY1(self):
        '''生命线 - ZY1(3日EMA)'''
        zy1_val, zy2_val, zy3_val = SG_SMX(CLOSE=self.C, HIGH=self.H, LOW=self.L, 
                                INDEXH=self.index_df['high'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXL=self.index_df['low'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                N=50)
        return zy1_val

    def SG_SMX_ZY2(self):
        '''生命线 - ZY2(17日EMA)'''
        zy1_val, zy2_val, zy3_val = SG_SMX(CLOSE=self.C, HIGH=self.H, LOW=self.L, 
                                INDEXH=self.index_df['high'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXL=self.index_df['low'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                N=50)
        return zy2_val

    def SG_SMX_ZY3(self):
        '''生命线 - ZY3(34日EMA)'''
        zy1_val, zy2_val, zy3_val = SG_SMX(CLOSE=self.C, HIGH=self.H, LOW=self.L, 
                                INDEXH=self.index_df['high'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXL=self.index_df['low'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                                N=50)
        return zy3_val

    def SG_LB_量比(self):
        '''量比'''
        量比_val, ma5_val, ma10_val = SG_LB(VOL=self.V, INDEXV=self.index_df['volume'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return 量比_val

    def SG_LB_MA5(self):
        '''量比 - MA5'''
        量比_val, ma5_val, ma10_val = SG_LB(VOL=self.V, INDEXV=self.index_df['volume'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return ma5_val

    def SG_LB_MA10(self):
        '''量比 - MA10'''
        量比_val, ma5_val, ma10_val = SG_LB(VOL=self.V, INDEXV=self.index_df['volume'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())
        return ma10_val

    def SG_PF(self):
        '''强势股评分'''
        return SG_PF(CLOSE=self.C, INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series())

    # ===== 龙系 =====

    def RAD_RADER1(self):
        '''威力雷达 - RADER1'''
        rader1_val, rader_ma_val = RAD(OPEN=self.O, HIGH=self.H, CLOSE=self.C, LOW=self.L,
                            INDEXO=self.index_df['open'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXH=self.index_df['high'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXL=self.index_df['low'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            D=3, S=30, M=30)
        return rader1_val

    def RAD_RADERMA(self):
        '''威力雷达 - RADERMA'''
        rader1_val, rader_ma_val = RAD(OPEN=self.O, HIGH=self.H, CLOSE=self.C, LOW=self.L,
                            INDEXO=self.index_df['open'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXH=self.index_df['high'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXL=self.index_df['low'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            INDEXC=self.index_df['close'] if hasattr(self, 'index_df') and not self.index_df.empty else pd.Series(),
                            D=3, S=30, M=30)
        return rader_ma_val

    def LON_LON(self):
        '''龙系长线 - LON'''
        lon_val, lonma_val, lont_val = LON(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V, N=10)
        return lon_val

    def LON_LONMA(self):
        '''龙系长线 - LONMA'''
        lon_val, lonma_val, lont_val = LON(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V, N=10)
        return lonma_val

    def LON_LONT(self):
        '''龙系长线 - LONT'''
        lon_val, lonma_val, lont_val = LON(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V, N=10)
        return lont_val

    def SHT_SHT(self):
        '''龙系短线 - SHT'''
        sht_val, shtma_val = SHT(CLOSE=self.C, VOL=self.V, N=5)
        return sht_val

    def SHT_SHTMA(self):
        '''龙系短线 - SHTMA'''
        sht_val, shtma_val = SHT(CLOSE=self.C, VOL=self.V, N=5)
        return shtma_val

    def ZLJC_JCS(self):
        '''主力进出 - JCS'''
        jcs_val, jcm_val, jcl_val = ZLJC(CLOSE=self.C, LOW=self.L, HIGH=self.H,VOL=self.V)
        return jcs_val

    def ZLJC_JCM(self):
        '''主力进出 - JCM'''
        jcs_val, jcm_val, jcl_val = ZLJC(CLOSE=self.C, LOW=self.L, HIGH=self.H,VOL=self.V)
        return jcm_val

    def ZLJC_JCL(self):
        '''主力进出 - JCL'''
        jcs_val, jcm_val, jcl_val = ZLJC(CLOSE=self.C, LOW=self.L, HIGH=self.H,VOL=self.V)
        return jcl_val

    def ZLMM_MMS(self):
        '''主力买卖 - MMS'''
        mms_val, mmm_val, mml_val = ZLMM(CLOSE=self.C)
        return mms_val

    def ZLMM_MMM(self):
        '''主力买卖 - MMM'''
        mms_val, mmm_val, mml_val = ZLMM(CLOSE=self.C)
        return mmm_val

    def ZLMM_MML(self):
        '''主力买卖 - MML'''
        mms_val, mmm_val, mml_val = ZLMM(CLOSE=self.C)
        return mml_val

    def SLZT_白龙(self):
        '''神龙在天 - 白龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 白龙_val

    def SLZT_黄龙(self):
        '''神龙在天 - 黄龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 黄龙_val

    def SLZT_紫龙(self):
        '''神龙在天 - 紫龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 紫龙_val

    def SLZT_青龙(self):
        '''神龙在天 - 青龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 青龙_val

    def SLZT_红龙(self):
        '''神龙在天 - 红龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 红龙_val

    def SLZT_蓝龙(self):
        '''神龙在天 - 蓝龙'''
        白龙_val, 黄龙_val, 紫龙_val, 青龙_val, 红龙_val, 蓝龙_val = SLZT(CLOSE=self.C, LOW=self.L,HIGH=self.H)
        return 蓝龙_val

    def ADVOL_ADVOL(self):
        '''龙系离散量 - ADVOL'''
        advol_val, ma1_val, ma2_val = ADVOL(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V)
        return advol_val

    def ADVOL_MA1(self):
        '''龙系离散量 - MA1'''
        advol_val, ma1_val, ma2_val = ADVOL(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V)
        return ma1_val

    def ADVOL_MA2(self):
        '''龙系离散量 - MA2'''
        advol_val, ma1_val, ma2_val = ADVOL(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V)
        return ma2_val

    # ===== 鬼系 =====

    def CYS(self):
        '''市场盈亏'''
        return CYS(CLOSE=self.C, AMOUNT=self.AMOUNT, VOL=self.V)

    

    def CYW(self):
        '''主力控盘'''
        return CYW(CLOSE=self.C, HIGH=self.H, LOW=self.L, VOL=self.V)

    # ===== 其他系 =====

    def JAX_J(self):
        '''济安线 - J'''
        j_val, a_val, x_val = JAX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30)
        return j_val

    def JAX_A(self):
        '''济安线 - A'''
        j_val, a_val, x_val = JAX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30)
        return a_val

    def JAX_X(self):
        '''济安线 - X'''
        j_val, a_val, x_val = JAX(CLOSE=self.C, HIGH=self.H, LOW=self.L, N=30)
        return x_val

    def XJDX_J(self):
        '''超级短线 - J'''
        j_val, d_val, k_val = XJDX(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return j_val

    def XJDX_D(self):
        '''超级短线 - D'''
        j_val, d_val, k_val = XJDX(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return d_val

    def XJDX_K(self):
        '''超级短线 - K'''
        j_val, d_val, k_val = XJDX(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return k_val

    def ZJTJ_无庄控盘(self):
        '''庄家抬轿 - 无庄控盘'''
        无庄控盘_val, 开始控盘_val, 有庄控盘_val, 主力出货_val = ZJTJ(CLOSE=self.C)
        return 无庄控盘_val

    def ZJTJ_开始控盘(self):
        '''庄家抬轿 - 开始控盘'''
        无庄控盘_val, 开始控盘_val, 有庄控盘_val, 主力出货_val = ZJTJ(CLOSE=self.C)
        return 开始控盘_val

    def ZJTJ_有庄控盘(self):
        '''庄家抬轿 - 有庄控盘'''
        无庄控盘_val, 开始控盘_val, 有庄控盘_val, 主力出货_val = ZJTJ(CLOSE=self.C)
        return 有庄控盘_val

    def ZJTJ_主力出货(self):
        '''庄家抬轿 - 主力出货'''
        无庄控盘_val, 开始控盘_val, 有庄控盘_val, 主力出货_val = ZJTJ(CLOSE=self.C)
        return 主力出货_val

    
    def BDZX_AK(self):
        '''波段之星 - AK'''
        ak_val, ad1_val, aj_val, aa_val, bb_val, cc_val, 买进_val, 卖出_val = BDZX(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return ak_val

    def BDZX_AD1(self):
        '''波段之星 - AD1'''
        ak_val, ad1_val, aj_val, aa_val, bb_val, cc_val, 买进_val, 卖出_val = BDZX(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return ad1_val

    def BDZX_AJ(self):
        '''波段之星 - AJ'''
        ak_val, ad1_val, aj_val, aa_val, bb_val, cc_val, 买进_val, 卖出_val = BDZX(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return aj_val

    def BDZX_买进(self):
        '''波段之星 - 买进信号'''
        ak_val, ad1_val, aj_val, aa_val, bb_val, cc_val, 买进_val, 卖出_val = BDZX(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return 买进_val

    def BDZX_卖出(self):
        '''波段之星 - 卖出信号'''
        ak_val, ad1_val, aj_val, aa_val, bb_val, cc_val, 买进_val, 卖出_val = BDZX(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return 卖出_val

    def LHXJ_主力弃盘(self):
        '''猎狐先觉 - 主力弃盘'''
        主力弃盘_val, 主力控盘_val = LHXJ(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return 主力弃盘_val

    def LHXJ_主力控盘(self):
        '''猎狐先觉 - 主力控盘'''
        主力弃盘_val, 主力控盘_val = LHXJ(HIGH=self.H, LOW=self.L, CLOSE=self.C)
        return 主力控盘_val

    def LYJH_机构做空能量线(self):
        '''猎鹰歼狐 - 机构做空能量线'''
        机构做空能量线_val, 机构做多能量线_val, lh_val, lh1_val = LYJH(CLOSE=self.C, HIGH=self.H, LOW=self.L, M=80, M1=50)
        return 机构做空能量线_val

    def LYJH_机构做多能量线(self):
        '''猎鹰歼狐 - 机构做多能量线'''
        机构做空能量线_val, 机构做多能量线_val, lh_val, lh1_val = LYJH(CLOSE=self.C, HIGH=self.H, LOW=self.L, M=80, M1=50)
        return 机构做多能量线_val

    def JFZX_多头力量(self):
        '''飓风智能中线 - 多头力量'''
        多头力量_val, 空头力量_val, 多空平衡_val = JFZX(OPEN=self.O, CLOSE=self.C, VOL=self.V, N=30)
        return 多头力量_val

    def JFZX_空头力量(self):
        '''飓风智能中线 - 空头力量'''
        多头力量_val, 空头力量_val, 多空平衡_val = JFZX(OPEN=self.O, CLOSE=self.C, VOL=self.V, N=30)
        return 空头力量_val

    def CYHT_SK(self):
        '''财运亨通 - SK'''
        高抛_val, sk_val, sd_val, 低吸_val, 强弱分界_val, 卖出_val, 买进_val = CYHT(CLOSE=self.C, HIGH=self.H, LOW=self.L, OPEN=self.O)
        return sk_val

    def CYHT_SD(self):
        '''财运亨通 - SD'''
        高抛_val, sk_val, sd_val, 低吸_val, 强弱分界_val, 卖出_val, 买进_val = CYHT(CLOSE=self.C, HIGH=self.H, LOW=self.L, OPEN=self.O)
        return sd_val

    def CYHT_卖出(self):
        '''财运亨通 - 卖出信号'''
        高抛_val, sk_val, sd_val, 低吸_val, 强弱分界_val, 卖出_val, 买进_val = CYHT(CLOSE=self.C, HIGH=self.H, LOW=self.L, OPEN=self.O)
        return 卖出_val

    def CYHT_买进(self):
        '''财运亨通 - 买进信号'''
        高抛_val, sk_val, sd_val, 低吸_val, 强弱分界_val, 卖出_val, 买进_val = CYHT(CLOSE=self.C, HIGH=self.H, LOW=self.L, OPEN=self.O)
        return 买进_val

    def BSQJ_B买(self):
        '''买卖区间 - B买信号'''
        b买_val, 持仓_val, s卖_val, 空仓_val = BSQJ(CLOSE=self.C)
        return b买_val

    def BSQJ_持仓(self):
        '''买卖区间 - 持仓信号'''
        b买_val, 持仓_val, s卖_val, 空仓_val = BSQJ(CLOSE=self.C)
        return 持仓_val

    def BSQJ_S卖(self):
        '''买卖区间 - S卖信号'''
        b买_val, 持仓_val, s卖_val, 空仓_val = BSQJ(CLOSE=self.C)
        return s卖_val

    def BSQJ_空仓(self):
        '''买卖区间 - 空仓信号'''
        b买_val, 持仓_val, s卖_val, 空仓_val = BSQJ(CLOSE=self.C)
        return 空仓_val

    def CDP_STD_CDP(self):
        '''逆势操作 - CDP'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return cdp_val

    def CDP_STD_AH(self):
        '''逆势操作 - AH'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return ah_val

    def CDP_STD_NH(self):
        '''逆势操作 - NH'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return nh_val

    def CDP_STD_NL(self):
        '''逆势操作 - NL'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return nl_val

    def CDP_STD_AL(self):
        '''逆势操作 - AL'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return al_val








































    # ===== Alpha因子 =====

    def alpha001(self, max_window=6):
        """
        (-1 * CORR(RANK(DELTA(LOG(VOLUME),1)), RANK((CLOSE-OPEN)/OPEN), 6))
        """
        rank_sizenl = np.log(self.V).diff(1).rank(axis=0, pct=True)
        rank_ret = ((self.C - self.O) / self.O).rank(axis=0, pct=True)
        return -1 * rank_sizenl.rolling(window=max_window, min_periods=max_window).corr(rank_ret)
    
    def alpha002(self, max_window=2):
        """
        -1*delta(((close-low)-(high-close))/(high-low),1)
        """
        win_ratio = (max_window * self.C - self.L - self.H) / (self.H - self.L)
        return -1 * win_ratio.diff(1)
    
    def alpha003(self):
        """
        -1*SUM((CLOSE=DELAY(CLOSE,1)?0:CLOSE-(CLOSE>DELAY(CLOSE,1)?MIN(LOW,DELAY(CLOSE,1)):MAX(HIGH,DELAY(CLOSE,1)))),6)
        """
        alpha = self.C.copy()
        condition2 = self.C.diff(periods=1) > 0.0
        condition3 = self.C.diff(periods=1) < 0.0
        alpha[condition2] = self.C[condition2] - np.minimum(self.C[condition2].shift(1).replace(np.NaN, 10000), self.L[condition2])
        alpha[condition3] = self.C[condition3] - np.maximum(self.C[condition3].shift(1).replace(np.NaN, 0), self.H[condition3])
        return -1 * alpha.sum(axis=0)

    def alpha004(self, max_window=20):
        """
        (((SUM(CLOSE,8)/8)+STD(CLOSE,8))<(SUM(CLOSE,2)/2))
        ?-1:(SUM(CLOSE,2)/2<(SUM(CLOSE,8)/8-STD(CLOSE,8))
            ?1:(1<=(VOLUME/MEAN(VOLUME,20))
                ?1:-1))
        """
        ma8 = self.C.rolling(window=8, min_periods=8).mean()
        std8 = self.C.rolling(window=8, min_periods=8).std()
        ma2 = self.C.rolling(window=2, min_periods=2).mean()
        ma20_vol = self.V.rolling(window=max_window, min_periods=max_window).mean()
        
        result = np.where(
            (ma8 + std8) < ma2,
            -1,
            np.where(
                ma2 < (ma8 - std8),
                1,
                np.where(1 <= (self.V / ma20_vol), 1, -1)
            )
        )
        return pd.Series(result, index=self.df.index, name='alpha004')

    # ... 继续 alpha005 到 alpha191(保持原有代码不变)
    def alpha005(self):
        """
        -1*TSMAX(CORR(TSRANK(VOLUME,5),TSRANK(HIGH,5),5),3)
        """
        ts_volume = self.V.rolling(window=5, min_periods=5).apply(lambda x: stats.rankdata(x)[-1] / 5.0)
        ts_high = self.H.rolling(window=5, min_periods=5).apply(lambda x: stats.rankdata(x)[-1] / 5.0)
        corr_ts = ts_volume.rolling(window=5, min_periods=5).corr(ts_high)
        return -1 * corr_ts.rolling(window=3, min_periods=3).max()
    
    def alpha006(self):
        """
        -1*RANK(SIGN(DELTA(OPEN*0.85+HIGH*0.15,4)))
        """
        weighted_price = self.O * 0.85 + self.H * 0.15
        delta = weighted_price.diff(periods=4)
        sign_val = np.sign(delta)
        rank_val = sign_val.rank(axis=0, pct=True)
        return -1 * rank_val
    
    def alpha007(self):
        """
        (RANK(MAX(VWAP-CLOSE,3))+RANK(MIN(VWAP-CLOSE,3)))*RANK(DELTA(VOLUME,3))
        """
        vwap = self.AMOUNT / self.V
        part1 = (vwap - self.C).rolling(window=3, min_periods=3).max().rank(axis=0, pct=True)
        part2 = (vwap - self.C).rolling(window=3, min_periods=3).min().rank(axis=0, pct=True)
        part3 = self.V.diff(3).rank(axis=0, pct=True)
        return (part1 + part2) * part3
    
    def alpha008(self):
        """
        -1*RANK(DELTA((HIGH+LOW)/10+VWAP*0.8,4))
        """
        vwap = self.AMOUNT / self.V
        ma_price = (self.H + self.L) / 10 + vwap * 0.8
        return -1 * ma_price.diff(4).rank(axis=0, pct=True)
    
    def alpha009(self):
        """
        SMA(((HIGH+LOW)/2-(DELAY(HIGH,1)+DELAY(LOW,1))/2)*(HIGH-LOW)/VOLUME,7,2)
        """
        part1 = (self.H + self.L) * 0.5 - (self.H.shift(1) + self.L.shift(1)) * 0.5
        part2 = part1 * (self.H - self.L) / self.V
        return part2.ewm(adjust=False, alpha=float(2) / 7, min_periods=7).mean()
    
    def alpha010(self):
        """
        RANK(MAX(((RET<0)?STD(RET,20):CLOSE)^2,5))
        """
        ret = self.C.pct_change(periods=1)
        std_ret = ret.rolling(window=20, min_periods=20).std()
        part1 = np.where(ret < 0, std_ret, self.C)
        part1 = pd.Series(part1, index=self.df.index)
        return (part1 ** 2).rolling(window=5, min_periods=5).max().rank(axis=0, pct=True)
    
    def alpha011(self):
        """
        SUM(((CLOSE-LOW)-(HIGH-CLOSE))/(HIGH-LOW)*VOLUME,6)
        """
        raw = ((2 * self.C - self.L - self.H) / (self.H - self.L)) * self.V
        return raw.rolling(window=6, min_periods=6).sum()
    
    def alpha012(self):
        """
        RANK(OPEN-MA(VWAP,10))*RANK(ABS(CLOSE-VWAP))*(-1)
        """
        vwap = self.AMOUNT / self.V
        part1 = (self.O - vwap.rolling(window=10, min_periods=10).mean()).rank(axis=0, pct=True)
        part2 = abs(self.C - vwap).rank(axis=0, pct=True)
        return -1 * part1 * part2
    
    def alpha013(self):
        """
        ((HIGH*LOW)^0.5)-VWAP
        """
        vwap = self.AMOUNT / self.V
        return np.sqrt(self.H * self.L) - vwap
    
    def alpha014(self):
        """
        CLOSE-DELAY(CLOSE,5)
        """
        return self.C.diff(5)
    
    def alpha015(self):
        """
        OPEN/DELAY(CLOSE,1)-1
        """
        return self.O / self.C.shift(1) - 1.0
    
    def alpha016(self):
        """
        (-1*TSMAX(RANK(CORR(RANK(VOLUME),RANK(VWAP),5)),5))
        """
        vwap = self.AMOUNT / self.V
        rank_vol = self.V.rank(axis=0, pct=True)
        rank_vwap = vwap.rank(axis=0, pct=True)
        corr_vol_vwap = rank_vol.rolling(window=5, min_periods=5).corr(rank_vwap)
        rank_corr = corr_vol_vwap.rank(axis=0, pct=True)
        return -1 * rank_corr.rolling(window=5, min_periods=5).max()
    
    def alpha017(self):
        """
        RANK(VWAP-MAX(VWAP,15))^DELTA(CLOSE,5)
        """
        vwap = self.AMOUNT / self.V
        delta_price = self.C.diff(5)
        base = (vwap - vwap.rolling(window=15, min_periods=15).max()).rank(axis=0, pct=True)
        return base ** delta_price
    
    def alpha018(self):
        """
        CLOSE/DELAY(CLOSE,5)
        """
        return self.C / self.C.shift(5)
    
    def alpha019(self):
        """
        (CLOSE<DELAY(CLOSE,5)?(CLOSE/DELAY(CLOSE,5)-1):(CLOSE=DELAY(CLOSE,5)?0:(1-DELAY(CLOSE,5)/CLOSE)))
        """
        condition1 = self.C <= self.C.shift(5)
        alpha = self.C.copy()
        alpha[condition1] = self.C.pct_change(periods=5)[condition1]
        alpha[~condition1] = -self.C.pct_change(periods=5)[~condition1]
        return alpha
    
    def alpha020(self):
        """
        (CLOSE/DELAY(CLOSE,6)-1)*100
        """
        return self.C.pct_change(periods=6) * 100.0
    
    def alpha021(self):
        """
        REGBETA(MEAN(CLOSE,6),SEQUENCE(6))
        """
        close_ma = self.C.rolling(window=6, min_periods=6).mean()
        result = pd.Series(index=self.df.index, dtype=float)
        for i in range(6, len(self.df)):
            y = close_ma.iloc[i-6:i]
            x = np.arange(1, 7)
            result.iloc[i] = self._regbeta(y, x)
        return result.fillna(0)
    
    def alpha022(self):
        """
        SMEAN((CLOSE/MEAN(CLOSE,6)-1-DELAY(CLOSE/MEAN(CLOSE,6)-1,3)),12,1)
        """
        ratio = self.C / self.C.rolling(window=6, min_periods=6).mean() - 1.0
        alpha = ratio.diff(3)
        return self._sma(alpha, 12, 1)
    
    def alpha023(self):
        """
        SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1) / 
        (SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)+SMA((CLOSE<=DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1))*100
        """
        prc_std = self.C.rolling(window=20, min_periods=20).std()
        condition1 = self.C > self.C.shift(1)
        part1 = prc_std.copy()
        part2 = prc_std.copy()
        part1[~condition1] = 0.0
        part2[condition1] = 0.0
        sma1 = self._sma(part1, 20, 1)
        sma2 = self._sma(part2, 20, 1)
        return sma1 / (sma1 + sma2) * 100
    
    def alpha024(self):
        """
        SMA(CLOSE-DELAY(CLOSE,5),5,1)
        """
        return self._sma(self.C.diff(5), 5, 1)
    
    def alpha025(self):
        """
        (-1*RANK(DELTA(CLOSE,7)*(1-RANK(DECAYLINEAR(VOLUME/MEAN(VOLUME,20),9)))))*(1+RANK(SUM(RET,250)))
        """
        n_rows = len(self.df)
        if n_rows < 50:
            return pd.Series(index=self.df.index, dtype=float)
        
        if n_rows < 260:
            ret_window = min(250, n_rows - 10)
        else:
            ret_window = 250
        
        w = np.arange(1, 10)
        ret = self.C.pct_change().fillna(0)
        
        part1 = self.C.diff(7).fillna(0)
        vol_ma = self.V.rolling(window=20, min_periods=5).mean().fillna(method='ffill').fillna(method='bfill')
        volume_ratio = (self.V / vol_ma).fillna(method='ffill').fillna(method='bfill')
        
        decay_linear = volume_ratio.rolling(window=9, min_periods=4).apply(
            lambda x: np.dot(x, w[:len(x)]) if len(x) >= 4 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        
        rank_decay = decay_linear.rank(method='min', pct=True).fillna(method='ffill').fillna(method='bfill')
        part2 = 1.0 - rank_decay
        
        sum_ret = ret.rolling(window=ret_window, min_periods=max(10, ret_window//5)).sum().fillna(method='ffill').fillna(method='bfill')
        rank_sum_ret = sum_ret.rank(method='min', pct=True).fillna(method='ffill').fillna(method='bfill')
        part3 = 1.0 + rank_sum_ret
        
        part1_part2 = (part1 * part2).fillna(method='ffill').fillna(method='bfill')
        rank_part1_part2 = part1_part2.rank(method='min', pct=True).fillna(method='ffill').fillna(method='bfill')
        
        alpha = -1.0 * rank_part1_part2 * part3
        return alpha.fillna(method='ffill').fillna(method='bfill')
    
    def alpha026(self):
        """
        (SUM(CLOSE,7)/7-CLOSE+CORR(VWAP,DELAY(CLOSE,5),230))
        """
        n_rows = len(self.df)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        part1 = (self.C.rolling(window=7, min_periods=3).mean() - self.C).fillna(method='ffill').fillna(method='bfill')
        
        if n_rows < 230:
            corr_window = max(30, n_rows // 2)
        else:
            corr_window = 230
        
        close_lag5 = self.C.shift(5)
        part2 = vwap.rolling(window=corr_window, min_periods=max(10, corr_window//5)).corr(close_lag5).fillna(method='ffill').fillna(method='bfill')
        
        alpha = (part1 + part2).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha027(self):
        """
        WMA((CLOSE-DELTA(CLOSE,3))/DELAY(CLOSE,3)*100+(CLOSE-DELAY(CLOSE,6))/DELAY(CLOSE,6)*100,12)
        """
        part1 = self.C.pct_change(periods=3) * 100.0 + self.C.pct_change(periods=6) * 100.0
        w = np.arange(1, 13)
        return part1.rolling(window=12, min_periods=12).apply(lambda x: np.dot(x, w))
    
    def alpha028(self):
        """
        3*SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1)
        -2*SMA(SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1),3,1)
        """
        part1 = self.C - self.C.rolling(window=9, min_periods=9).min()
        part2 = self.H.rolling(window=9, min_periods=9).max() - self.L.rolling(window=9, min_periods=9).min()
        rsv = part1 / part2 * 100
        sma1 = self._sma(rsv, 3, 1)
        sma2 = self._sma(sma1, 3, 1)
        return 3 * sma1 - 2 * sma2
    
    def alpha029(self):
        """
        (CLOSE-DELAY(CLOSE,6))/DELAY(CLOSE,6)*VOLUME
        """
        return self.C.pct_change(periods=6) * self.V
    
    def alpha030(self):
        """
        WMA((REGRESI(RET,MKT,SMB,HML,60))^2,20)
        单只股票版本:使用市场指数作为基准
        """
        ret = self.C.pct_change().fillna(0.0)
        if 'index_close' in self.df.columns:
            mkt_ret = self.df['index_close'].pct_change().fillna(0.0)
        else:
            mkt_ret = ret.rolling(window=20, min_periods=20).mean().fillna(0.0)
        
        smb_ret = pd.Series(0, index=ret.index)
        hml_ret = pd.Series(0, index=ret.index)
        
        result = pd.Series(index=self.df.index, dtype=float)
        for i in range(60, len(self.df)):
            y = ret.iloc[i-60:i]
            X = pd.DataFrame({
                'const': 1,
                'mkt': mkt_ret.iloc[i-60:i],
                'smb': smb_ret.iloc[i-60:i],
                'hml': hml_ret.iloc[i-60:i]
            }).dropna()
            y = y.loc[X.index]
            if len(y) >= 20:
                try:
                    result.iloc[i] = sm.OLS(y, X).fit().resid.iloc[-1]
                except:
                    result.iloc[i] = np.nan
            else:
                result.iloc[i] = np.nan
        
        w = np.arange(1, 21) / np.arange(1, 21).sum()
        return (result ** 2).rolling(window=20, min_periods=20).apply(lambda x: np.dot(x, w))
    
    def alpha031(self):
        """
        (CLOSE-MEAN(CLOSE,12))/MEAN(CLOSE,12)*100
        """
        ma = self.C.rolling(window=12, min_periods=12).mean()
        return (self.C / ma - 1.0) * 100
    
    def alpha032(self):
        """
        (-1*SUM(RANK(CORR(RANK(HIGH),RANK(VOLUME),3)),3))
        """
        part1 = self.H.rank(pct=True).rolling(window=3, min_periods=3).corr(self.V.rank(pct=True))
        return -1 * part1.rank(pct=True).rolling(window=3, min_periods=3).sum()
    
    def alpha033(self):
        """
        (-1*TSMIN(LOW,5)+DELAY(TSMIN(LOW,5),5))*RANK((SUM(RET,240)-SUM(RET,20))/220)*TSRANK(VOLUME,5)
        """
        n_rows = len(self.df)
        if n_rows < 10:
            return pd.Series(0, index=self.df.index)
        
        self.V = self.V.replace(0, np.nan).fillna(method='ffill').fillna(method='bfill')
        
        low_min5 = self.L.rolling(window=5, min_periods=3).min().fillna(method='ffill').fillna(method='bfill')
        part1 = -1 * low_min5.diff(5).fillna(0)
        
        if n_rows < 240:
            sum_window1 = min(240, n_rows - 5)
            sum_window2 = min(20, n_rows // 3)
        else:
            sum_window1 = 240
            sum_window2 = 20
        
        ret = self.C.pct_change().fillna(0)
        sum_ret1 = ret.rolling(window=sum_window1, min_periods=max(5, sum_window1//10)).sum().fillna(method='ffill').fillna(method='bfill')
        sum_ret2 = ret.rolling(window=sum_window2, min_periods=max(3, sum_window2//5)).sum().fillna(method='ffill').fillna(method='bfill')
        
        part2_series = ((sum_ret1 - sum_ret2) / 220).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_series.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        part3 = self._tsrank_fixed(self.V, 5).fillna(method='ffill').fillna(method='bfill')
        
        alpha = (part1 * part2 * part3).fillna(0)
        return alpha
    
    def alpha034(self):
        """
        MEAN(CLOSE,12)/CLOSE
        """
        return self.C.rolling(window=12, min_periods=12).mean() / self.C
    
    def alpha035(self):
        """
        (MIN(RANK(DECAYLINEAR(DELTA(OPEN,1),15)),RANK(DECAYLINEAR(CORR(VOLUME,OPEN*0.65+CLOSE*0.35,17),7)))*-1)
        """
        w7 = np.arange(1, 8)
        w15 = np.arange(1, 16)
        part1 = self.O.diff().rolling(window=15, min_periods=15).apply(lambda x: np.dot(x, w15)).rank(pct=True)
        part2 = (self.O * 0.65 + self.C * 0.35).rolling(window=17, min_periods=17).corr(self.V)
        part2 = part2.rolling(window=7, min_periods=7).apply(lambda x: np.dot(x, w7)).rank(pct=True)
        return np.minimum(part1, part2) * (-1)
    
    def alpha036(self):
        """
        RANK(SUM(CORR(RANK(VOLUME),RANK(VWAP),6),2))
        """
        self.V = self.V.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill')
        vol_rank = self.V.rank(pct=True, method='min')
        vwap_rank = vwap.rank(pct=True, method='min')
        part1 = vol_rank.rolling(window=6, min_periods=3).corr(vwap_rank)
        return part1.rolling(window=2, min_periods=1).sum().rank(pct=True, method='min')
    
    def alpha037(self):
        """
        (-1*RANK(SUM(OPEN,5)*SUM(RET,5)-DELAY(SUM(OPEN,5)*SUM(RET,5),10)))
        """
        part1 = self.O.rolling(window=5, min_periods=5).sum() * self.C.pct_change().rolling(window=5, min_periods=5).sum()
        return -1 * part1.diff(10)
    
    def alpha038(self):
        """
        ((SUM(HIGH,20)/20)<HIGH)?(-1*DELTA(HIGH,2)):0
        """
        condition = self.H.rolling(window=20, min_periods=20).mean() < self.H
        alpha = -1 * self.H.diff(2)
        alpha[~condition] = 0.0
        return alpha
    
    def alpha039(self):
        """
        (RANK(DECAYLINEAR(DELTA(CLOSE,2),8))-RANK(DECAYLINEAR(CORR(VWAP*0.3+OPEN*0.7,SUM(MEAN(VOLUME,180),37),14),12)))*-1
        使用填充版本
        """
        n_rows = len(self.df)
        if n_rows < 200:
            return self._alpha039_small_data()
        
        w8 = np.arange(1, 9)
        w12 = np.arange(1, 13)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        parta = vwap * 0.3 + self.O * 0.7
        V_filled = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(180, n_rows // 2)
        vol_min_periods = min(vol_window, max(10, vol_window // 10))
        vol_ma = V_filled.rolling(window=vol_window, min_periods=vol_min_periods).mean().fillna(method='ffill').fillna(method='bfill')
        
        sum_window = min(37, n_rows // 4)
        sum_min_periods = min(sum_window, max(5, sum_window // 4))
        partb = vol_ma.rolling(window=sum_window, min_periods=sum_min_periods).sum().fillna(method='ffill').fillna(method='bfill')
        
        part1 = self.C.diff(2).fillna(0)
        decay_window1 = 8
        decay_min_periods1 = min(decay_window1, max(3, decay_window1 // 2))
        part1_decay = part1.rolling(window=decay_window1, min_periods=decay_min_periods1).apply(
            lambda x: np.dot(x, w8[:len(x)]) if len(x) >= decay_min_periods1 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        corr_window = min(14, n_rows // 8)
        corr_min_periods = min(corr_window, max(3, corr_window // 2))
        part2_corr = parta.rolling(window=corr_window, min_periods=corr_min_periods).corr(partb).fillna(0)
        
        decay_window2 = min(12, n_rows // 8)
        decay_min_periods2 = min(decay_window2, max(3, decay_window2 // 2))
        part2_decay = part2_corr.rolling(window=decay_window2, min_periods=decay_min_periods2).apply(
            lambda x: np.dot(x, w12[:len(x)]) if len(x) >= decay_min_periods2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return -1 * (part1 - part2).fillna(method='ffill').fillna(method='bfill')
    
    def _alpha039_small_data(self):
        """
        小数据量版本
        """
        n_rows = len(self.df)
        w8 = np.arange(1, 9)
        w12 = np.arange(1, 13)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        parta = vwap * 0.3 + self.O * 0.7
        V_filled = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(30, n_rows // 2)
        vol_min_periods = min(vol_window, max(3, vol_window // 3))
        vol_ma = V_filled.rolling(window=vol_window, min_periods=vol_min_periods).mean().fillna(method='ffill').fillna(method='bfill')
        
        sum_window = min(10, n_rows // 3)
        sum_min_periods = min(sum_window, max(3, sum_window // 2))
        partb = vol_ma.rolling(window=sum_window, min_periods=sum_min_periods).sum().fillna(method='ffill').fillna(method='bfill')
        
        part1 = self.C.diff(2).fillna(0)
        decay_window1 = min(8, n_rows // 3)
        decay_min_periods1 = min(decay_window1, max(2, decay_window1 // 2))
        part1_decay = part1.rolling(window=decay_window1, min_periods=decay_min_periods1).apply(
            lambda x: np.dot(x, w8[:len(x)]) if len(x) >= decay_min_periods1 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        corr_window = min(8, n_rows // 4)
        corr_min_periods = min(corr_window, max(2, corr_window // 2))
        part2_corr = parta.rolling(window=corr_window, min_periods=corr_min_periods).corr(partb).fillna(0)
        
        decay_window2 = min(8, n_rows // 4)
        decay_min_periods2 = min(decay_window2, max(2, decay_window2 // 2))
        part2_decay = part2_corr.rolling(window=decay_window2, min_periods=decay_min_periods2).apply(
            lambda x: np.dot(x, w12[:len(x)]) if len(x) >= decay_min_periods2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return -1 * (part1 - part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha040(self):
        """
        SUM(CLOSE>DELAY(CLOSE,1)?VOLUME:0,26)/SUM(CLOSE<=DELAY(CLOSE,1)?VOLUME:0,26)*100
        """
        diff = self.C.diff()
        part1 = ((diff > 0) * self.V).rolling(window=26, min_periods=26).sum()
        part2 = ((diff <= 0) * self.V).rolling(window=26, min_periods=26).sum()
        return part1 / part2 * 100
    
    def alpha041(self):
        """
        RANK(MAX(DELTA(VWAP,3),5))*-1
        """
        self.V = self.V.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        vwap_diff = vwap.diff(3)
        vwap_max = vwap_diff.rolling(window=5, min_periods=3).max()
        return -1 * vwap_max.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
    
    def alpha042(self):
        """
        (-1*RANK(STD(HIGH,10)))*CORR(HIGH,VOLUME,10)
        """
        part1 = -1 * self.H.rolling(window=10, min_periods=10).std().rank(pct=True)
        part2 = self.H.rolling(window=10, min_periods=10).corr(self.V)
        return part1 * part2
    
    def alpha043(self):
        """
        (SUM(CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0),6))
        """
        diff = self.C.diff()
        part1 = ((diff > 0) * self.V).rolling(window=6, min_periods=6).sum()
        part2 = ((diff < 0) * -self.V).rolling(window=6, min_periods=6).sum()
        return part1 + part2
    
    def alpha044(self):
        """
        (TSRANK(DECAYLINEAR(CORR(LOW,MEAN(VOLUME,10),7),6),4)+TSRANK(DECAYLINEAR(DELTA(VWAP,3),10),15))
        """
        w6 = np.arange(1, 7)
        w10 = np.arange(1, 11)
        self.V = self.V.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        vol_ma = self.V.rolling(window=10, min_periods=5).mean().fillna(method='ffill').fillna(method='bfill')
        part1_corr = vol_ma.rolling(window=7, min_periods=4).corr(self.L).fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_corr.rolling(window=6, min_periods=3).apply(
            lambda x: np.dot(x, w6[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = self._tsrank_fixed(part1_decay, 4)
        
        vwap_diff = vwap.diff(3).fillna(0)
        part2_decay = vwap_diff.rolling(window=10, min_periods=5).apply(
            lambda x: np.dot(x, w10[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_decay, 15)
        
        return part1 + part2
    
    def alpha045(self):
        """
        (RANK(DELTA(CLOSE*0.6+OPEN*0.4,1))*RANK(CORR(VWAP,MEAN(VOLUME,150),15)))
        调整版本:根据数据量动态调整窗口
        """
        n_rows = len(self.df)
        vol_window = max(20, n_rows // 3) if n_rows < 150 else 150
        
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        weighted_price = self.C * 0.6 + self.O * 0.4
        part1 = weighted_price.diff().fillna(0).rank(pct=True, method='min')
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vwap.rolling(window=15, min_periods=5).corr(vol_ma).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_corr.rank(pct=True, method='min')
        
        return (part1 * part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha046(self):
        """
        (MEAN(CLOSE,3)+MEAN(CLOSE,6)+MEAN(CLOSE,12)+MEAN(CLOSE,24))/(4*CLOSE)
        """
        ma3 = self.C.rolling(window=3, min_periods=3).mean()
        ma6 = self.C.rolling(window=6, min_periods=6).mean()
        ma12 = self.C.rolling(window=12, min_periods=12).mean()
        ma24 = self.C.rolling(window=24, min_periods=24).mean()
        return (ma3 + ma6 + ma12 + ma24) / (4 * self.C)
    
    def alpha047(self):
        """
        SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,9,1)
        """
        high_max = self.H.rolling(window=6, min_periods=6).max()
        low_min = self.L.rolling(window=6, min_periods=6).min()
        part1 = (high_max - self.C) / (high_max - low_min) * 100
        return self._sma(part1, 9, 1)
    
    def alpha048(self):
        """
        -1*RANK(SIGN(CLOSE-DELAY(CLOSE,1))+SIGN(DELAY(CLOSE,1)-DELAY(CLOSE,2))+SIGN(DELAY(CLOSE,2)-DELAY(CLOSE,3)))*SUM(VOLUME,5)/SUM(VOLUME,20)
        """
        diff1 = self.C.diff()
        part1 = (np.sign(diff1) + np.sign(diff1.shift(1)) + np.sign(diff1.shift(2))).rank(pct=True)
        part2 = self.V.rolling(window=5, min_periods=5).sum() / self.V.rolling(window=20, min_periods=20).sum()
        return -1 * part1 * part2
    
    def alpha049(self):
        """
        SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
        (SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)+
        SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
        """
        hl_sum = self.H + self.L
        condition1 = hl_sum >= hl_sum.shift(1)
        condition2 = hl_sum <= hl_sum.shift(1)
        max_abs = np.maximum(abs(self.H.diff()), abs(self.L.diff()))
        
        part1 = max_abs.copy()
        part2 = max_abs.copy()
        part1[condition1] = 0.0
        part2[condition2] = 0.0
        
        sum1 = part1.rolling(window=12, min_periods=12).sum()
        sum2 = part2.rolling(window=12, min_periods=12).sum()
        return sum1 / (sum1 + sum2)
    
    def alpha050(self):
        """
        SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
        (SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)
        +SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
        -SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
        (SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)
        +SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
        """
        hl_sum = self.H + self.L
        condition1 = hl_sum >= hl_sum.shift(1)
        condition2 = hl_sum <= hl_sum.shift(1)
        max_abs = np.maximum(abs(self.H.diff()), abs(self.L.diff()))
        
        part1 = max_abs.copy()
        part2 = max_abs.copy()
        part1[condition2] = 0.0
        part2[condition1] = 0.0
        
        sum1 = part1.rolling(window=12, min_periods=12).sum()
        sum2 = part2.rolling(window=12, min_periods=12).sum()
        return sum1 / (sum1 + sum2) - sum2 / (sum1 + sum2)
    
    def alpha051(self):
        """
        SUM(((HIGH+LOW)<=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12)/
        (SUM(((HIGH+LOW)<=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12)
        +SUM(((HIGH+LOW)>=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12))
        """
        hl_sum = self.H + self.L
        condition1 = hl_sum <= hl_sum.shift(1)
        condition2 = hl_sum >= hl_sum.shift(1)
        max_abs = np.maximum(abs(self.H.diff()), abs(self.L.diff()))
        
        part1 = max_abs.copy()
        part2 = max_abs.copy()
        part1[condition1] = 0.0
        part2[condition2] = 0.0
        
        sum1 = part1.rolling(window=12, min_periods=12).sum()
        sum2 = part2.rolling(window=12, min_periods=12).sum()
        return sum1 / (sum1 + sum2)
    
    def alpha052(self):
        """
        SUM(MAX(0,HIGH-DELAY((HIGH+LOW+CLOSE)/3,1)),26)/SUM(MAX(0,DELAY((HIGH+LOW+CLOSE)/3,1)-L),26)*100
        """
        ma = (self.H + self.L + self.C) / 3.0
        part1 = np.maximum(0.0, self.H - ma.shift(1)).rolling(window=26, min_periods=26).sum()
        part2 = np.maximum(0.0, ma.shift(1) - self.L).rolling(window=26, min_periods=26).sum()
        return part1 / part2 * 100.0
    
    def alpha053(self):
        """
        COUNT(CLOSE>DELAY(CLOSE,1),12)/12*100
        """
        return (self.C.diff() > 0.0).rolling(window=12, min_periods=12).sum() / 12.0 * 100
    
    def alpha054(self):
        """
        (-1*RANK(STD(ABS(CLOSE-OPEN))+CLOSE-OPEN+CORR(CLOSE,OPEN,10)))
        """
        part1 = abs(self.C - self.O).rolling(window=10, min_periods=10).std() + self.C - self.O + self.C.rolling(window=10, min_periods=10).corr(self.O)
        return -1 * part1.rank(pct=True)
    
    def alpha055(self):
        """
        SUM(16*(CLOSE+(CLOSE-OPEN)/2-DELAY(OPEN,1))/
        ((ABS(HIGH-DELAY(CLOSE,1))>ABS(LOW-DELAY(CLOSE,1)) & ABS(HIGH-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) ? 
        ABS(HIGH-DELAY(CLOSE,1))+ABS(LOW-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
        (ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) & ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(CLOSE,1)) ?
        ABS(LOW-DELAY(CLOSE,1))+ABS(HIGH-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
        ABS(HIGH-DELAY(LOW,1))+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4)))
        *MAX(ABS(HIGH-DELAY(CLOSE,1)),ABS(LOW-DELAY(CLOSE,1))),20)
        """
        part1 = self.C * 1.5 - self.O * 0.5 - self.O.shift(1)
        part2 = abs(self.H - self.C.shift(1)) + abs(self.L - self.C.shift(1)) / 2.0 + abs(self.C - self.O).shift(1) / 4.0
        
        condition1 = np.logical_and(
            abs(self.H - self.C.shift(1)) > abs(self.L - self.C.shift(1)),
            abs(self.H - self.C.shift(1)) > abs(self.H - self.L.shift(1))
        )
        condition2 = np.logical_and(
            abs(self.L - self.C.shift(1)) > abs(self.H - self.L.shift(1)),
            abs(self.L - self.C.shift(1)) > abs(self.H - self.C.shift(1))
        )
        
        part2[~condition1 & condition2] = abs(self.L - self.C.shift(1)) + abs(self.H - self.C.shift(1)) / 2.0 + abs(self.C - self.O).shift(1) / 4.0
        part2[~condition1 & ~condition2] = abs(self.H - self.L.shift(1)) + abs(self.C - self.O).shift(1) / 4.0
        
        part3 = np.maximum(abs(self.H - self.C.shift(1)), abs(self.L - self.C.shift(1)))
        alpha = (part1 / part2 * part3 * 16.0).rolling(window=20, min_periods=20).sum()
        return alpha
    
    def alpha056(self):
        """
        RANK(OPEN-TSMIN(OPEN,12))<RANK(RANK(CORR(SUM((HIGH +LOW)/2,19),SUM(MEAN(VOLUME,40),19),13))^5)
        """
        part1 = (self.O - self.O.rolling(window=12, min_periods=12).min()).rank(pct=True)
        t1 = (self.H * 0.5 + self.L * 0.5).rolling(window=19, min_periods=19).sum()
        t2 = self.V.rolling(window=40, min_periods=40).mean().rolling(window=19, min_periods=19).sum()
        part2 = (t1.rolling(window=13, min_periods=13).corr(t2).rank(pct=True) ** 5).rank(pct=True)
        return part2 - part1
    
    def alpha057(self):
        """
        SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1)
        """
        part1 = self.C - self.C.rolling(window=9, min_periods=9).min()
        part2 = self.H.rolling(window=9, min_periods=9).max() - self.L.rolling(window=9, min_periods=9).min()
        rsv = part1 / part2 * 100
        return self._sma(rsv, 3, 1)
    
    def alpha058(self):
        """
        COUNT(CLOSE>DELAY(CLOSE,1),20)/20*100
        """
        return (self.C.diff() > 0.0).rolling(window=20, min_periods=20).sum() / 20.0 * 100
    
    def alpha059(self):
        """
        SUM((CLOSE=DELAY(CLOSE,1)?0:CLOSE-(CLOSE>DELAY(CLOSE,1)?MIN(LOW,DELAY(CLOSE,1)):MAX(HIGH,DELAY(CLOSE,1)))),20)
        """
        alpha = self.C.copy()
        diff = self.C.diff()
        condition1 = diff > 0.0
        condition2 = diff < 0.0
        
        alpha[condition1] = self.C[condition1] - np.minimum(self.L[condition1], self.C.shift(1)[condition1])
        alpha[condition2] = self.C[condition2] - np.maximum(self.H[condition2], self.C.shift(1)[condition2])
        alpha[diff == 0] = 0.0
        
        return alpha.rolling(window=20, min_periods=20).sum()
    
    def alpha060(self):
        """
        SUM((2*CLOSE-LOW-HIGH)/(HIGH-LOW)*VOLUME,20)
        """
        price_range = (self.H - self.L).replace(0, 1e-10)
        numerator = 2 * self.C - self.L - self.H
        ratio = numerator / price_range
        part1 = (ratio * self.V).fillna(method='ffill').fillna(method='bfill')
        alpha = part1.rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha061(self):
        """
        MAX(RANK(DECAYLINEAR(DELTA(VWAP,1),12)),RANK(DECAYLINEAR(RANK(CORR(LOW,MEAN(VOLUME,80),8)),17)))*-1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        w12 = np.arange(1, 13)
        vwap_diff = vwap.diff().fillna(0)
        part1_decay = vwap_diff.rolling(window=12, min_periods=6).apply(
            lambda x: np.dot(x, w12[:len(x)]) if len(x) >= 6 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        vol_window = min(80, len(self.df) // 2)
        turnover_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = turnover_ma.rolling(window=8, min_periods=4).corr(self.L).fillna(method='ffill').fillna(method='bfill')
        part2_rank = part2_corr.rank(pct=True, method='min')
        
        w17 = np.arange(1, 18)
        part2_decay = part2_rank.rolling(window=17, min_periods=8).apply(
            lambda x: np.dot(x, w17[:len(x)]) if len(x) >= 8 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return -1 * np.maximum(part1, part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha062(self):
        """
        -1*CORR(HIGH,RANK(VOLUME),5)
        """
        return -1 * self.V.rank(pct=True).rolling(window=5, min_periods=5).corr(self.H)
    
    def alpha063(self):
        """
        SMA(MAX(CLOSE-DELAY(CLOSE,1),0),6,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),6,1)*100
        """
        diff = self.C.diff()
        part1 = np.maximum(diff, 0.0)
        part2 = abs(diff)
        sma1 = self._sma(part1, 6, 1)
        sma2 = self._sma(part2, 6, 1)
        return sma1 / sma2 * 100.0
    
    def alpha064(self):
        """
        (MAX(RANK(DECAYLINEAR(CORR(RANK(VWAP),RANK(VOLUME),4),4)),RANK(DECAYLINEAR(MAX(CORR(RANK(CLOSE),RANK(MEAN(VOLUME,60)),4),13),14)))*-1)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w4 = np.arange(1, 5)
        w14 = np.arange(1, 15)
        
        vwap_rank = vwap.rank(pct=True, method='min')
        vol_rank = self.V.rank(pct=True, method='min')
        
        part1_corr = vwap_rank.rolling(window=4, min_periods=3).corr(vol_rank).fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_corr.rolling(window=4, min_periods=3).apply(
            lambda x: np.dot(x, w4[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        vol_window = min(60, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        vol_ma_rank = vol_ma.rank(pct=True, method='min')
        close_rank = self.C.rank(pct=True, method='min')
        
        part2_corr = close_rank.rolling(window=4, min_periods=3).corr(vol_ma_rank).fillna(method='ffill').fillna(method='bfill')
        part2_max = part2_corr.rolling(window=13, min_periods=7).max().fillna(method='ffill').fillna(method='bfill')
        part2_decay = part2_max.rolling(window=14, min_periods=7).apply(
            lambda x: np.dot(x, w14[:len(x)]) if len(x) >= 7 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return -1 * np.maximum(part1, part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha065(self):
        """
        MEAN(CLOSE,6)/CLOSE
        """
        return self.C.rolling(window=6, min_periods=6).mean() / self.C
    
    def alpha066(self):
        """
        (CLOSE-MEAN(CLOSE,6))/MEAN(CLOSE,6)*100
        """
        ma = self.C.rolling(window=6, min_periods=6).mean()
        return (self.C - ma) / ma * 100
    
    def alpha067(self):
        """
        SMA(MAX(CLOSE-DELAY(CLOSE,1),0),24,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),24,1)*100
        """
        diff = self.C.diff()
        part1 = np.maximum(diff, 0.0)
        part2 = abs(diff)
        sma1 = self._sma(part1, 24, 1)
        sma2 = self._sma(part2, 24, 1)
        return sma1 / sma2 * 100
    
    def alpha068(self):
        """
        SMA(((HIGH+LOW)/2-(DELAY(HIGH,1)+DELAY(LOW,1))/2)*(HIGH-LOW)/VOLUME,15,2)
        """
        part1 = (self.H.diff() * 0.5 + self.L.diff() * 0.5) * (self.H - self.L) / self.V
        return self._sma(part1, 15, 2)
    
    def alpha069(self):
        """
        (SUM(DTM,20)>SUM(DBM,20)?(SUM(DTM,20)-SUM(DBM,20))/SUM(DTM,20):
        (SUM(DTM,20)=SUM(DBM,20)?0:(SUM(DTM,20)-SUM(DBM,20))/SUM(DBM,20)))
        """
        dtm = (self.O.diff() <= 0) * np.maximum(self.H - self.O, self.O.diff())
        dbm = (self.O.diff() >= 0) * np.maximum(self.O - self.L, self.O.diff())
        
        dtm_sum = dtm.rolling(window=20, min_periods=20).sum()
        dbm_sum = dbm.rolling(window=20, min_periods=20).sum()
        
        result = pd.Series(index=self.df.index, dtype=float)
        mask_gt = dtm_sum > dbm_sum
        mask_eq = dtm_sum == dbm_sum
        mask_lt = dtm_sum < dbm_sum
        
        result[mask_gt] = (dtm_sum[mask_gt] - dbm_sum[mask_gt]) / dtm_sum[mask_gt]
        result[mask_eq] = 0.0
        result[mask_lt] = (dtm_sum[mask_lt] - dbm_sum[mask_lt]) / dbm_sum[mask_lt]
        
        return result
    
    def alpha070(self):
        """
        STD(AMOUNT,6)
        """
        return self.AMOUNT.rolling(window=6, min_periods=6).std()
    
    def alpha071(self):
        """
        (CLOSE-MEAN(CLOSE,24))/MEAN(CLOSE,24)*100
        """
        ma = self.C.rolling(window=24, min_periods=24).mean()
        return (self.C - ma) / ma * 100
    
    def alpha072(self):
        """
        SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,15,1)
        """
        high_max = self.H.rolling(window=6, min_periods=6).max()
        low_min = self.L.rolling(window=6, min_periods=6).min()
        part1 = (high_max - self.C) / (high_max - low_min) * 100.0
        return self._sma(part1, 15, 1)
    
    def alpha073(self):
        """
        ((TSRANK(DECAYLINEAR(DECAYLINEAR(CORR(CLOSE,VOLUME,10),16),4),5)-RANK(DECAYLINEAR(CORR(VWAP,MEAN(VOLUME,30),4),3)))*-1)
        ETF专用版本
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        def normalize(series):
            return (series - series.min()) / (series.max() - series.min() + 1e-10)
        
        part1_corr = self.C.rolling(window=10, min_periods=5).corr(self.V).fillna(method='ffill').fillna(method='bfill')
        part1_ema1 = part1_corr.ewm(span=16, adjust=False, min_periods=5).mean()
        part1_ema2 = part1_ema1.ewm(span=4, adjust=False, min_periods=3).mean()
        part1 = normalize(part1_ema2)
        
        vol_window = min(30, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=5).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vwap.rolling(window=4, min_periods=3).corr(vol_ma).fillna(method='ffill').fillna(method='bfill')
        
        w3 = np.arange(1, 4) / np.arange(1, 4).sum()
        part2 = part2_corr.rolling(window=3, min_periods=2).apply(
            lambda x: np.sum(x * w3[:len(x)]) if len(x) >= 2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = normalize(part2)
        
        return -1 * (part1 - part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha074(self):
        """
        RANK(CORR(SUM(LOW*0.35+VWAP*0.65,20),SUM(MEAN(VOLUME,40),20),7))+RANK(CORR(RANK(VWAP),RANK(VOLUME),6))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        weighted_price = self.L * 0.35 + vwap * 0.65
        sum1 = weighted_price.rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(40, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//8)).mean().fillna(method='ffill').fillna(method='bfill')
        sum2 = vol_ma.rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill')
        
        part1_corr = sum1.rolling(window=7, min_periods=4).corr(sum2).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_corr.rank(pct=True, method='min')
        
        vwap_rank = vwap.rank(pct=True, method='min')
        vol_rank = self.V.rank(pct=True, method='min')
        part2_corr = vwap_rank.rolling(window=6, min_periods=4).corr(vol_rank).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_corr.rank(pct=True, method='min')
        
        return (part1 + part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha075(self):
        """
        COUNT(CLOSE>OPEN & BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN,50)/COUNT(BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN,50)
        使用指数数据
        """
        n_rows = len(self.df)
        
        if hasattr(self, 'index_df') and self.index_df is not None:
            index_data = self.index_df.copy()
            if 'close' in index_data.columns:
                index_close = index_data['close']
            else:
                index_close = index_data.iloc[:, 0]
            
            if 'open' in index_data.columns:
                index_open = index_data['open']
            else:
                index_open = index_close.shift(1).fillna(index_close)
            
            if 'date' in self.df.columns and 'date' in index_data.columns:
                self.df['date'] = pd.to_datetime(self.df['date'])
                index_data['date'] = pd.to_datetime(index_data['date'])
                close_map = dict(zip(index_data['date'], index_close))
                open_map = dict(zip(index_data['date'], index_open))
                bm_close = self.df['date'].map(close_map).fillna(method='ffill').fillna(method='bfill')
                bm_open = self.df['date'].map(open_map).fillna(method='ffill').fillna(method='bfill')
            else:
                bm_close = index_close.reindex(self.df.index, method='ffill')
                bm_open = index_open.reindex(self.df.index, method='ffill')
        else:
            bm_close = self.C.rolling(window=20, min_periods=5).mean().fillna(method='ffill').fillna(method='bfill')
            bm_open = self.O.rolling(window=20, min_periods=5).mean().fillna(method='ffill').fillna(method='bfill')
        
        bm_down = bm_close < bm_open
        stock_up = self.C > self.O
        condition = stock_up & bm_down
        
        if condition.sum() == 0:
            bm_ret = bm_close.pct_change().fillna(0)
            bm_down_ret = bm_ret < 0
            condition = stock_up & bm_down_ret
            bm_down = bm_down_ret
        
        window = min(50, n_rows // 2)
        min_periods = max(5, window // 3)
        
        numerator = condition.rolling(window=window, min_periods=min_periods).sum()
        denominator = bm_down.rolling(window=window, min_periods=min_periods).sum().replace(0, np.nan)
        alpha = (numerator / denominator).fillna(method='ffill').fillna(method='bfill').fillna(0)
        
        return alpha
    
    def alpha076(self):
        """
        STD(ABS(CLOSE/DELAY(CLOSE,1)-1)/VOLUME,20)/MEAN(ABS(CLOSE/DELAY(CLOSE,1)-1)/VOLUME,20)
        """
        self.V = self.V.replace(0, np.nan).fillna(method='ffill').fillna(method='bfill')
        ret = self.C.pct_change().fillna(0).replace([np.inf, -np.inf], 0)
        ret_vol = (abs(ret) / self.V).fillna(method='ffill').fillna(method='bfill')
        std = ret_vol.rolling(window=20, min_periods=10).std()
        mean = ret_vol.rolling(window=20, min_periods=10).mean().replace(0, np.nan)
        alpha = (std / mean).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha077(self):
        """
        MIN(RANK(DECAYLINEAR(HIGH*0.5+LOW*0.5-VWAP,20)),RANK(DECAYLINEAR(CORR(HIGH*0.5+LOW*0.5,MEAN(VOLUME,40),3),6)))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w6 = np.arange(1, 7)
        w20 = np.arange(1, 21)
        
        hl_avg = self.H * 0.5 + self.L * 0.5
        part1_series = hl_avg - vwap
        part1_decay = part1_series.rolling(window=20, min_periods=10).apply(
            lambda x: np.dot(x, w20[:len(x)]) if len(x) >= 10 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        vol_window = min(40, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//8)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = hl_avg.rolling(window=3, min_periods=2).corr(vol_ma).fillna(method='ffill').fillna(method='bfill')
        part2_decay = part2_corr.rolling(window=6, min_periods=3).apply(
            lambda x: np.dot(x, w6[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return np.minimum(part1, part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha078(self):
        """
        ((HIGH+LOW+CLOSE)/3-MA((HIGH+LOW+CLOSE)/3,12))/(0.015*MEAN(ABS(CLOSE-MEAN((HIGH+LOW+CLOSE)/3,12)),12))
        """
        tp = (self.H + self.L + self.C) / 3
        tp_ma = tp.rolling(window=12, min_periods=12).mean()
        part1 = tp - tp_ma
        part2 = abs(self.C - tp_ma).rolling(window=12, min_periods=12).mean() * 0.015
        return part1 / part2
    
    def alpha079(self):
        """
        SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100
        """
        diff = self.C.diff()
        part1 = np.maximum(diff, 0.0)
        part2 = abs(diff)
        sma1 = self._sma(part1, 12, 1)
        sma2 = self._sma(part2, 12, 1)
        return sma1 / sma2 * 100
    
    def alpha080(self):
        """
        (VOLUME-DELAY(VOLUME,5))/DELAY(VOLUME,5)*100
        """
        return self.V.pct_change(periods=5) * 100.0
    
    def alpha081(self):
        """
        SMA(VOLUME,21,2)
        """
        return self._sma(self.V, 21, 2)
    
    def alpha082(self):
        """
        SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,20,1)
        """
        high_max = self.H.rolling(window=6, min_periods=6).max()
        low_min = self.L.rolling(window=6, min_periods=6).min()
        part1 = (high_max - self.C) / (high_max - low_min) * 100
        return self._sma(part1, 20, 1)
    
    def alpha083(self):
        """
        (-1*RANK(COVIANCE(RANK(HIGH),RANK(VOLUME),5)))
        """
        alpha = self.H.rank(pct=True).rolling(window=5, min_periods=5).cov(self.V.rank(pct=True))
        return -1 * alpha.rank(pct=True)
    
    def alpha084(self):
        """
        SUM((CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0)),20)
        """
        part1 = np.sign(self.C.diff()) * self.V
        return part1.rolling(window=20, min_periods=20).sum()
    
    def alpha085(self):
        """
        TSRANK(VOLUME/MEAN(VOLUME,20),20)*TSRANK(-1*DELTA(CLOSE,7),8)
        """
        part1 = self.V / self.V.rolling(window=20, min_periods=20).mean()
        part1 = self._tsrank(part1, 20)
        part2 = -1 * self.C.diff(7)
        part2 = self._tsrank(part2, 8)
        return part1 * part2
    
    def alpha086(self):
        """
        ((0.25<((DELAY(CLOSE,20)-DELAY(CLOSE,10))/10-(DELAY(CLOSE,10)-CLOSE)/10))?-1:((((DELAY(CLOSE,20)-DELAY(CLOSE,10))/10-(DELAY(CLOSE,10)-CLOSE)/10)<0)?1:(DELAY(CLOSE,1)-CLOSE)))
        """
        part = (self.C.shift(20) - self.C.shift(10)) / 10 - (self.C.shift(10) - self.C) / 10
        condition1 = part > 0.25
        condition2 = part < 0.0
        
        alpha = pd.Series(index=self.df.index, dtype=float)
        alpha[condition1] = -1.0
        alpha[~condition1 & condition2] = 1.0
        alpha[~condition1 & ~condition2] = self.C.shift(1) - self.C
        
        return alpha
    
    def alpha087(self):
        """
        (RANK(DECAYLINEAR(DELTA(VWAP,4),7))+TSRANK(DECAYLINEAR((LOW-VWAP)/(OPEN-(HIGH+LOW)/2),11),7))*-1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w7 = np.arange(1, 8)
        w11 = np.arange(1, 12)
        
        vwap_diff = vwap.diff(4).fillna(0)
        part1_decay = vwap_diff.rolling(window=7, min_periods=4).apply(
            lambda x: np.dot(x, w7[:len(x)]) if len(x) >= 4 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        hl_avg = (self.H + self.L) / 2
        denominator = self.O - hl_avg
        denominator = denominator.replace(0, 1e-10)
        mask_small = abs(denominator) < 1e-8
        denominator[mask_small] = 1e-10 * np.sign(denominator[mask_small])
        
        part2_series = (self.L - vwap) / denominator
        part2_series = part2_series.replace([np.inf, -np.inf], np.nan).fillna(method='ffill').fillna(method='bfill').clip(-100, 100)
        
        part2_decay = part2_series.rolling(window=11, min_periods=6).apply(
            lambda x: np.dot(x, w11[:len(x)]) if len(x) >= 6 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_decay, 7)
        
        return -1 * (part1 + part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha088(self):
        """
        (CLOSE-DELAY(CLOSE,20))/DELAY(CLOSE,20)*100
        """
        return self.C.pct_change(periods=20) * 100
    
    def alpha089(self):
        """
        2*(SMA(CLOSE,13,2)-SMA(CLOSE,27,2)-SMA(SMA(CLOSE,13,2)-SMA(CLOSE,27,2),10,2))
        """
        sma13 = self._sma(self.C, 13, 2)
        sma27 = self._sma(self.C, 27, 2)
        part = sma13 - sma27
        return 2.0 * (part - self._sma(part, 10, 2))
    
    def alpha090(self):
        """
        (RANK(CORR(RANK(VWAP),RANK(VOLUME),5))*-1)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vwap_rank = vwap.rank(pct=True, method='min')
        vol_rank = self.V.rank(pct=True, method='min')
        corr = vwap_rank.rolling(window=5, min_periods=3).corr(vol_rank).fillna(method='ffill').fillna(method='bfill')
        alpha = -1 * corr.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        return alpha
    
    def alpha091(self):
        """
        ((RANK(CLOSE-MAX(CLOSE,5))*RANK(CORR(MEAN(VOLUME,40),LOW,5)))*-1)
        """
        part1 = (self.C - self.C.rolling(window=5, min_periods=5).max()).rank(pct=True)
        part2 = self.V.rolling(window=40, min_periods=40).mean().rolling(window=5, min_periods=5).corr(self.L).rank(pct=True)
        return -1 * part1 * part2
    
    def alpha092(self):
        """
        (MAX(RANK(DECAYLINEAR(DELTA(CLOSE*0.35+VWAP*0.65,2),3)),TSRANK(DECAYLINEAR(ABS(CORR((MEAN(VOLUME,180)),CLOSE,13)),5),15))*-1)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w3 = np.arange(1, 4)
        w5 = np.arange(1, 6)
        
        weighted_price = self.C * 0.35 + vwap * 0.65
        weighted_diff = weighted_price.diff(2).fillna(0)
        part1_decay = weighted_diff.rolling(window=3, min_periods=2).apply(
            lambda x: np.dot(x, w3[:len(x)]) if len(x) >= 2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        vol_window = min(180, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vol_ma.rolling(window=13, min_periods=7).corr(self.C).fillna(method='ffill').fillna(method='bfill')
        part2_abs = abs(part2_corr)
        part2_decay = part2_abs.rolling(window=5, min_periods=3).apply(
            lambda x: np.dot(x, w5[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_decay, 15)
        
        return -1 * np.maximum(part1, part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha093(self):
        """
        SUM(OPEN>=DELAY(OPEN,1)?0:MAX(OPEN-LOW,OPEN-DELAY(OPEN,1)),20)
        """
        condition = self.O.diff() >= 0.0
        alpha = np.maximum(self.O - self.L, self.O.diff())
        alpha[condition] = 0.0
        return alpha.rolling(window=20, min_periods=20).sum()
    
    def alpha094(self):
        """
        SUM((CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0)),30)
        """
        part1 = np.sign(self.C.diff()) * self.V
        return part1.rolling(window=30, min_periods=30).sum()
    
    def alpha095(self):
        """
        STD(AMOUNT,20)
        """
        return self.AMOUNT.rolling(window=20, min_periods=20).std()
    
    def alpha096(self):
        """
        SMA(SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1),3,1)
        """
        part1 = self.C - self.C.rolling(window=9, min_periods=9).min()
        part2 = self.H.rolling(window=9, min_periods=9).max() - self.L.rolling(window=9, min_periods=9).min()
        rsv = part1 / part2 * 100
        sma1 = self._sma(rsv, 3, 1)
        return self._sma(sma1, 3, 1)
    
    def alpha097(self):
        """
        STD(VOLUME,10)
        """
        return self.V.rolling(window=10, min_periods=10).std()
    
    def alpha098(self):
        """
        (DELTA(SUM(CLOSE,100)/100,100)/DELAY(CLOSE,100)<=0.05)?(-1*(CLOSE-TSMIN(CLOSE,100))):(-1*DELTA(CLOSE,3))
        """
        condition1 = self.C.rolling(window=100, min_periods=100).mean().diff(100) / self.C.shift(100) <= 0.05
        alpha = pd.Series(index=self.df.index, dtype=float)
        alpha[condition1] = -1 * (self.C - self.C.rolling(window=100, min_periods=100).min())
        alpha[~condition1] = -1 * self.C.diff(3)
        return alpha
    
    def alpha099(self):
        """
        (-1*RANK(COVIANCE(RANK(CLOSE),RANK(VOLUME),5)))
        """
        alpha = self.C.rank(pct=True).rolling(window=5, min_periods=5).cov(self.V.rank(pct=True))
        return -1 * alpha.rank(pct=True)
    
    def alpha100(self):
        """
        STD(VOLUME,20)
        """
        return self.V.rolling(window=20, min_periods=20).std()
    
    def alpha101(self):
        """
        (RANK(CORR(CLOSE,SUM(MEAN(VOLUME,30),37),15)) < RANK(CORR(RANK(HIGH*0.1+VWAP*0.9),RANK(VOLUME),11)))*-1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(30, len(self.df) // 3)
        sum_window = min(37, len(self.df) // 3)
        corr_window = min(15, len(self.df) // 4)
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//6)).mean().fillna(method='ffill').fillna(method='bfill')
        vol_sum = vol_ma.rolling(window=sum_window, min_periods=max(5, sum_window//6)).sum().fillna(method='ffill').fillna(method='bfill')
        part1_corr = vol_sum.rolling(window=corr_window, min_periods=max(5, corr_window//3)).corr(self.C).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_corr.rank(pct=True, method='min')
        
        weighted_price = self.H * 0.1 + vwap * 0.9
        weighted_rank = weighted_price.rank(pct=True, method='min')
        vol_rank = self.V.rank(pct=True, method='min')
        corr_window2 = min(11, len(self.df) // 4)
        part2_corr = weighted_rank.rolling(window=corr_window2, min_periods=max(4, corr_window2//3)).corr(vol_rank).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_corr.rank(pct=True, method='min')
        
        return -1 * (part2 - part1).fillna(method='ffill').fillna(method='bfill')
    
    def alpha102(self):
        """
        SMA(MAX(VOLUME-DELAY(VOLUME,1),0),6,1)/SMA(ABS(VOLUME-DELAY(VOLUME,1)),6,1)*100
        """
        diff = self.V.diff()
        part1 = np.maximum(diff, 0.0)
        part2 = abs(diff)
        sma1 = self._sma(part1, 6, 1)
        sma2 = self._sma(part2, 6, 1)
        return sma1 / sma2 * 100
    
    def alpha103(self):
        """
        ((20-LOWDAY(LOW,20))/20)*100
        """
        def lowday(x):
            return 19 - x.argmin() if len(x) == 20 else np.nan
        return (20 - self.L.rolling(window=20, min_periods=20).apply(lowday)) / 20 * 100
    
    def alpha104(self):
        """
        -1*(DELTA(CORR(HIGH,VOLUME,5),5)*RANK(STD(CLOSE,20)))
        """
        part1 = self.H.rolling(window=5, min_periods=5).corr(self.V).diff(5)
        part2 = self.C.rolling(window=20, min_periods=20).std().rank(pct=True)
        return -1 * part1 * part2
    
    def alpha105(self):
        """
        -1*CORR(RANK(OPEN),RANK(VOLUME),10)
        """
        return -1 * self.O.rank(pct=True).rolling(window=10, min_periods=10).corr(self.V.rank(pct=True))
    
    def alpha106(self):
        """
        CLOSE-DELAY(CLOSE,20)
        """
        return self.C.diff(20)
    
    def alpha107(self):
        """
        (-1*RANK(OPEN-DELAY(HIGH,1)))*RANK(OPEN-DELAY(CLOSE,1))*RANK(OPEN-DELAY(LOW,1))
        """
        part1 = -1 * (self.O - self.H.shift(1)).rank(pct=True)
        part2 = (self.O - self.C.shift(1)).rank(pct=True)
        part3 = (self.O - self.L.shift(1)).rank(pct=True)
        return part1 * part2 * part3
    
    def alpha108(self):
        """
        (RANK(HIGH-MIN(HIGH,2))^RANK(CORR(VWAP,MEAN(VOLUME,120),6)))*-1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        high_min = self.H.rolling(window=2, min_periods=1).min()
        part1 = (self.H - high_min).rank(pct=True, method='min')
        
        vol_window = min(120, len(self.df) // 2)
        corr_window = min(6, len(self.df) // 6)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vwap.rolling(window=corr_window, min_periods=max(3, corr_window//2)).corr(vol_ma).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_corr.rank(pct=True, method='min')
        
        alpha = pd.Series(index=self.df.index, dtype=float)
        for i in range(len(self.df)):
            p1 = part1.iloc[i]
            p2 = part2.iloc[i]
            if pd.notna(p1) and pd.notna(p2):
                p1 = max(0.001, min(p1, 0.999))
                try:
                    alpha.iloc[i] = -(p1 ** p2)
                except:
                    alpha.iloc[i] = np.nan
            else:
                alpha.iloc[i] = np.nan
        
        return alpha.fillna(method='ffill').fillna(method='bfill')
    
    def alpha109(self):
        """
        SMA(HIGH-LOW,10,2)/SMA(SMA(HIGH-LOW,10,2),10,2)
        """
        hl = self.H - self.L
        sma = self._sma(hl, 10, 2)
        return sma / self._sma(sma, 10, 2)
    
    def alpha110(self):
        """
        SUM(MAX(0,HIGH-DELAY(CLOSE,1)),20)/SUM(MAX(0,DELAY(CLOSE,1)-LOW),20)*100
        """
        part1 = np.maximum(self.H - self.C.shift(1), 0.0).rolling(window=20, min_periods=20).sum()
        part2 = np.maximum(self.C.shift(1) - self.L, 0.0).rolling(window=20, min_periods=20).sum()
        return part1 / part2 * 100.0
    
    def alpha111(self):
        """
        SMA(VOL*(2*CLOSE-LOW-HIGH)/(HIGH-LOW),11,2)-SMA(VOL*(2*CLOSE-LOW-HIGH)/(HIGH-LOW),4,2)
        """
        win_vol = self.V * (2 * self.C - self.L - self.H) / (self.H - self.L)
        return self._sma(win_vol, 11, 2) - self._sma(win_vol, 4, 2)
    
    def alpha112(self):
        """
        (SUM((CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0),12)-SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12))
        /(SUM((CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0),12)+SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12))*100
        """
        diff = self.C.diff()
        part1 = np.maximum(diff, 0.0).rolling(window=12, min_periods=12).sum()
        part2 = abs(np.minimum(diff, 0.0)).rolling(window=12, min_periods=12).sum()
        return (part1 - part2) / (part1 + part2) * 100
    
    def alpha113(self):
        """
        -1*RANK(SUM(DELAY(CLOSE,5),20)/20)*CORR(CLOSE,VOLUME,2)*RANK(CORR(SUM(CLOSE,5),SUM(CLOSE,20),2))
        """
        self.V = self.V.replace(0, np.nan).fillna(method='ffill').fillna(method='bfill')
        
        part1_series = self.C.shift(5).rolling(window=20, min_periods=10).mean().fillna(method='ffill').fillna(method='bfill')
        part1 = part1_series.rank(pct=True, method='min')
        
        part2 = self.C.rolling(window=2, min_periods=2).corr(self.V).fillna(method='ffill').fillna(method='bfill').clip(-1, 1)
        
        sum5 = self.C.rolling(window=5, min_periods=3).sum().fillna(method='ffill').fillna(method='bfill')
        sum20 = self.C.rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill')
        part3_corr = sum5.rolling(window=2, min_periods=2).corr(sum20).fillna(method='ffill').fillna(method='bfill').clip(-1, 1)
        part3 = part3_corr.rank(pct=True, method='min')
        
        return -1 * part1 * part2 * part3
    
    def alpha114(self):
        """
        RANK(DELAY((HIGH-LOW)/(SUM(CLOSE,5)/5),2))*RANK(RANK(VOLUME))/((HIGH-LOW)/(SUM(CLOSE,5)/5)/(VWAP-CLOSE))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        hl = self.H - self.L
        close_ma5 = self.C.rolling(window=5, min_periods=3).mean().fillna(method='ffill').fillna(method='bfill')
        hl_ma = (hl / close_ma5).fillna(method='ffill').fillna(method='bfill')
        
        part1 = hl_ma.shift(2).rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        vol_rank1 = self.V.rank(pct=True, method='min')
        part2 = vol_rank1.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        vwap_close_diff = vwap - self.C
        threshold = 0.0001
        mask_small = abs(vwap_close_diff) < threshold
        vwap_close_diff[mask_small] = threshold * np.sign(vwap_close_diff[mask_small])
        vwap_close_diff = vwap_close_diff.replace(0, threshold)
        part3 = (hl_ma / vwap_close_diff).fillna(method='ffill').fillna(method='bfill')
        part3 = part3.clip(lower=part3.quantile(0.01), upper=part3.quantile(0.99))
        
        alpha = (part1 * part2 / part3).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha115(self):
        """
        (RANK(CORR(HIGH*0.9+CLOSE*0.1,MEAN(VOLUME,30),10))^RANK(CORR(TSRANK((HIGH+LOW)/2,4),TSRANK(VOLUME,10),7)))
        """
        part1 = (self.H * 0.9 + self.C * 0.1).rolling(window=10, min_periods=10).corr(
            self.V.rolling(window=30, min_periods=30).mean()
        ).rank(pct=True)
        part2 = self._tsrank((self.H + self.L) / 2, 4)
        part2 = part2.rolling(window=7, min_periods=7).corr(self._tsrank(self.V, 10)).rank(pct=True)
        return part1 ** part2
    
    def alpha116(self):
        """
        REGBETA(CLOSE,SEQUENCE,20)
        """
        result = pd.Series(index=self.df.index, dtype=float)
        for i in range(20, len(self.df)):
            y = self.C.iloc[i-20:i]
            x = np.arange(1, 21)
            result.iloc[i] = self._regbeta(y, x)
        return result.fillna(0)
    
    def alpha117(self):
        """
        TSRANK(VOLUME,32)*(1-TSRANK(CLOSE+HIGH-LOW,16))*(1-TSRANK(RET,32))
        """
        part1 = self._tsrank(self.V, 32)
        part2 = 1.0 - self._tsrank(self.C + self.H - self.L, 16)
        part3 = 1.0 - self._tsrank(self.C.pct_change(), 32)
        return part1 * part2 * part3
    
    def alpha118(self):
        """
        SUM(HIGH-OPEN,20)/SUM(OPEN-LOW,20)*100
        """
        part1 = (self.H - self.O).rolling(window=20, min_periods=20).sum()
        part2 = (self.O - self.L).rolling(window=20, min_periods=20).sum()
        return part1 / part2 * 100.0
    
    def alpha119(self):
        """
        RANK(DECAYLINEAR(CORR(VWAP,SUM(MEAN(VOLUME,5),26),5),7))-RANK(DECAYLINEAR(TSRANK(MIN(CORR(RANK(OPEN),RANK(MEAN(VOLUME,15)),21),9),7),8))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w7 = np.arange(1, 8)
        w8 = np.arange(1, 9)
        
        vol_ma5 = self.V.rolling(window=5, min_periods=3).mean().fillna(method='ffill').fillna(method='bfill')
        sum_window = min(26, len(self.df) // 3)
        corr_window1 = min(5, len(self.df) // 10)
        decay_window1 = min(7, len(self.df) // 10)
        
        vol_sum = vol_ma5.rolling(window=sum_window, min_periods=max(5, sum_window//5)).sum().fillna(method='ffill').fillna(method='bfill')
        part1_corr = vol_sum.rolling(window=corr_window1, min_periods=max(3, corr_window1//2)).corr(vwap).fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_corr.rolling(window=decay_window1, min_periods=max(3, decay_window1//2)).apply(
            lambda x: np.dot(x, w7[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min')
        
        vol_window = min(15, len(self.df) // 3)
        corr_window2 = min(21, len(self.df) // 3)
        min_window = min(9, len(self.df) // 5)
        decay_window2 = min(8, len(self.df) // 5)
        
        vol_ma15 = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//3)).mean().fillna(method='ffill').fillna(method='bfill')
        vol_ma15_rank = vol_ma15.rank(pct=True, method='min')
        open_rank = self.O.rank(pct=True, method='min')
        part2_corr = vol_ma15_rank.rolling(window=corr_window2, min_periods=max(5, corr_window2//4)).corr(open_rank).fillna(method='ffill').fillna(method='bfill')
        part2_min = part2_corr.rolling(window=min_window, min_periods=max(3, min_window//3)).min().fillna(method='ffill').fillna(method='bfill')
        part2_tsrank = self._tsrank_fixed(part2_min, 7)
        part2_decay = part2_tsrank.rolling(window=decay_window2, min_periods=max(3, decay_window2//2)).apply(
            lambda x: np.dot(x, w8[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min')
        
        return (part1 - part2).fillna(method='ffill').fillna(method='bfill')
    
    def alpha120(self):
        """
        RANK(VWAP-CLOSE)/RANK(VWAP+CLOSE)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        denominator = vwap + self.C
        denominator = denominator.replace(0, 1e-10)
        alpha = ((vwap - self.C) / denominator).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha121(self):
        """
        (RANK(VWAP-MIN(VWAP,12))^TSRANK(CORR(TSRANK(VWAP,20),TSRANK(MEAN(VOLUME,60),2),18),3))*-1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vwap_min = vwap.rolling(window=12, min_periods=6).min().fillna(method='ffill').fillna(method='bfill')
        part1 = (vwap - vwap_min).rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill').clip(0.001, 0.999)
        
        vol_window = min(60, len(self.df) // 2)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//6)).mean().fillna(method='ffill').fillna(method='bfill')
        tsrank_vwap = self._tsrank_fixed(vwap, 20)
        tsrank_vol = self._tsrank_fixed(vol_ma, 2)
        corr_window = min(18, len(self.df) // 3)
        part2_corr = tsrank_vwap.rolling(window=corr_window, min_periods=max(5, corr_window//3)).corr(tsrank_vol).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_corr, 3).fillna(method='ffill').fillna(method='bfill').clip(0.001, 0.999)
        
        alpha = pd.Series(index=self.df.index, dtype=float)
        for i in range(len(self.df)):
            p1 = part1.iloc[i]
            p2 = part2.iloc[i]
            if pd.notna(p1) and pd.notna(p2):
                try:
                    alpha.iloc[i] = -(p1 ** p2)
                except:
                    alpha.iloc[i] = np.nan
            else:
                alpha.iloc[i] = np.nan
        
        return alpha.fillna(method='ffill').fillna(method='bfill')
    
    def alpha122(self):
        """
        (SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2)-DELAY(SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2),1))/DELAY(SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2),1)
        """
        part1 = np.log(self.C)
        part1 = self._sma(part1, 13, 2)
        part1 = self._sma(part1, 13, 2)
        part1 = self._sma(part1, 13, 2)
        return part1.pct_change()
    
    def alpha123(self):
        """
        (RANK(CORR(SUM((HIGH+LOW)/2,20),SUM(MEAN(VOLUME,60),20),9)) < RANK(CORR(LOW,VOLUME,6)))*-1
        """
        part1 = (self.H * 0.5 + self.L * 0.5).rolling(window=20, min_periods=20).sum()
        part1 = self.V.rolling(window=60, min_periods=60).mean().rolling(window=20, min_periods=20).sum().rolling(window=9, min_periods=9).corr(part1).rank(pct=True)
        part2 = self.L.rolling(window=6, min_periods=6).corr(self.V).rank(pct=True)
        return -1 * (part2 - part1)
    
    def alpha124(self):
        """
        (CLOSE-VWAP)/DECAYLINEAR(RANK(TSMAX(CLOSE,30)),2)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        part1 = self.C - vwap
        close_max = self.C.rolling(window=30, min_periods=15).max().fillna(method='ffill').fillna(method='bfill')
        part2_rank = close_max.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        w2 = np.arange(1, 3)
        part2 = part2_rank.rolling(window=2, min_periods=1).apply(
            lambda x: np.dot(x, w2[:len(x)]) if len(x) >= 1 else np.nan
        ).fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        
        alpha = (part1 / part2).fillna(method='ffill').fillna(method='bfill')
        alpha = alpha.clip(lower=alpha.quantile(0.01), upper=alpha.quantile(0.99))
        return alpha
    
    def alpha125(self):
        """
        RANK(DECAYLINEAR(CORR(VWAP,MEAN(VOLUME,80),17),20))/RANK(DECAYLINEAR(DELTA(CLOSE*0.5+VWAP*0.5,3),16))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w20 = np.arange(1, 21)
        w16 = np.arange(1, 17)
        
        vol_window = min(80, len(self.df) // 2)
        corr_window = min(17, len(self.df) // 3)
        decay_window1 = min(20, len(self.df) // 3)
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//8)).mean().fillna(method='ffill').fillna(method='bfill')
        part1_corr = vol_ma.rolling(window=corr_window, min_periods=max(5, corr_window//3)).corr(vwap).fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_corr.rolling(window=decay_window1, min_periods=max(5, decay_window1//4)).apply(
            lambda x: np.dot(x, w20[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        decay_window2 = min(16, len(self.df) // 3)
        weighted_price = self.C * 0.5 + vwap * 0.5
        part2_diff = weighted_price.diff(3).fillna(0)
        part2_decay = part2_diff.rolling(window=decay_window2, min_periods=max(5, decay_window2//3)).apply(
            lambda x: np.dot(x, w16[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        
        alpha = (part1 / part2).fillna(method='ffill').fillna(method='bfill')
        alpha = alpha.clip(lower=alpha.quantile(0.01), upper=alpha.quantile(0.99))
        return alpha
    
    def alpha126(self):
        """
        (CLOSE+HIGH+LOW)/3
        """
        return (self.C + self.H + self.L) / 3.0
    
    def alpha127(self):
        """
        MEAN((100*(CLOSE-MAX(CLOSE,12))/MAX(CLOSE,12))^2)^(1/2)
        """
        close_max = self.C.rolling(window=12, min_periods=12).max()
        alpha = (self.C - close_max) / close_max * 100
        return (alpha ** 2).rolling(window=12, min_periods=12).mean() ** 0.5
    
    def alpha128(self):
        """
        100-(100/(1+SUM(((HIGH+LOW+CLOSE)/3>DELAY((HIGH+LOW+CLOSE)/3,1)?(HIGH+LOW+CLOSE)/3*VOLUME:0),14)/
        SUM(((HIGH+LOW+CLOSE)/3<DELAY((HIGH+LOW+CLOSE)/3,1)?(HIGH+LOW+CLOSE)/3*VOLUME:0),14)))
        """
        tp = (self.H + self.L + self.C) / 3.0
        condition1 = tp.diff() > 0.0
        condition2 = tp.diff() < 0.0
        
        part1 = tp * self.V
        part1[~condition1] = 0.0
        part1 = part1.rolling(window=14, min_periods=14).sum()
        
        part2 = tp * self.V
        part2[~condition2] = 0.0
        part2 = part2.rolling(window=14, min_periods=14).sum()
        
        return 100.0 - 100.0 / (1 + part1 / part2)
    
    def alpha129(self):
        """
        SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12)
        """
        return abs(np.minimum(self.C.diff(), 0.0)).rolling(window=12, min_periods=12).sum()
    
    def alpha130(self):
        """
        (RANK(DECAYLINEAR(CORR((HIGH+LOW)/2,MEAN(VOLUME,40),9),10))/RANK(DECAYLINEAR(CORR(RANK(VWAP),RANK(VOLUME),7),3)))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w10 = np.arange(1, 11)
        w3 = np.arange(1, 4)
        
        vol_window = min(40, len(self.df) // 2)
        corr_window1 = min(9, len(self.df) // 4)
        decay_window1 = min(10, len(self.df) // 4)
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//4)).mean().fillna(method='ffill').fillna(method='bfill')
        hl_avg = self.H * 0.5 + self.L * 0.5
        part1_corr = vol_ma.rolling(window=corr_window1, min_periods=max(5, corr_window1//2)).corr(hl_avg).fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_corr.rolling(window=decay_window1, min_periods=max(5, decay_window1//2)).apply(
            lambda x: np.dot(x, w10[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        corr_window2 = min(7, len(self.df) // 5)
        decay_window2 = min(3, len(self.df) // 10)
        vwap_rank = vwap.rank(pct=True, method='min')
        vol_rank = self.V.rank(pct=True, method='min')
        part2_corr = vwap_rank.rolling(window=corr_window2, min_periods=max(4, corr_window2//2)).corr(vol_rank).fillna(method='ffill').fillna(method='bfill')
        part2_decay = part2_corr.rolling(window=decay_window2, min_periods=2).apply(
            lambda x: np.dot(x, w3[:len(x)]) if len(x) >= 2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        
        alpha = (part1 / part2).fillna(method='ffill').fillna(method='bfill')
        alpha = alpha.clip(lower=alpha.quantile(0.01), upper=alpha.quantile(0.99))
        return alpha
    
    def alpha131(self):
        """
        (RANK(DELTA(VWAP,1))^TSRANK(CORR(CLOSE,MEAN(VOLUME,50),18),18))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vwap_diff = vwap.diff().fillna(0)
        part1 = vwap_diff.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill').clip(0.001, 0.999)
        
        vol_window = min(50, len(self.df) // 2)
        corr_window = min(18, len(self.df) // 3)
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//5)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vol_ma.rolling(window=corr_window, min_periods=max(5, corr_window//3)).corr(self.C).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_corr, 18).fillna(method='ffill').fillna(method='bfill').clip(0.001, 0.999)
        
        alpha = np.exp(np.log(part1 + 1e-10) * part2)
        alpha = alpha.fillna(method='ffill').fillna(method='bfill').clip(0, 100)
        return alpha
    
    def alpha132(self):
        """
        MEAN(AMOUNT,20)
        """
        return self.AMOUNT.rolling(window=20, min_periods=20).mean()
    
    def alpha133(self):
        """
        ((20-HIGHDAY(HIGH,20))/20)*100-((20-LOWDAY(LOW,20))/20)*100
        """
        def highday(x):
            return 19 - x.argmax() if len(x) == 20 else np.nan
        def lowday(x):
            return 19 - x.argmin() if len(x) == 20 else np.nan
        
        part1 = (20 - self.H.rolling(window=20, min_periods=20).apply(highday)) / 20 * 100
        part2 = (20 - self.L.rolling(window=20, min_periods=20).apply(lowday)) / 20 * 100
        return part1 - part2
    
    def alpha134(self):
        """
        (CLOSE-DELAY(CLOSE,12))/DELAY(CLOSE,12)*VOLUME
        """
        return self.C.pct_change(periods=12) * self.V
    
    def alpha135(self):
        """
        SMA(DELAY(CLOSE/DELAY(CLOSE,20),1),20,1)
        """
        alpha = (self.C / self.C.shift(20)).shift(1)
        return self._sma(alpha, 20, 1)
    
    def alpha136(self):
        """
        -1*RANK(DELTA(RET,3))*CORR(OPEN,VOLUME,10)
        """
        ret = self.C.pct_change()
        part1 = ret.diff(3).rank(pct=True)
        part2 = self.O.rolling(window=10, min_periods=10).corr(self.V)
        return -1 * part1 * part2
    
    def alpha137(self):
        """
        16*(CLOSE+(CLOSE-OPEN)/2-DELAY(OPEN,1))/
        ((ABS(HIGH-DELAY(CLOSE,1))>ABS(LOW-DELAY(CLOSE,1))&ABS(HIGH-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1))?ABS(HIGH-DELAY(CLOSE,1))+ABS(LOW-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
        (ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) & ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(CLOSE,1))?ABS(LOW-DELAY(CLOSE,1))+ABS(HIGH-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:ABS(HIGH-DELAY(LOW,1))+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4)))
        *MAX(ABS(HIGH-DELAY(CLOSE,1)),ABS(LOW-DELAY(CLOSE,1)))
        """
        part1 = self.C * 1.5 - self.O * 0.5 - self.O.shift(1)
        part2 = abs(self.H - self.C.shift(1)) + abs(self.L - self.C.shift(1)) / 2.0 + abs(self.C - self.O).shift(1) / 4.0
        
        condition1 = np.logical_and(
            abs(self.H - self.C.shift(1)) > abs(self.L - self.C.shift(1)),
            abs(self.H - self.C.shift(1)) > abs(self.H - self.L.shift(1))
        )
        condition2 = np.logical_and(
            abs(self.L - self.C.shift(1)) > abs(self.H - self.L.shift(1)),
            abs(self.L - self.C.shift(1)) > abs(self.H - self.C.shift(1))
        )
        
        part2[~condition1 & condition2] = abs(self.L - self.C.shift(1)) + abs(self.H - self.C.shift(1)) / 2.0 + abs(self.C - self.O).shift(1) / 4.0
        part2[~condition1 & ~condition2] = abs(self.H - self.L.shift(1)) + abs(self.C - self.O).shift(1) / 4.0
        
        part3 = np.maximum(abs(self.H - self.C.shift(1)), abs(self.L - self.C.shift(1)))
        alpha = part1 / part2 * part3 * 16.0
        return alpha
    
    def alpha138(self):
        """
        ((RANK(DECAYLINEAR(DELTA(LOW*0.7+VWAP*0.3,3),20))
        -TSRANK(DECAYLINEAR(TSRANK(
            CORR(TSRANK(LOW,8),TSRANK(MEAN(VOLUME,60),17),5)
            ,19),16),7))* -1)
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w20 = np.arange(1, 21)
        w16 = np.arange(1, 17)
        
        decay_window1 = min(20, len(self.df) // 3)
        weighted_price = self.L * 0.7 + vwap * 0.3
        part1_diff = weighted_price.diff(3).fillna(0)
        part1_decay = part1_diff.rolling(window=decay_window1, min_periods=max(5, decay_window1//4)).apply(
            lambda x: np.dot(x, w20[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(60, len(self.df) // 2)
        tsrank_window1 = min(17, len(self.df) // 3)
        corr_window = min(5, len(self.df) // 6)
        tsrank_window2 = min(19, len(self.df) // 3)
        decay_window2 = min(16, len(self.df) // 3)
        tsrank_window3 = min(7, len(self.df) // 5)
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//6)).mean().fillna(method='ffill').fillna(method='bfill')
        tsrank_vol = self._tsrank_fixed(vol_ma, tsrank_window1).fillna(method='ffill').fillna(method='bfill')
        tsrank_low = self._tsrank_fixed(self.L, 8).fillna(method='ffill').fillna(method='bfill')
        part2_corr = tsrank_low.rolling(window=corr_window, min_periods=max(3, corr_window//2)).corr(tsrank_vol).fillna(method='ffill').fillna(method='bfill')
        part2_tsrank = self._tsrank_fixed(part2_corr, tsrank_window2).fillna(method='ffill').fillna(method='bfill')
        part2_decay = part2_tsrank.rolling(window=decay_window2, min_periods=max(5, decay_window2//3)).apply(
            lambda x: np.dot(x, w16[:len(x)]) if len(x) >= 5 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_decay, tsrank_window3).fillna(method='ffill').fillna(method='bfill')
        
        alpha = -1 * (part1 - part2).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha139(self):
        """
        (-1*CORR(OPEN,VOLUME,10))
        """
        return -1 * self.O.rolling(window=10, min_periods=10).corr(self.V)
    
    def alpha140(self):
        """
        MIN(RANK(DECAYLINEAR(RANK(OPEN)+RANK(LOW)-RANK(HIGH)-RANK(CLOSE),8)),TSRANK(DECAYLINEAR(CORR(TSRANK(CLOSE,8),TSRANK(MEAN(VOLUME,60),20),8),7),3))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        w8 = np.arange(1, 9)
        w7 = np.arange(1, 8)
        
        decay_window1 = min(8, len(self.df) // 4)
        open_rank = self.O.rank(pct=True, method='min')
        low_rank = self.L.rank(pct=True, method='min')
        high_rank = self.H.rank(pct=True, method='min')
        close_rank = self.C.rank(pct=True, method='min')
        
        part1_series = open_rank + low_rank - high_rank - close_rank
        part1_series = part1_series.fillna(method='ffill').fillna(method='bfill')
        part1_decay = part1_series.rolling(window=decay_window1, min_periods=max(4, decay_window1//2)).apply(
            lambda x: np.dot(x, w8[:len(x)]) if len(x) >= 4 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        vol_window = min(60, len(self.df) // 2)
        tsrank_window1 = min(20, len(self.df) // 3)
        corr_window = min(8, len(self.df) // 4)
        decay_window2 = min(7, len(self.df) // 5)
        tsrank_window2 = min(3, len(self.df) // 10)
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//6)).mean().fillna(method='ffill').fillna(method='bfill')
        tsrank_vol = self._tsrank_fixed(vol_ma, tsrank_window1).fillna(method='ffill').fillna(method='bfill')
        tsrank_close = self._tsrank_fixed(self.C, 8).fillna(method='ffill').fillna(method='bfill')
        part2_corr = tsrank_close.rolling(window=corr_window, min_periods=max(4, corr_window//2)).corr(tsrank_vol).fillna(method='ffill').fillna(method='bfill')
        part2_decay = part2_corr.rolling(window=decay_window2, min_periods=max(3, decay_window2//2)).apply(
            lambda x: np.dot(x, w7[:len(x)]) if len(x) >= 3 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = self._tsrank_fixed(part2_decay, tsrank_window2).fillna(method='ffill').fillna(method='bfill')
        
        alpha = np.minimum(part1, part2).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha141(self):
        """
        (RANK(CORR(RANK(HIGH),RANK(MEAN(VOLUME,15)),9))*-1)
        """
        alpha = self.V.rolling(window=15, min_periods=15).mean().rank(pct=True)
        alpha = alpha.rolling(window=9, min_periods=9).corr(self.H.rank(pct=True)).rank(pct=True)
        return -1 * alpha
    
    def alpha142(self):
        """
        -1*RANK(TSRANK(CLOSE,10))*RANK(DELTA(DELTA(CLOSE,1),1))*RANK(TSRANK(VOLUME/MEAN(VOLUME,20),5))
        """
        part1 = self._tsrank(self.C, 10).rank(pct=True)
        part2 = self.C.diff().diff().rank(pct=True)
        part3 = self._tsrank(self.V / self.V.rolling(window=20, min_periods=20).mean(), 5).rank(pct=True)
        return -1 * part1 * part2 * part3
    
    def alpha143(self):
        """
        CLOSE>DELAY(CLOSE,1)?(CLOSE-DELAY(CLOSE,1))/DELAY(CLOSE,1)*SELF:SELF
        """
        condition = self.C > self.C.shift(1)
        alpha = self.C.pct_change()
        alpha[~condition] = alpha.shift(1)[~condition]
        return alpha
    
    def alpha144(self):
        """
        SUMIF(ABS(CLOSE/DELAY(CLOSE,1)-1)/AMOUNT,20,CLOSE<DELAY(CLOSE,1))/COUNT(CLOSE<DELAY(CLOSE,1),20)
        """
        part1 = abs(self.C.pct_change()) / self.AMOUNT
        part1[self.C.diff() >= 0] = 0.0
        part1 = part1.rolling(window=20, min_periods=20).sum()
        part2 = (self.C.diff() < 0.0).rolling(window=20, min_periods=20).sum()
        return part1 / part2
    
    def alpha145(self):
        """
        (MEAN(VOLUME,9)-MEAN(VOLUME,26))/MEAN(VOLUME,12)*100
        """
        ma9 = self.V.rolling(window=9, min_periods=9).mean()
        ma26 = self.V.rolling(window=26, min_periods=26).mean()
        ma12 = self.V.rolling(window=12, min_periods=12).mean()
        return (ma9 - ma26) / ma12 * 100.0
    
    def alpha146(self):
        """
        MEAN(RET-SMA(RET,61,2),20)*(RET-SMA(RET,61,2))/SMA(SMA(RET,61,2)^2,60)
        """
        ret = self.C.pct_change()
        sma = self._sma(ret, 61, 2)
        ret_excess = ret - sma
        part1 = ret_excess.rolling(window=20, min_periods=20).mean() * ret_excess
        part2 = self._sma(sma ** 2, 60, 1)
        return part1 / part2
    
    def alpha147(self):
        """
        REGBETA(MEAN(CLOSE,12),SEQUENCE(12))
        """
        ma_price = self.C.rolling(window=12, min_periods=12).mean()
        result = pd.Series(index=self.df.index, dtype=float)
        for i in range(12, len(self.df)):
            y = ma_price.iloc[i-12:i]
            x = np.arange(1, 13)
            result.iloc[i] = self._regbeta(y, x)
        return result.fillna(0)
    
    def alpha148(self):
        """
        (RANK(CORR(OPEN,SUM(MEAN(VOLUME,60),9),6))<RANK(OPEN-TSMIN(OPEN,14)))*-1
        """
        part1 = self.V.rolling(window=60, min_periods=60).mean().rolling(window=9, min_periods=9).sum()
        part1 = part1.rolling(window=6, min_periods=6).corr(self.O).rank(pct=True)
        part2 = (self.O - self.O.rolling(window=14, min_periods=14).min()).rank(pct=True)
        return -1 * (part2 - part1)
    
    def alpha149(self):
        """
        REGBETA(FILTER(RET,BANCHMARK_INDEX_CLOSE<DELAY(BANCHMARK_INDEX_CLOSE,1)),
        FILTER(BANCHMARK_INDEX_CLOSE/DELAY(BANCHMARK_INDEX_CLOSE,1)-1,BANCHMARK_INDEX_CLOSE<DELAY(BANCHMARK_INDEX_CLOSE,1)),252)
        调整窗口期以适应数据量
        """
        n_rows = len(self.df)
        if n_rows < 252:
            window = max(60, n_rows // 2)
        else:
            window = 252
        
        if hasattr(self, 'index_df') and self.index_df is not None:
            index_data = self.index_df.copy()
            if 'close' in index_data.columns:
                index_close = index_data['close']
            elif 'closePrice' in index_data.columns:
                index_close = index_data['closePrice']
            else:
                index_close = index_data.iloc[:, 0]
            
            if 'date' in self.df.columns and 'date' in index_data.columns:
                self.df['date'] = pd.to_datetime(self.df['date'])
                index_data['date'] = pd.to_datetime(index_data['date'])
                date_to_index = dict(zip(index_data['date'], index_close))
                bm_close = self.df['date'].map(date_to_index).fillna(method='ffill').fillna(method='bfill')
            else:
                bm_close = index_close.reindex(self.df.index, method='ffill')
        else:
            bm_close = self.C.rolling(window=20, min_periods=5).mean()
        
        bm_ret = bm_close.pct_change().fillna(0)
        bm_down = bm_ret < 0.0
        stock_ret = self.C.pct_change().fillna(0)
        
        result = pd.Series(index=self.df.index, dtype=float)
        if n_rows < window:
            return pd.Series(0, index=self.df.index)
        
        for i in range(window, n_rows):
            start_idx = i - window
            bm_down_window = bm_down.iloc[start_idx:i]
            valid_indices = bm_down_window[bm_down_window].index
            if len(valid_indices) < 5:
                result.iloc[i] = np.nan
                continue
            y = stock_ret.loc[valid_indices]
            x = bm_ret.loc[valid_indices]
            valid_mask = ~(y.isna() | x.isna())
            y_clean = y[valid_mask]
            x_clean = x[valid_mask]
            if len(y_clean) > 3:
                try:
                    slope, intercept, r_value, p_value, std_err = stats.linregress(x_clean, y_clean)
                    result.iloc[i] = slope
                except:
                    result.iloc[i] = np.nan
            else:
                result.iloc[i] = np.nan
        
        result = result.fillna(method='ffill').fillna(method='bfill').fillna(0)
        return result
    
    def alpha150(self):
        """
        (CLOSE+HIGH+LOW)/3*VOLUME
        """
        return (self.C + self.H + self.L) / 3.0 * self.V
    
    def alpha151(self):
        """
        SMA(CLOSE-DELAY(CLOSE,20),20,1)
        """
        return self._sma(self.C.diff(20), 20, 1)
    
    def alpha152(self):
        """
        A=DELAY(SMA(DELAY(CLOSE/DELAY(CLOSE,9),1),9,1),1)
        SMA(MEAN(A,12)-MEAN(A,26),9,1)
        """
        a = (self.C / self.C.shift(9)).shift(1)
        a = self._sma(a, 9, 1).shift(1)
        alpha = (a.rolling(window=12, min_periods=12).mean() - a.rolling(window=26, min_periods=26).mean())
        alpha = self._sma(alpha, 9, 1)
        return alpha
    
    def alpha153(self):
        """
        (MEAN(CLOSE,3)+MEAN(CLOSE,6)+MEAN(CLOSE,12)+MEAN(CLOSE,24))/4
        """
        ma3 = self.C.rolling(window=3, min_periods=3).mean()
        ma6 = self.C.rolling(window=6, min_periods=6).mean()
        ma12 = self.C.rolling(window=12, min_periods=12).mean()
        ma24 = self.C.rolling(window=24, min_periods=24).mean()
        return (ma3 + ma6 + ma12 + ma24) / 4
    
    def alpha154(self):
        """
        VWAP-MIN(VWAP,16)<CORR(VWAP,MEAN(VOLUME,180),18)
        """
        n_rows = len(self.df)
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        vwap_min = vwap.rolling(window=16, min_periods=8).min().fillna(method='ffill').fillna(method='bfill')
        part1 = vwap - vwap_min
        
        if n_rows < 180:
            vol_window = max(60, n_rows // 2)
            corr_window = max(10, min(18, n_rows // 5))
        else:
            vol_window = 180
            corr_window = 18
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(10, vol_window//10)).mean().fillna(method='ffill').fillna(method='bfill')
        part2_corr = vol_ma.rolling(window=corr_window, min_periods=max(5, corr_window//3)).corr(vwap).fillna(method='ffill').fillna(method='bfill')
        
        alpha = (part2_corr - part1).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha155(self):
        """
        SMA(VOLUME,13,2)-SMA(VOLUME,27,2)-SMA(SMA(VOLUME,13,2)-SMA(VOLUME,27,2),10,2)
        """
        sma13 = self._sma(self.V, 13, 2)
        sma27 = self._sma(self.V, 27, 2)
        diff = sma13 - sma27
        return sma13 - sma27 - self._sma(diff, 10, 2)
    
    def alpha156(self):
        """
        MAX(RANK(DECAYLINEAR(DELTA(VWAP,5),3)),RANK(DECAYLINEAR((DELTA(OPEN*0.15+LOW*0.85,2)/(OPEN*0.15+LOW*0.85)) * -1,3))) * -1
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        
        w3 = np.arange(1, 4)
        den = self.O * 0.15 + self.L * 0.85
        
        vwap_diff = vwap.diff(5).fillna(0)
        part1_decay = vwap_diff.rolling(window=3, min_periods=2).apply(
            lambda x: np.dot(x, w3[:len(x)]) if len(x) >= 2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        den = den.replace(0, 1e-10)
        den_diff = den.diff(2).fillna(0)
        den_ratio = (den_diff / den) * (-1)
        den_ratio = den_ratio.replace([np.inf, -np.inf], np.nan).fillna(method='ffill').fillna(method='bfill').clip(-100, 100)
        part2_decay = den_ratio.rolling(window=3, min_periods=2).apply(
            lambda x: np.dot(x, w3[:len(x)]) if len(x) >= 2 else np.nan
        ).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_decay.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        alpha = -1 * np.maximum(part1, part2).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha157(self):
        """
        MIN(PROD(RANK(LOG(SUM(TSMIN(RANK(-1*RANK(DELTA(CLOSE-1,5))),2),1))),1),5)+TSRANK(DELAY(-1*RET,6),5)
        """
        part1 = (self.C - 1.0).diff(5).rank(pct=True) * (-1)
        part1 = part1.rank(pct=True).rolling(window=2, min_periods=2).min()
        part1 = np.log(part1.rolling(window=1, min_periods=1).sum()).rank(pct=True)
        part1 = part1.rolling(window=5, min_periods=5).min()
        
        part2 = self._tsrank((-1 * self.C.pct_change()).shift(6), 5)
        
        return part1 + part2
    
    def alpha158(self):
        """
        (HIGH-LOW)/CLOSE
        """
        return (self.H - self.L) / self.C
    
    def alpha159(self):
        """
        ((CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),6))/SUM(MAX(HIGH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),6)*12*24
        +(CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),12))/SUM(MAX(HIGH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),12)*6*24
        +(CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),24))/SUM(MAX(HIGH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),24)*6*12)*100/(6*12+6*24+12*24)
        """
        min_low_close = np.minimum(self.L, self.C.shift(1))
        max_high_close = np.maximum(self.H, self.C.shift(1))
        diff = max_high_close - min_low_close
        
        part1 = (self.C - min_low_close.rolling(window=6, min_periods=6).sum()) / diff.rolling(window=6, min_periods=6).sum() * 12 * 24
        part2 = (self.C - min_low_close.rolling(window=12, min_periods=12).sum()) / diff.rolling(window=12, min_periods=12).sum() * 6 * 24
        part3 = (self.C - min_low_close.rolling(window=24, min_periods=24).sum()) / diff.rolling(window=24, min_periods=24).sum() * 6 * 12
        
        return (part1 + part2 + part3) * 100.0 / (12 * 6 + 6 * 24 + 12 * 24)
    
    def alpha160(self):
        """
        SMA((CLOSE<=DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)
        """
        part1 = self.C.rolling(window=20, min_periods=20).std()
        part1[self.C.diff() > 0] = 0.0
        return self._sma(part1, 20, 1)
    
    def alpha161(self):
        """
        MEAN(MAX(MAX(HIGH-LOW,ABS(DELAY(CLOSE,1)-HIGH)),ABS(DELAY(CLOSE,1)-LOW)),12)
        """
        part1 = np.maximum(self.H - self.L, abs(self.C.shift(1) - self.H))
        part1 = np.maximum(part1, abs(self.C.shift(1) - self.L))
        return part1.rolling(window=12, min_periods=12).mean()
    
    def alpha162(self):
        """
        (SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100
        -MIN(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12))
        /(MAX(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12)
        -MIN(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12))
        """
        diff = self.C.diff()
        den = np.maximum(diff, 0.0).ewm(adjust=False, alpha=1/12, min_periods=0).mean() / abs(diff).ewm(adjust=False, alpha=1/12, min_periods=0).mean() * 100.0
        
        alpha = (den - den.rolling(window=12, min_periods=12).min()) / (den.rolling(window=12, min_periods=12).max() - den.rolling(window=12, min_periods=12).min())
        return alpha
    
    def alpha163(self):
        """
        RANK((-1*RET)*MEAN(VOLUME,20)*VWAP*(HIGH-CLOSE))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        ret = self.C.pct_change().fillna(0)
        vol_ma = self.V.rolling(window=20, min_periods=10).mean().fillna(method='ffill').fillna(method='bfill')
        high_minus_close = self.H - self.C
        
        alpha = (-1 * ret) * vol_ma * vwap * high_minus_close
        alpha = alpha.fillna(method='ffill').fillna(method='bfill')
        alpha_rank = alpha.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        return alpha_rank
    
    def alpha164(self):
        """
        SMA(((CLOSE>DELAY(CLOSE,1)?1/(CLOSE-DELAY(CLOSE,1)):1)-MIN(CLOSE>DELAY(CLOSE,1)?1/(CLOSE-DELAY(CLOSE,1)):1,12))/(HIGH-LOW)*100,13,2)
        """
        diff = self.C.diff()
        part1 = 1.0 / diff
        part1[diff <= 0] = 1.0
        part2 = part1.rolling(window=12, min_periods=12).min()
        alpha = (part1 - part2) / (self.H - self.L) * 100.0
        return self._sma(alpha, 13, 2)
    
    def alpha165(self):
        """
        MAX(SUMAC(CLOSE-MEAN(CLOSE,48)))-MIN(SUMAC(CLOSE-MEAN(CLOSE,48)))/STD(CLOSE,48)
        """
        part = self.C - self.C.rolling(window=48, min_periods=48).mean()
        part = part.rolling(window=48, min_periods=48).sum()
        
        part1 = part.rolling(window=48, min_periods=48).max()
        part2 = part.rolling(window=48, min_periods=48).min()
        part3 = self.C.rolling(window=48, min_periods=48).std()
        
        return part1 - part2 / part3
    
    def alpha166(self):
        """
        -20*(20-1)^1.5*SUM(CLOSE/DELAY(CLOSE,1)-1-MEAN(CLOSE/DELAY(CLOSE,1)-1,20),20)/((20-1)*(20-2)*(SUM((CLOSE/DELAY(CLOSE,1))^2,20))^1.5)
        """
        ret = self.C.pct_change()
        ret_mean = ret.rolling(window=20, min_periods=20).mean()
        part1 = (ret - ret_mean).rolling(window=20, min_periods=20).sum() * (-20 * 19 ** 1.5)
        part2 = ((self.C / self.C.shift(1)) ** 2).rolling(window=20, min_periods=20).sum() ** 1.5 * 19 * 18
        return part1 / part2
    
    def alpha167(self):
        """
        SUM(CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0,12)
        """
        return np.maximum(self.C.diff(), 0.0).rolling(window=12, min_periods=12).sum()
    
    def alpha168(self):
        """
        -1*VOLUME/MEAN(VOLUME,20)
        """
        return -1 * self.V / self.V.rolling(window=20, min_periods=20).mean()
    
    def alpha169(self):
        """
        SMA(MEAN(DELAY(SMA(CLOSE-DELAY(CLOSE,1),9,1),1),12)-MEAN(DELAY(SMA(CLOSE-DELAY(CLOSE,1),9,1),1),26),10,1)
        """
        part1 = self._sma(self.C.diff(), 9, 1).shift(1)
        part2 = part1.rolling(window=12, min_periods=12).mean() - part1.rolling(window=26, min_periods=26).mean()
        return self._sma(part2, 10, 1)
    
    def alpha170(self):
        """
        ((RANK(1/CLOSE)*VOLUME)/MEAN(VOLUME,20))*(HIGH*RANK(HIGH-CLOSE)/(SUM(HIGH,5)/5))-RANK(VWAP-DELAY(VWAP,5))
        """
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        inv_close_rank = (1.0 / self.C).rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        vol_ma = self.V.rolling(window=20, min_periods=10).mean().fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        part1 = (inv_close_rank * self.V) / vol_ma
        
        high_minus_close_rank = (self.H - self.C).rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        high_ma5 = self.H.rolling(window=5, min_periods=3).sum() / 5.0
        high_ma5 = high_ma5.fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        part2 = (self.H * high_minus_close_rank) / high_ma5
        
        vwap_diff = vwap.diff(5).fillna(0)
        part3 = vwap_diff.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        alpha = (part1 * part2 - part3).fillna(method='ffill').fillna(method='bfill').clip(-10, 10)
        return alpha
    
    def alpha171(self):
        """
        (-1*(LOW-CLOSE)*(OPEN^5))/((CLOSE-HIGH)*(CLOSE^5))
        """
        self.C = self.C.clip(lower=1e-10)
        self.O = self.O.clip(lower=1e-10)
        self.H = self.H.clip(lower=1e-10)
        self.L = self.L.clip(lower=1e-10)
        
        part1 = (self.C - self.L) * (self.O ** 5)
        part2 = (self.C - self.H) * (self.C ** 5)
        part2 = part2.replace(0, 1e-10)
        mask_small = abs(part2) < 1e-10
        part2[mask_small] = 1e-10 * np.sign(part2[mask_small])
        
        alpha = part1 / part2
        alpha = alpha.replace([np.inf, -np.inf], np.nan).fillna(method='ffill').fillna(method='bfill').clip(-100, 100)
        return alpha
    
    def alpha172(self):
        """
        ADX指标
        """
        hd = self.H.diff()
        ld = -self.L.diff()
        tr = np.maximum(
            np.maximum(self.H - self.L, abs(self.H - self.C.shift(1))),
            abs(self.L - self.C.shift(1))
        )
        
        plus_dm = ((hd > 0) & (hd > ld)) * hd
        minus_dm = ((ld > 0) & (ld > hd)) * ld
        
        plus_di = plus_dm.rolling(window=14, min_periods=14).sum() * 100 / tr.rolling(window=14, min_periods=14).sum()
        minus_di = minus_dm.rolling(window=14, min_periods=14).sum() * 100 / tr.rolling(window=14, min_periods=14).sum()
        
        dx = abs(plus_di - minus_di) / (plus_di + minus_di) * 100
        return dx.rolling(window=6, min_periods=6).mean()
    
    def alpha173(self):
        """
        3*SMA(CLOSE,13,2)-2*SMA(SMA(CLOSE,13,2),13,2)+SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2)
        """
        sma = self._sma(self.C, 13, 2)
        sma2 = self._sma(sma, 13, 2)
        log_sma = self._sma(np.log(self.C), 13, 2)
        log_sma2 = self._sma(log_sma, 13, 2)
        log_sma3 = self._sma(log_sma2, 13, 2)
        
        return 3 * sma - 2 * sma2 + log_sma3
    
    def alpha174(self):
        """
        SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)
        """
        part1 = self.C.rolling(window=20, min_periods=20).std()
        part1[self.C.diff() <= 0] = 0.0
        return self._sma(part1, 20, 1)
    
    def alpha175(self):
        """
        MEAN(MAX(MAX(HIGH-LOW,ABS(DELAY(CLOSE,1)-HIGH)),ABS(DELAY(CLOSE,1)-LOW)),6)
        """
        part1 = np.maximum(self.H - self.L, abs(self.C.shift(1) - self.H))
        part1 = np.maximum(part1, abs(self.C.shift(1) - self.L))
        return part1.rolling(window=6, min_periods=6).mean()
    
    def alpha176(self):
        """
        CORR(RANK((CLOSE-TSMIN(LOW,12))/(TSMAX(HIGH,12)-TSMIN(LOW,12))),RANK(VOLUME),6)
        """
        high_max = self.H.rolling(window=12, min_periods=12).max()
        low_min = self.L.rolling(window=12, min_periods=12).min()
        part1 = (self.C - low_min) / (high_max - low_min)
        part1 = part1.rank(pct=True)
        part2 = self.V.rank(pct=True)
        return part1.rolling(window=6, min_periods=6).corr(part2)
    
    def alpha177(self):
        """
        ((20-HIGHDAY(HIGH,20))/20)*100
        """
        def highday(x):
            return 19 - x.argmax() if len(x) == 20 else np.nan
        return (20 - self.H.rolling(window=20, min_periods=20).apply(highday)) / 20 * 100
    
    def alpha178(self):
        """
        (CLOSE-DELAY(CLOSE,1))/DELAY(CLOSE,1)*VOLUME
        """
        return self.C.pct_change() * self.V
    
    def alpha179(self):
        """
        RANK(CORR(VWAP,VOLUME,4))*RANK(CORR(RANK(LOW),RANK(MEAN(VOLUME,50)),12))
        """
        n_rows = len(self.df)
        self.V = self.V.replace(0, np.nan)
        self.AMOUNT = self.AMOUNT.replace(0, np.nan)
        vwap = (self.AMOUNT / self.V).fillna(method='ffill').fillna(method='bfill')
        self.V = self.V.fillna(method='ffill').fillna(method='bfill')
        
        part1_corr = vwap.rolling(window=4, min_periods=3).corr(self.V).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_corr.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        if n_rows < 50:
            vol_window = max(20, n_rows // 2)
            corr_window = max(5, min(12, n_rows // 4))
        else:
            vol_window = 50
            corr_window = 12
        
        vol_ma = self.V.rolling(window=vol_window, min_periods=max(5, vol_window//5)).mean().fillna(method='ffill').fillna(method='bfill')
        low_rank = self.L.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        vol_ma_rank = vol_ma.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        part2_corr = low_rank.rolling(window=corr_window, min_periods=max(3, corr_window//2)).corr(vol_ma_rank).fillna(method='ffill').fillna(method='bfill')
        part2 = part2_corr.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        alpha = (part1 * part2).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha180(self):
        """
        (MEAN(VOLUME,20)<VOLUME)?((-1*TSRANK(ABS(DELTA(CLOSE,7)),60))*SIGN(DELTA(CLOSE,7)):(-1*VOLUME))
        """
        condition = self.V.rolling(window=20, min_periods=20).mean() < self.V
        alpha = pd.Series(index=self.df.index, dtype=float)
        alpha[condition] = self._tsrank(abs(self.C.diff(7)), 60) * np.sign(self.C.diff(7)) * (-1)
        alpha[~condition] = -1 * self.V
        return alpha
    
    def alpha181(self):
        """
        SUM(RET-MEAN(RET,20)-(BANCHMARK_INDEX_CLOSE-MEAN(BANCHMARK_INDEX_CLOSE,20))^2,20)/SUM((BANCHMARK_INDEX_CLOSE-MEAN(BANCHMARK_INDEX_CLOSE,20))^3)
        """
        n_rows = len(self.df)
        
        if hasattr(self, 'index_df') and self.index_df is not None:
            index_data = self.index_df.copy()
            if 'close' in index_data.columns:
                index_close = index_data['close']
            elif 'closePrice' in index_data.columns:
                index_close = index_data['closePrice']
            else:
                index_close = index_data.iloc[:, 0]
            
            if 'date' in self.df.columns and 'date' in index_data.columns:
                self.df['date'] = pd.to_datetime(self.df['date'])
                index_data['date'] = pd.to_datetime(index_data['date'])
                date_to_index = dict(zip(index_data['date'], index_close))
                bm_close = self.df['date'].map(date_to_index).fillna(method='ffill').fillna(method='bfill')
            else:
                bm_close = index_close.reindex(self.df.index, method='ffill')
        else:
            bm_close = self.C.rolling(window=20, min_periods=10).mean()
        
        bm_mean = bm_close - bm_close.rolling(window=20, min_periods=10).mean().fillna(0)
        ret = self.C.pct_change().fillna(0)
        ret_mean = ret.rolling(window=20, min_periods=10).mean().fillna(0)
        
        part1 = (ret - ret_mean - bm_mean ** 2).rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill')
        part2 = (bm_mean ** 3).rolling(window=20, min_periods=10).sum().fillna(method='ffill').fillna(method='bfill').replace(0, 1e-10)
        
        alpha = (part1 / part2).fillna(method='ffill').fillna(method='bfill').clip(-100, 100)
        return alpha
    
    def alpha182(self):
        """
        COUNT((CLOSE>OPEN & BANCHMARK_INDEX_CLOSE>BANCHMARK_INDEX_OPEN) OR (CLOSE<OPEN &BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN),20)/20
        """
        n_rows = len(self.df)
        
        if hasattr(self, 'index_df') and self.index_df is not None:
            index_data = self.index_df.copy()
            if 'close' in index_data.columns:
                index_close = index_data['close']
            elif 'closePrice' in index_data.columns:
                index_close = index_data['closePrice']
            else:
                index_close = index_data.iloc[:, 0]
            
            if 'open' in index_data.columns:
                index_open = index_data['open']
            elif 'openPrice' in index_data.columns:
                index_open = index_data['openPrice']
            else:
                index_open = index_close.shift(1).fillna(index_close)
            
            if 'date' in self.df.columns and 'date' in index_data.columns:
                self.df['date'] = pd.to_datetime(self.df['date'])
                index_data['date'] = pd.to_datetime(index_data['date'])
                date_to_close = dict(zip(index_data['date'], index_close))
                date_to_open = dict(zip(index_data['date'], index_open))
                bm_close = self.df['date'].map(date_to_close).fillna(method='ffill').fillna(method='bfill')
                bm_open = self.df['date'].map(date_to_open).fillna(method='ffill').fillna(method='bfill')
            else:
                bm_close = index_close.reindex(self.df.index, method='ffill')
                bm_open = index_open.reindex(self.df.index, method='ffill')
        else:
            bm_close = self.C.rolling(window=20, min_periods=5).mean()
            bm_open = self.O.rolling(window=20, min_periods=5).mean()
        
        bm_up = bm_close > bm_open
        stock_up = self.C > self.O
        stock_down = self.C < self.O
        
        condition1 = stock_up & bm_up
        condition2 = stock_down & ~bm_up
        condition = condition1 | condition2
        
        min_periods = max(5, min(10, n_rows // 4))
        alpha = condition.rolling(window=20, min_periods=min_periods).mean().fillna(method='ffill').fillna(method='bfill')
        
        return alpha
    
    def alpha183(self):
        """
        MAX(SUMAC(CLOSE-MEAN(CLOSE,24)))-MIN(SUMAC(CLOSE-MEAN(CLOSE,24)))/STD(CLOSE,24)
        """
        part = self.C - self.C.rolling(window=24, min_periods=24).mean()
        part = part.rolling(window=24, min_periods=24).sum()
        
        part1 = part.rolling(window=24, min_periods=24).max()
        part2 = part.rolling(window=24, min_periods=24).min()
        part3 = self.C.rolling(window=24, min_periods=24).std()
        
        return part1 - part2 / part3
    
    def alpha184(self):
        """
        RANK(CORR(DELAY(OPEN-CLOSE,1),CLOSE,200))+RANK(OPEN-CLOSE)
        """
        n_rows = len(self.df)
        if n_rows < 200:
            window = max(20, int(n_rows * 0.6))
        else:
            window = 200
        
        oc = self.O - self.C
        min_periods = max(10, min(50, window // 4))
        part1_corr = oc.shift(1).rolling(window=window, min_periods=min_periods).corr(self.C).fillna(method='ffill').fillna(method='bfill')
        part1 = part1_corr.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        part2 = oc.rank(pct=True, method='min').fillna(method='ffill').fillna(method='bfill')
        
        alpha = ((part1 + part2) / 2.0).fillna(method='ffill').fillna(method='bfill')
        return alpha
    
    def alpha185(self):
        """
        RANK(-1*(1-OPEN/CLOSE)^2)
        """
        return -1 * (1.0 - self.O / self.C) ** 2
    
    def alpha186(self):
        """
        ADXR指标
        """
        hd = self.H.diff()
        ld = -self.L.diff()
        tr = np.maximum(
            np.maximum(self.H - self.L, abs(self.H - self.C.shift(1))),
            abs(self.L - self.C.shift(1))
        )
        
        plus_dm = ((hd > 0) & (hd > ld)) * hd
        minus_dm = ((ld > 0) & (ld > hd)) * ld
        
        plus_di = plus_dm.rolling(window=14, min_periods=14).sum() * 100 / tr.rolling(window=14, min_periods=14).sum()
        minus_di = minus_dm.rolling(window=14, min_periods=14).sum() * 100 / tr.rolling(window=14, min_periods=14).sum()
        
        dx = abs(plus_di - minus_di) / (plus_di + minus_di) * 100
        adx = dx.rolling(window=6, min_periods=6).mean()
        adxr = (adx + adx.shift(6)) / 2
        
        return adxr
    
    def alpha187(self):
        """
        SUM(OPEN<=DELAY(OPEN,1)?0:MAX(HIGH-OPEN,OPEN-DELAY(OPEN,1)),20)
        """
        part1 = np.maximum(self.H - self.O, self.O.diff())
        part1[self.O.diff() <= 0] = 0.0
        return part1.rolling(window=20, min_periods=20).sum()
    
    def alpha188(self):
        """
        ((HIGH-LOW-SMA(HIGH-LOW,11,2))/SMA(HIGH-LOW,11,2))*100
        """
        hl = self.H - self.L
        sma = self._sma(hl, 11, 2)
        return (hl - sma) / sma * 100
    
    def alpha189(self):
        """
        MEAN(ABS(CLOSE-MEAN(CLOSE,6)),6)
        """
        ma = self.C.rolling(window=6, min_periods=6).mean()
        return abs(self.C - ma).rolling(window=6, min_periods=6).mean()
    
    def alpha190(self):
        """
        LOG((COUNT(RET>((CLOSE/DELAY(CLOSE,19))^(1/20)-1),20)-1)
        *SUMIF((RET-(CLOSE/DELAY(CLOSE,19))^(1/20)-1)^2,20,RET<(CLOSE/DELAY(CLOSE,19))^(1/20)-1)
        /(COUNT(RET<(CLOSE/DELAY(CLOSE,19))^(1/20)-1,20)
        *SUMIF((RET-((CLOSE/DELAY(CLOSE,19))^(1/20)-1))^2,20,RET>(CLOSE/DELAY(CLOSE,19))^(1/20)-1)))
        """
        ret = self.C.pct_change()
        ret_19 = (self.C / self.C.shift(19)) ** 0.05 - 1.0
        
        part1 = (ret > ret_19).rolling(window=20, min_periods=20).sum() - 1.0
        part2 = (np.minimum(ret - ret_19, 0.0) ** 2).rolling(window=20, min_periods=20).sum()
        part3 = (ret < ret_19).rolling(window=20, min_periods=20).sum()
        part4 = (np.maximum(ret - ret_19, 0.0) ** 2).rolling(window=20, min_periods=20).sum()
        
        return np.log(part1 * part2 / part3 / part4)
    
    def alpha191(self):
        """
        CORR(MEAN(VOLUME,20),LOW,5)+(HIGH+LOW)/2-CLOSE
        """
        part1 = self.V.rolling(window=20, min_periods=20).mean().rolling(window=5, min_periods=5).corr(self.L)
        return part1 + (self.H + self.L) / 2 - self.C


if __name__ == '__main__':
    api = xg_factor()
    result = api.CROSS_DOWN()
    # print(result)

源码模块:xg_factor_trader.py

小果量化因子批量调度引擎

import pandas as pd
import numpy as np
import os
from datetime import datetime
import json
import warnings
from concurrent.futures import ProcessPoolExecutor, as_completed, ThreadPoolExecutor
from tqdm import tqdm
import multiprocessing
import gc
import shutil
import pickle
from functools import lru_cache
import re

warnings.filterwarnings("ignore")


# ========== 模块级函数(用于多进程) ==========
def _call_factor_function_worker(models, func_str):
    """因子函数调用工作函数(修复版 - 正确解析参数)"""
    if not func_str:
        return None
    
    # 提取函数名
    func_name = func_str.split('(')[0].strip() if '(' in func_str else func_str.strip()
    
    if not hasattr(models, func_name):
        return None
    
    method = getattr(models, func_name)
    if not callable(method):
        return None
    
    # 如果没有参数,直接调用
    if '(' not in func_str or func_str.endswith('()'):
        try:
            return method()
        except Exception as e:
            return None
    
    # 解析参数
    try:
        start = func_str.index('(') + 1
        end = func_str.rindex(')')
        params_str = func_str[start:end].strip()
        
        if not params_str:
            return method()
        
        # 解析参数 - 处理带括号的复杂参数
        args = {}
        # 按逗号分割,但跳过括号内的逗号
        params = re.split(r',(?![^()]*\))', params_str)
        
        for param in params:
            param = param.strip()
            if not param:
                continue
                
            if '=' in param:
                key, value = param.split('=', 1)
                key = key.strip()
                value = value.strip()
                
                # 尝试转换为数值
                try:
                    if value.lower() == 'true':
                        args[key] = True
                    elif value.lower() == 'false':
                        args[key] = False
                    elif value.lower() == 'none':
                        args[key] = None
                    elif '.' in value:
                        args[key] = float(value)
                    else:
                        args[key] = int(value)
                except:
                    # 尝试去除引号
                    if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")):
                        args[key] = value[1:-1]
                    else:
                        args[key] = value
            else:
                # 位置参数 - 尝试转换为数值
                try:
                    if '.' in param:
                        args['arg'] = float(param)
                    else:
                        args['arg'] = int(param)
                except:
                    args['arg'] = param
        
        # 调用方法
        try:
            return method(**args)
        except TypeError as e:
            # 如果参数不匹配,尝试不带参数调用
            try:
                return method()
            except:
                return None
    except Exception as e:
        return None


def calculate_single_stock_worker_optimized(stock_code, path, index_stock, start_date, end_date, text, adj_type='none'):
    """多进程工作函数:计算单只股票的所有因子(优化版 - 修复数据对齐)"""
    try:
        from xg_factor import xg_factor
        
        file_path = r'{}/data/历史数据/{}.parquet'.format(path, stock_code)
        if not os.path.exists(file_path):
            return (stock_code, False, "数据文件不存在")
        
        # 只读取需要的列,减少内存
        use_cols = ['date','证券代码','证券名称' ,'open', 'high', 'low', 'close', 'volume', 'amount']
        if adj_type != 'none':
            use_cols.append('preClose')
        
        df = pd.read_parquet(file_path, columns=use_cols, engine='pyarrow', use_threads=True)
        df['date'] = pd.to_datetime(df['date'].astype(str), format='%Y%m%d')
        
        # 使用query过滤,速度更快
        start_dt = pd.to_datetime(start_date)
        end_dt = pd.to_datetime(end_date)
        df = df[(df['date'] >= start_dt) & (df['date'] <= end_dt)]
        df = df.sort_values('date').reset_index(drop=True)
        
        # 过滤无效数据
        df = df[(df['close'] > 0) & (df['open'] > 0)]
        
        if df.empty:
            return (stock_code, False, "无有效数据")
        
        # 获取指数数据
        index_file = r'{}/data/指数数据/{}.parquet'.format(path, index_stock)
        index_df = pd.DataFrame()
        if os.path.exists(index_file):
            try:
                index_df = pd.read_parquet(index_file, columns=['date', 'open', 'close'], 
                                          engine='pyarrow', use_threads=True)
                index_df['date'] = pd.to_datetime(index_df['date'].astype(str), format='%Y%m%d')
                index_df = index_df[(index_df['date'] >= start_dt) & (index_df['date'] <= end_dt)]
                index_df = index_df.sort_values('date').reset_index(drop=True)
            except:
                index_df = pd.DataFrame()
        
        # 创建因子计算实例
        models = xg_factor(df=df, index_df=index_df)
        
        # 预分配结果列
        for name in text.keys():
            df[name] = np.nan
        
        # 批量计算因子
        for name, func_str in text.items():
            try:
                result = _call_factor_function_worker(models, func_str)
                
                if result is None:
                    continue
                elif isinstance(result, pd.Series):
                    # 对齐长度 - 确保与df长度一致
                    if len(result) == len(df):
                        df[name] = result.values
                    elif len(result) < len(df):
                        # 前面填充NaN
                        temp = pd.Series([np.nan] * (len(df) - len(result)) + list(result))
                        df[name] = temp.values
                    else:
                        # 截取前len(df)个
                        df[name] = result.iloc[:len(df)].values
                elif isinstance(result, (int, float, np.number)):
                    # 标量值,整列赋值
                    df[name] = result
                elif isinstance(result, (list, tuple, np.ndarray)):
                    if len(result) == len(df):
                        df[name] = result
                    elif len(result) < len(df):
                        temp = [np.nan] * (len(df) - len(result)) + list(result)
                        df[name] = temp
                    else:
                        df[name] = result[:len(df)]
                else:
                    try:
                        if hasattr(result, '__len__') and len(result) == len(df):
                            df[name] = result
                    except:
                        pass
            except Exception as e:
                continue
        
        if df.shape[0] > 0:
            save_path = r'{}/data/全部因子数据/{}.parquet'.format(path, stock_code)
            os.makedirs(os.path.dirname(save_path), exist_ok=True)
            df.to_parquet(save_path, compression='zstd')
            return (stock_code, True, "成功")
        else:
            return (stock_code, False, "数据为空")
            
    except Exception as e:
        return (stock_code, False, str(e))


class xg_factor_trader:
    def __init__(self,
            index_stock='000300.SH',
            start_date='20200101',
            end_date='20500101',
            max_workers=None,
            verbose=False,
            use_multiprocess=True,
            chunk_size=30,
            stage_size=200,
            use_async_io=True,
            force_recalc=False):
        """
        初始化因子计算器(超级优化版)
        
        Args:
            index_stock: 指数代码
            start_date: 开始日期
            end_date: 结束日期
            max_workers: 最大进程数
            verbose: 是否显示详细信息
            use_multiprocess: 是否使用多进程
            chunk_size: 批次处理大小
            stage_size: 阶段大小
            use_async_io: 是否使用异步IO
            force_recalc: 是否强制重新计算所有股票(True=覆盖计算全部,False=跳过已计算的)
        """
        self.path = os.path.dirname(os.path.abspath(__file__))
        self.index_stock = index_stock
        self.start_date = start_date
        self.end_date = end_date
        self.chunk_size = chunk_size
        self.stage_size = stage_size
        self.use_async_io = use_async_io
        self.force_recalc = force_recalc
        
        if max_workers is None:
            self.max_workers = max(1, multiprocessing.cpu_count() - 1)
        else:
            self.max_workers = max_workers
        
        self.verbose = verbose
        self.use_multiprocess = use_multiprocess
        
        # 缓存指数数据
        self.index_df = self.get_index_data()
        self.adj_type = 'none'
        
        # 加载因子表
        try:
            with open(r'因子表.json', 'r+', encoding='utf-8') as f:
                com = f.read()
            self.text = json.loads(com)
        except:
            self.text = {}
            print("警告: 因子表.json 不存在,请先创建")
        
        # 统计
        self.success_count = 0
        self.fail_count = 0
        self.fail_list = []
        self.stage_results = []
        
        # 创建目录
        os.makedirs(r'{}/data/全部因子数据'.format(self.path), exist_ok=True)
        
        self.stock_list = None
        self._processed_cache = set()  # 缓存已处理的股票
        
        # 如果强制重算,清空已计算的缓存
        if self.force_recalc:
            print("⚠️  强制重算模式已开启,将重新计算所有股票并覆盖已有数据")
            # 清理已处理缓存,但保留目录
            self._processed_cache = set()

    def get_all_factor_table(self):
        """生成因子列表"""
        data = pd.DataFrame()
        text_copy = self.text.copy()
        text_copy['close'] = '默认'
        text_copy['high'] = '默认'
        text_copy['low'] = '默认'
        text_copy['open'] = '默认'
        text_copy['amount'] = '默认'
        text_copy['volume'] = '默认'
        text_copy['zdf'] = '默认'

        for name, func in text_copy.items():
            data = pd.concat([data, pd.DataFrame({'因子名称': [name], '因子函数': [func]})], ignore_index=True)
        
        os.makedirs(r'{}/data/全部因子'.format(self.path), exist_ok=True)
        data.to_excel(r'{}/data/全部因子/全部因子.xlsx'.format(self.path))
        data.to_json(r'{}/data/全部因子/全部因子.json'.format(self.path), orient='records', force_ascii=False)
        print(f"因子列表已生成,共 {len(data)} 个因子")

    @lru_cache(maxsize=128)
    def _get_stock_data_cached(self, stock_code):
        """缓存股票数据"""
        return self.get_stock_data(stock_code)

    def get_stock_data(self, stock_code):
        """获取单只股票数据(优化版)"""
        try:
            file_path = r'{}/data/历史数据/{}.parquet'.format(self.path, stock_code)
            if not os.path.exists(file_path):
                return pd.DataFrame()
            
            # 只读需要的列
            use_cols = ['date','证券代码','证券名称', 'open', 'high', 'low', 'close', 'volume', 'amount']
            if self.adj_type != 'none':
                use_cols.append('preClose')
            
            df = pd.read_parquet(file_path, columns=use_cols, engine='pyarrow', use_threads=True)
            df['date'] = pd.to_datetime(df['date'].astype(str), format='%Y%m%d')
            
            start_dt = pd.to_datetime(self.start_date)
            end_dt = pd.to_datetime(self.end_date)
            df = df[(df['date'] >= start_dt) & (df['date'] <= end_dt)]
            df = df.sort_values('date').reset_index(drop=True)
            df = df[(df['close'] > 0) & (df['open'] > 0)]
            
            if df.empty:
                return df
            
            df = self.adjust_price(df)
            df['zdf'] = df['close'].pct_change() * 100
            return df
        except Exception as e:
            return pd.DataFrame()
    
    def adjust_price(self, df):
        """价格复权(优化版)"""
        if self.adj_type == 'none' or 'preClose' not in df.columns:
            return df
        
        try:
            # 使用向量化操作
            df['adj_factor'] = 1.0
            pre_close = df['preClose'].values
            close = df['close'].values
            
            # 批量计算复权因子
            for i in range(1, len(df)):
                if pre_close[i] > 0:
                    df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor'] * (close[i] / pre_close[i])
                else:
                    df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor']
            
            if self.adj_type in ['front', 'front_ratio']:
                df['adj_factor'] = df['adj_factor'] / df['adj_factor'].iloc[-1]
            
            price_cols = ['open', 'high', 'low', 'close']
            for col in price_cols:
                if col in df.columns:
                    df[col] = df[col] * df['adj_factor']
            df = df.drop(columns=['adj_factor'])
        except Exception as e:
            pass
        return df
    
    def get_index_data(self):
        """获取指数数据"""
        try:
            file_path = r'{}/data/指数数据/{}.parquet'.format(self.path, self.index_stock)
            if not os.path.exists(file_path):
                return pd.DataFrame()
            df = pd.read_parquet(file_path, columns=['date', 'open', 'close'], 
                                engine='pyarrow', use_threads=True)
            df['date'] = pd.to_datetime(df['date'].astype(str), format='%Y%m%d')
            
            start_dt = pd.to_datetime(self.start_date)
            end_dt = pd.to_datetime(self.end_date)
            df = df[(df['date'] >= start_dt) & (df['date'] <= end_dt)]
            df = df.sort_values('date').reset_index(drop=True)
            df = df[(df['close'] > 0) & (df['open'] > 0)]
            return df
        except Exception as e:
            return pd.DataFrame()
    
    def _call_factor_function(self, models, func_str):
        """调用因子函数(单线程版本 - 修复参数解析)"""
        if not func_str:
            return None
        
        func_name = func_str.split('(')[0].strip() if '(' in func_str else func_str.strip()
        
        if not hasattr(models, func_name):
            return None
        
        method = getattr(models, func_name)
        if not callable(method):
            return None
        
        if '(' not in func_str or func_str.endswith('()'):
            try:
                return method()
            except:
                return None
        
        try:
            start = func_str.index('(') + 1
            end = func_str.rindex(')')
            params_str = func_str[start:end].strip()
            
            if not params_str:
                return method()
            
            # 解析参数 - 处理带括号的复杂参数
            args = {}
            params = re.split(r',(?![^()]*\))', params_str)
            
            for param in params:
                param = param.strip()
                if not param:
                    continue
                    
                if '=' in param:
                    key, value = param.split('=', 1)
                    key = key.strip()
                    value = value.strip()
                    
                    try:
                        if value.lower() == 'true':
                            args[key] = True
                        elif value.lower() == 'false':
                            args[key] = False
                        elif value.lower() == 'none':
                            args[key] = None
                        elif '.' in value:
                            args[key] = float(value)
                        else:
                            args[key] = int(value)
                    except:
                        if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")):
                            args[key] = value[1:-1]
                        else:
                            args[key] = value
                else:
                    try:
                        if '.' in param:
                            args['arg'] = float(param)
                        else:
                            args['arg'] = int(param)
                    except:
                        args['arg'] = param
            
            try:
                return method(**args)
            except TypeError as e:
                try:
                    return method()
                except:
                    return None
        except:
            return None
    
    def cacal_stock_factor(self, stock='513100.SH'):
        """单只股票因子计算(修复版)"""
        try:
            from xg_factor import xg_factor
            df = self.get_stock_data(stock_code=stock)
            if df.empty:
                print(f"股票 {stock} 无数据")
                return False
            
            print(f"股票 {stock} 数据加载成功: {len(df)} 行")
            print(f"因子数量: {len(self.text)} 个")
            
            models = xg_factor(df=df, index_df=self.index_df)
            factor_items = list(self.text.items())
            
            for name, func_str in tqdm(factor_items, desc=f"计算 {stock}", unit="个", leave=False, disable=not self.verbose):
                try:
                    result = self._call_factor_function(models, func_str)
                    if result is None:
                        df[name] = np.nan
                        continue
                    
                    # 处理不同类型的返回值
                    if isinstance(result, pd.Series):
                        # 对齐长度
                        if len(result) < df.shape[0]:
                            # 结果长度小于df,在前面填充NaN
                            result = pd.concat([pd.Series([np.nan] * (df.shape[0] - len(result))), result], ignore_index=True)
                        elif len(result) > df.shape[0]:
                            # 结果长度大于df,截取前df.shape[0]个
                            result = result.iloc[:df.shape[0]]
                        df[name] = result.values
                        
                    elif isinstance(result, (list, tuple, np.ndarray)):
                        # 列表、元组、数组
                        if len(result) < df.shape[0]:
                            # 前面填充NaN
                            result = [np.nan] * (df.shape[0] - len(result)) + list(result)
                        elif len(result) > df.shape[0]:
                            # 截取前df.shape[0]个
                            result = result[:df.shape[0]]
                        df[name] = result
                        
                    elif isinstance(result, (int, float, np.number)):
                        # 标量值,直接赋值(整列都是同一个值)
                        df[name] = result
                        
                    else:
                        # 其他类型尝试转换
                        try:
                            if hasattr(result, '__len__') and len(result) == df.shape[0]:
                                df[name] = result
                            else:
                                df[name] = np.nan
                        except:
                            df[name] = np.nan
                            
                except Exception as e:
                    df[name] = np.nan
            
            if df.shape[0] > 0:
                save_path = r'{}/data/全部因子数据/{}.parquet'.format(self.path, stock)
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                df.to_parquet(save_path, compression='zstd')
                print(f"股票 {stock} 因子计算完成,共 {df.shape[0]} 行数据")
                return True
            return False
        except Exception as e:
            print(f"股票 {stock} 计算失败: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def _calculate_single_stock_sync(self, stock):
        """同步单线程计算单只股票(修复版)"""
        try:
            from xg_factor import xg_factor
            df = self.get_stock_data(stock_code=stock)
            if df.empty:
                return False
            
            models = xg_factor(df=df, index_df=self.index_df)
            df_len = len(df)
            
            for name, func_str in self.text.items():
                try:
                    result = self._call_factor_function(models, func_str)
                    
                    if result is None:
                        df[name] = np.nan
                    elif isinstance(result, pd.Series):
                        if len(result) == df_len:
                            df[name] = result.values
                        elif len(result) < df_len:
                            temp = pd.Series([np.nan] * (df_len - len(result)) + list(result))
                            df[name] = temp.values
                        else:
                            df[name] = result.iloc[:df_len].values
                    elif isinstance(result, (int, float, np.number)):
                        df[name] = result
                    elif isinstance(result, (list, tuple, np.ndarray)):
                        if len(result) == df_len:
                            df[name] = result
                        elif len(result) < df_len:
                            df[name] = [np.nan] * (df_len - len(result)) + list(result)
                        else:
                            df[name] = result[:df_len]
                    else:
                        try:
                            if hasattr(result, '__len__') and len(result) == df_len:
                                df[name] = result
                            else:
                                df[name] = np.nan
                        except:
                            df[name] = np.nan
                except Exception as e:
                    df[name] = np.nan
            
            if df.shape[0] > 0:
                save_path = r'{}/data/全部因子数据/{}.parquet'.format(self.path, stock)
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                df.to_parquet(save_path, compression='zstd')
                return True
            return False
        except Exception as e:
            if self.verbose:
                print(f"计算 {stock} 时出错: {e}")
            return False
    def get_bond_stock(self):
        '''
        可转债代码
        '''
        df_bond = pd.read_excel(r'{}/data/可转债代码/可转债代码.xlsx'.format(self.path))
        df_bond['代码'] = df_bond['代码'].apply(lambda x: str(x)[2:] + '.' + str(x)[:2])
        df_bond.columns = ['证券代码', '证券名称']
        return df_bond
    def _get_stock_list(self):
        """获取股票列表(带缓存)- 支持强制重算模式"""
        if self.stock_list is not None:
            return self.stock_list
        
        # 如果不强制重算,加载已处理缓存
        if not self.force_recalc:
            try:
                factor_path = r'{}/data/全部因子数据'.format(self.path)
                if os.path.exists(factor_path):
                    processed = [f.replace('.parquet', '') for f in os.listdir(factor_path) 
                                if f.endswith('.parquet') and f != '失败列表.xlsx']
                    self._processed_cache = set(processed)
            except:
                self._processed_cache = set()
        else:
            # 强制重算模式:清空缓存,但保留已计算文件(后续会覆盖)
            self._processed_cache = set()
            print("🔄 强制重算模式:将重新计算所有股票并覆盖已有数据文件")
        
        try:
            # 尝试从Excel读取
            excel_path = r'{}/data/基金代码/基金代码.xlsx'.format(self.path)
            if os.path.exists(excel_path):
                df_fund = pd.read_excel(excel_path)
                df_fund=df_fund[['基金代码','基金名称']]
                df_fund.columns = ['证券代码', '证券名称']
                df_bond=self.get_bond_stock()
                df=pd.concat([df_fund,df_bond],ignore_index=True)
                if '证券代码' in df.columns:
                    self.stock_list = df['证券代码'].tolist()
                    # 如果不强制重算,过滤已处理的股票
                    if not self.force_recalc and self._processed_cache:
                        original_count = len(self.stock_list)
                        self.stock_list = [s for s in self.stock_list if s not in self._processed_cache]
                        skipped_count = original_count - len(self.stock_list)
                        if skipped_count > 0:
                            print(f"⏭️  跳过已计算的股票: {skipped_count} 只")
                    
                    print(f"📊 本次需要计算的股票数: {len(self.stock_list)} 只")
                    return self.stock_list
            
            # 尝试从parquet目录获取
            hist_path = r'{}/data/历史数据'.format(self.path)
            if os.path.exists(hist_path):
                files = [f.replace('.parquet', '') for f in os.listdir(hist_path) if f.endswith('.parquet')]
                if files:
                    self.stock_list = files
                    # 如果不强制重算,过滤已处理的
                    if not self.force_recalc and self._processed_cache:
                        original_count = len(self.stock_list)
                        self.stock_list = [s for s in self.stock_list if s not in self._processed_cache]
                        skipped_count = original_count - len(self.stock_list)
                        if skipped_count > 0:
                            print(f"⏭️  跳过已计算的股票: {skipped_count} 只")
                    
                    print(f"📊 本次需要计算的股票数: {len(self.stock_list)} 只")
                    return self.stock_list
            
            self.stock_list = []
            return self.stock_list
        except Exception as e:
            print(f"获取股票列表失败: {e}")
            self.stock_list = []
            return self.stock_list
    
    def _clear_cache(self):
        """清理缓存释放内存"""
        gc.collect()
    
    def _save_stage_checkpoint(self, stage_num, total_stages):
        """保存阶段检查点"""
        checkpoint_path = r'{}/data/全部因子数据/checkpoint.json'.format(self.path)
        checkpoint_data = {
            'stage': stage_num,
            'total_stages': total_stages,
            'success_count': self.success_count,
            'fail_count': self.fail_count,
            'force_recalc': self.force_recalc,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        try:
            with open(checkpoint_path, 'w', encoding='utf-8') as f:
                json.dump(checkpoint_data, f, ensure_ascii=False, indent=2)
        except:
            pass
    
    def cacal_all_stock_factor_single(self):
        """单线程分阶段计算所有股票因子"""
        stock_list = self._get_stock_list()
        if not stock_list:
            print("没有找到需要计算的股票数据")
            return
        
        total = len(stock_list)
        self.success_count = 0
        self.fail_count = 0
        self.fail_list = []
        self.stage_results = []
        
        total_stages = max(1, (total + self.stage_size - 1) // self.stage_size)
        
        print(f"\n{'='*60}")
        print(f"单线程分阶段计算模式")
        print(f"需要计算股票数: {total}")
        print(f"因子数量: {len(self.text)} 个")
        print(f"阶段大小: {self.stage_size} 只/阶段")
        print(f"总阶段数: {total_stages}")
        if self.force_recalc:
            print("模式: 🔄 强制重算(覆盖已有数据)")
        else:
            print("模式: 📝 增量计算(跳过已计算)")
        print(f"{'='*60}\n")
        
        start_time = datetime.now()
        
        for stage_idx in range(total_stages):
            stage_start = stage_idx * self.stage_size
            stage_end = min(stage_start + self.stage_size, total)
            stage_stocks = stock_list[stage_start:stage_end]
            
            stage_success = 0
            stage_fail = 0
            stage_start_time = datetime.now()
            
            print(f"\n阶段 {stage_idx + 1}/{total_stages} (股票 {stage_start+1}-{stage_end}/{total})")
            
            # 使用线程池进行并行IO
            if self.use_async_io and len(stage_stocks) > 10:
                with ThreadPoolExecutor(max_workers=min(8, len(stage_stocks))) as io_executor:
                    # 预加载数据
                    futures = {io_executor.submit(self.get_stock_data, stock): stock for stock in stage_stocks}
                    for future in as_completed(futures):
                        stock = futures[future]
                        try:
                            df = future.result()
                            if not df.empty:
                                self.success_count += 1
                                stage_success += 1
                                # 保存数据
                                save_path = r'{}/data/全部因子数据/{}.parquet'.format(self.path, stock)
                                df.to_parquet(save_path, compression='zstd')
                            else:
                                self.fail_count += 1
                                stage_fail += 1
                                self.fail_list.append(stock)
                        except:
                            self.fail_count += 1
                            stage_fail += 1
                            self.fail_list.append(stock)
            else:
                # 传统顺序处理
                for idx, stock in enumerate(tqdm(stage_stocks, desc=f"阶段{stage_idx+1}进度", unit="只")):
                    try:
                        success = self._calculate_single_stock_sync(stock)
                        if success:
                            self.success_count += 1
                            stage_success += 1
                        else:
                            self.fail_count += 1
                            stage_fail += 1
                            self.fail_list.append(stock)
                    except Exception as e:
                        self.fail_count += 1
                        stage_fail += 1
                        self.fail_list.append(stock)
            
            stage_elapsed = (datetime.now() - stage_start_time).total_seconds()
            self.stage_results.append({
                'stage': stage_idx + 1,
                'stocks': len(stage_stocks),
                'success': stage_success,
                'fail': stage_fail,
                'time': stage_elapsed
            })
            
            self._clear_cache()
            self._save_stage_checkpoint(stage_idx + 1, total_stages)
            
            total_elapsed = (datetime.now() - start_time).total_seconds()
            print(f"\n阶段 {stage_idx+1} 完成! 成功:{stage_success} 失败:{stage_fail} 耗时:{stage_elapsed:.1f}s")
            
            if stage_idx + 1 < total_stages:
                avg_time = total_elapsed / (stage_idx + 1)
                remaining = avg_time * (total_stages - stage_idx - 1)
                print(f"  预计剩余: {remaining:.1f}s ({remaining/60:.1f}分钟)")
        
        elapsed = (datetime.now() - start_time).total_seconds()
        self._print_summary(total, elapsed)
    
    def cacal_all_stock_factor_multiprocess(self):
        """多进程分阶段计算所有股票因子(优化版)"""
        stock_list = self._get_stock_list()
        if not stock_list:
            print("没有找到需要计算的股票数据")
            return
        
        total = len(stock_list)
        self.success_count = 0
        self.fail_count = 0
        self.fail_list = []
        self.stage_results = []
        
        total_stages = max(1, (total + self.stage_size - 1) // self.stage_size)
        
        print(f"\n{'='*60}")
        print(f"多进程分阶段计算模式(优化版)")
        print(f"需要计算股票数: {total}")
        print(f"因子数量: {len(self.text)} 个")
        print(f"进程数: {self.max_workers}")
        print(f"批次大小: {self.chunk_size}")
        print(f"阶段大小: {self.stage_size} 只/阶段")
        print(f"总阶段数: {total_stages}")
        if self.force_recalc:
            print("模式: 🔄 强制重算(覆盖已有数据)")
        else:
            print("模式: 📝 增量计算(跳过已计算)")
        print(f"{'='*60}\n")
        
        start_time = datetime.now()
        
        for stage_idx in range(total_stages):
            stage_start = stage_idx * self.stage_size
            stage_end = min(stage_start + self.stage_size, total)
            stage_stocks = stock_list[stage_start:stage_end]
            
            stage_success = 0
            stage_fail = 0
            stage_start_time = datetime.now()
            
            print(f"\n阶段 {stage_idx + 1}/{total_stages} (股票 {stage_start+1}-{stage_end}/{total})")
            
            # 批量提交任务
            with ProcessPoolExecutor(max_workers=self.max_workers) as executor:
                futures = {}
                for stock in stage_stocks:
                    future = executor.submit(
                        calculate_single_stock_worker_optimized,
                        stock,
                        self.path,
                        self.index_stock,
                        self.start_date,
                        self.end_date,
                        self.text,
                        self.adj_type
                    )
                    futures[future] = stock
                
                with tqdm(total=len(futures), desc=f"阶段{stage_idx+1}进度", unit="只") as pbar:
                    for future in as_completed(futures):
                        try:
                            stock, success, msg = future.result(timeout=600)
                            if success:
                                self.success_count += 1
                                stage_success += 1
                            else:
                                self.fail_count += 1
                                stage_fail += 1
                                self.fail_list.append(stock)
                            pbar.set_postfix_str(f"成功:{self.success_count} 失败:{self.fail_count}")
                        except Exception as e:
                            self.fail_count += 1
                            stage_fail += 1
                            stock = futures[future]
                            self.fail_list.append(stock)
                            if self.verbose:
                                print(f"股票 {stock} 计算异常: {e}")
                        pbar.update(1)
            
            stage_elapsed = (datetime.now() - stage_start_time).total_seconds()
            self.stage_results.append({
                'stage': stage_idx + 1,
                'stocks': len(stage_stocks),
                'success': stage_success,
                'fail': stage_fail,
                'time': stage_elapsed
            })
            
            self._clear_cache()
            self._save_stage_checkpoint(stage_idx + 1, total_stages)
            
            total_elapsed = (datetime.now() - start_time).total_seconds()
            print(f"\n阶段 {stage_idx+1} 完成!")
            
            if stage_idx + 1 < total_stages:
                avg_time = total_elapsed / (stage_idx + 1)
                remaining = avg_time * (total_stages - stage_idx - 1)
                print(f"  预计剩余: {remaining:.1f}s ({remaining/60:.1f}分钟)")
        
        elapsed = (datetime.now() - start_time).total_seconds()
        self._print_summary(total, elapsed)
    
    def _print_summary(self, total, elapsed):
        """打印计算摘要"""
        print(f"\n{'='*60}")
        print(f"计算完成!")
        print(f"{'='*60}")
        print(f"总股票数: {total}")
        print(f"成功: {self.success_count} 只")
        print(f"失败: {self.fail_count} 只")
        if self.fail_list:
            print(f"失败列表: {self.fail_list[:10]}{'...' if len(self.fail_list) > 10 else ''}")
        print(f"总耗时: {elapsed:.1f} 秒 ({elapsed/60:.1f} 分钟)")
        if total > 0:
            print(f"平均每只: {elapsed/total:.2f} 秒")
        print(f"{'='*60}")
        
        if self.stage_results:
            print(f"\n阶段统计:")
            print(f"{'阶段':<8} {'股票数':<8} {'成功':<8} {'失败':<8} {'耗时(s)':<10}")
            print("-" * 50)
            for r in self.stage_results:
                print(f"{r['stage']:<8} {r['stocks']:<8} {r['success']:<8} {r['fail']:<8} {r['time']:<10.1f}")
        
        if self.fail_list:
            fail_df = pd.DataFrame({'失败股票': self.fail_list})
            fail_path = r'{}/data/全部因子数据/失败列表.xlsx'.format(self.path)
            fail_df.to_excel(fail_path, index=False)
            print(f"\n失败列表已保存至: {fail_path}")
    
    def cacal_all_stock_factor(self):
        """计算所有股票因子"""
        if not self.text:
            print("因子表为空,请检查因子表.json")
            return
        
        if self.use_multiprocess and self.max_workers > 1:
            self.cacal_all_stock_factor_multiprocess()
        else:
            self.cacal_all_stock_factor_single()
    
    def get_factor_data(self, stock='513100.SH'):
        """获取已计算的因子数据"""
        try:
            file_path = r'{}/data/全部因子数据/{}.parquet'.format(self.path, stock)
            if not os.path.exists(file_path):
                return pd.DataFrame()
            return pd.read_parquet(file_path, engine='pyarrow', use_threads=True)
        except:
            return pd.DataFrame()
    
    def get_all_factor_data(self):
        """获取所有已计算的因子数据"""
        data_path = r'{}/data/全部因子数据'.format(self.path)
        if not os.path.exists(data_path):
            return pd.DataFrame()
        
        all_data = []
        for file in os.listdir(data_path):
            if file.endswith('.parquet') and file != '失败列表.xlsx':
                try:
                    stock = file.replace('.parquet', '')
                    df = self.get_factor_data(stock)
                    if not df.empty:
                        df['stock'] = stock
                        all_data.append(df)
                except:
                    continue
        
        if all_data:
            return pd.concat(all_data, ignore_index=True)
        return pd.DataFrame()
    
    def run_all_func(self):
        """运行完整流程"""
        print("="*60)
        print("小果因子计算系统 (超级优化版)")
        print("="*60)
        
        print("\n[1/2] 生成因子列表...")
        self.get_all_factor_table()
        
        print("\n[2/2] 计算所有股票因子...")
        self.cacal_all_stock_factor()
        
        print("\n全部完成!")
        #下载一个因子的例子
        df=self.get_factor_data('513100.SH')[-10:]
        df['date']=pd.to_datetime(df['date'])
        df['date']=df['date'].apply(lambda x:str(x)[:10])
        df.to_json(r'{}/data/因子例子参考/因子例子参考.json'.format(self.path),orient='records',force_ascii=False)
        df.to_excel(r'{}/data/因子例子参考/因子例子参考.xlsx'.format(self.path))

if __name__ == '__main__':
    # ========== 强制重新计算所有股票(覆盖最新) ==========
    api = xg_factor_trader(
        max_workers=4,          # 进程数
        verbose=False,          # 是否显示详细信息
        use_multiprocess=True,  # 多进程模式
        chunk_size=100,         # 每批处理100只
        stage_size=100,         # 每阶段处理100只后清理缓存
        use_async_io=True,      # 使用异步IO
        start_date='20240101',
        force_recalc=True       # 🔥 强制重算模式:覆盖计算全部股票
    )
    api.run_all_func()
   
    df=api.get_factor_data('513100.SH')[-10:]
    df['date']=pd.to_datetime(df['date'])
    df['date']=df['date'].apply(lambda x:str(x)[:10])
    df.to_json(r'data/因子例子参考/因子例子参考.json',orient='records',force_ascii=False)
    df.to_excel(r'data/因子例子参考/因子例子参考.xlsx')
    


    
    
    

源码模块:xg_tdx_func.py

通达信底层指标函数库

'''
小果
微信:xg_quant
'''
import pandas as pd
import numpy as np
#------------------ 0级:核心工具函数 -------------------------------------------
import numpy as np
import pandas as pd

def RD(N, D=3):
    """四舍五入取3位小数"""
    return np.round(N, D)

def RET(S, N=1):
    """返回序列倒数第N个值,默认返回最后一个"""
    return np.array(S)[-N]

def ABS(S):
    """返回N的绝对值"""
    return np.abs(S)

def MAX(S1, S2):
    """序列max"""
    return np.maximum(S1, S2)

def MIN(S1, S2):
    """序列min"""
    return np.minimum(S1, S2)

def IF(S, A, B):
    """序列布尔判断 return=A if S==True else B"""
    return np.where(S, A, B)

def REF(S, N=1):
    """对序列整体下移动N,返回序列(shift后会产生NAN)"""
    return pd.Series(S).shift(N).values

def DIFF(S, N=1):
    """前一个值减后一个值,前面会产生nan;np.diff(S)直接删除nan,会少一行"""
    return pd.Series(S).diff(N).values

def STD(S, N):
    """求序列的N日标准差,返回序列"""
    return pd.Series(S).rolling(N).std(ddof=0).values

def SUM(S, N):
    """对序列求N天累计和,返回序列;N=0对序列所有依次求和"""
    return pd.Series(S).rolling(N).sum().values if N > 0 else pd.Series(S).cumsum().values

def CONST(S):
    """返回序列S最后的值组成常量序列"""
    return np.full(len(S), S[-1])

def AND(S1, S2):
    """逻辑与运算"""
    return np.logical_and(S1, S2)

def OR(S1, S2):
    """逻辑或运算"""
    return np.logical_or(S1, S2)

def NOT(S1):
    """逻辑非运算"""
    return np.logical_not(S1)

def RANGE(A, B, C):
    """期间函数:B <= A <= C"""
    df = pd.DataFrame()
    df['select'] = A.tolist()
    df['select'] = df['select'].apply(lambda x: True if (x >= B and x <= C) else False)
    return df['select']

def HHV(S, N):
    """HHV(C, 5) 最近5天收盘最高价"""
    return pd.Series(S).rolling(N).max().values

def LLV(S, N):
    """LLV(C, 5) 最近5天收盘最低价"""
    return pd.Series(S).rolling(N).min().values

def HHVBARS(S, N):
    """求N周期内S最高值到当前周期数,返回序列"""
    return pd.Series(S).rolling(N).apply(lambda x: np.argmax(x[::-1]), raw=True).values

def LLVBARS(S, N):
    """求N周期内S最低值到当前周期数,返回序列"""
    return pd.Series(S).rolling(N).apply(lambda x: np.argmin(x[::-1]), raw=True).values

def MA(S, N):
    """求序列的N日简单移动平均值,返回序列"""
    return pd.Series(S).rolling(N).mean().values

def EMA(S, N):
    """指数移动平均,为了精度 S>4*N,EMA至少需要120周期;alpha=2/(span+1)"""
    return pd.Series(S).ewm(span=N, adjust=False).mean().values

def SMA(S, N, M=1):
    """中国式的SMA,至少需要120周期才精确(雪球180周期);alpha=1/(1+com)"""
    return pd.Series(S).ewm(alpha=M/N, adjust=False).mean().values  # com=N-M/M

def DMA(S, A):
    """求S的动态移动平均,A作平滑因子,必须 0<A<1 (此为核心函数,非指标)"""
    return pd.Series(S).ewm(alpha=A, adjust=True).mean().values

def WMA(S, N):
    """通达信S序列的N日加权移动平均 Yn = (1*X1+2*X2+3*X3+...+n*Xn)/(1+2+3+...+Xn)"""
    return pd.Series(S).rolling(N).apply(lambda x: x[::-1].cumsum().sum() * 2 / N / (N + 1), raw=True).values

def AVEDEV(S, N):
    """平均绝对偏差 (序列与其平均值的绝对差的平均值)"""
    return pd.Series(S).rolling(N).apply(lambda x: (np.abs(x - x.mean())).mean()).values

def SLOPE(S, N):
    """返回S序列N周期回线性回归斜率"""
    return pd.Series(S).rolling(N).apply(lambda x: np.polyfit(range(N), x, deg=1)[0], raw=True).values

def FORCAST(S, N):
    """返回S序列N周期回线性回归后的预测值"""
    return pd.Series(S).rolling(N).apply(lambda x: np.polyval(np.polyfit(range(N), x, deg=1), N-1), raw=True).values

def LAST(S, A, B):
    """从前A日到前B日一直满足S_BOOL条件,要求A>B & A>0 & B>=0"""
    return np.array(pd.Series(S).rolling(A+1).apply(lambda x: np.all(x[::-1][B:]), raw=True), dtype=bool)


#------------------ 1级:应用层函数(通过0级核心函数实现)--------------------------
def COUNT(S, N):
    """COUNT(CLOSE>O, N): 最近N天满足S_BOO的天数,True的天数"""
    return SUM(S, N)

def EVERY(S, N):
    """EVERY(CLOSE>O, 5) 最近N天是否都是True"""
    return IF(SUM(S, N) == N, True, False)

def EXIST(S, N):
    """EXIST(CLOSE>3010, N=5) n日内是否存在一天大于3000点"""
    return IF(SUM(S, N) > 0, True, False)

def FILTER(S, N):
    """
    FILTER函数,S满足条件后,将其后N周期内的数据置为0
    例:FILTER(C==H,5) 涨停后,后5天不再发出信号
    """
    for i in range(len(S)):
        if S[i]:
            S[i+1:i+1+N] = 0
    return S

def BARSLAST(S):
    """上一次条件成立到当前的周期,BARSLAST(C/REF(C,1)>=1.1) 上一次涨停到今天的天数"""
    M = np.concatenate(([0], np.where(S, 1, 0)))
    for i in range(1, len(M)):
        M[i] = 0 if M[i] else M[i-1] + 1
    return M[1:]

def BARSLASTCOUNT(S):
    """统计连续满足S条件的周期数;BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数"""
    rt = np.zeros(len(S) + 1)
    for i in range(len(S)):
        rt[i+1] = rt[i] + 1 if S[i] else rt[i+1]
    return rt[1:]

def BARSSINCEN(S, N):
    """N周期内第一次S条件成立到现在的周期数,N为常量"""
    return pd.Series(S).rolling(N).apply(
        lambda x: N-1-np.argmax(x) if np.argmax(x) or x[0] else 0,
        raw=True
    ).fillna(0).values.astype(int)

def CROSS(S1, S2):
    """判断向上金叉穿越 CROSS(MA(C,5), MA(C,10));判断向下死叉穿越 CROSS(MA(C,10), MA(C,5))"""
    return np.concatenate(([False], np.logical_not((S1 > S2)[:-1]) & (S1 > S2)[1:]))

def CROSS_UP(S1, S2):
    """判断向上金叉穿越 CROSS(MA(C,5), MA(C,10))"""
    return np.concatenate(([False], np.logical_not((S1 > S2)[:-1]) & (S1 > S2)[1:]))

def CROSS_DOWN(S1, S2):
    """判断向下死叉穿越 CROSS(MA(C,5), MA(C,10))"""
    return np.concatenate(([False], np.logical_not((S1 < S2)[:-1]) & (S1 < S2)[1:]))

def LONGCROSS(S1, S2, N):
    """两条线维持一定周期后交叉,S1在N周期内都小于S2,本周期从S1下方向上穿过S2时返回1,否则返回0;N=1时等同于CROSS(S1, S2)"""
    return np.array(np.logical_and(LAST(S1 < S2, N, 1), (S1 > S2)), dtype=bool)

def VALUEWHEN(S, X):
    """当S条件成立时,取X的当前值,否则取VALUEWHEN的上个成立时的X值"""
    return pd.Series(np.where(S, X, np.nan)).ffill().values


#------------------ 扩展函数(来自第二个文件)-------------------------------------
def BACKSET(X, N):
    """
    属于未来函数,将当前位置到若干周期前的数据设为1。
    用法:BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1。
    例如:BACKSET(CLOSE>OPEN,2) 若收阳则将该周期及前一周期数值设为1,否则为0
    """
    result = np.zeros_like(X)
    for i in range(len(X)):
        if X[i] != 0:
            start_index = max(0, i - N + 1)
            result[start_index:i+1] = 1
    return result

def ALIGNRIGHT(X):
    """
    有效数据右对齐。
    用法:ALIGNRIGHT(X) 有效数据向右移动,左边空出来的周期填充无效值
    例如:TC:=IF(CURRBARSCOUNT=2 || CURRBARSCOUNT=5, DRAWNULL, C); XC:=ALIGNRIGHT(TC);
         删除了两天的收盘价,并将剩余数据右移
    """
    valid_indices = np.where(X != np.nan)[0]
    invalid_count = len(X) - len(valid_indices)
    result = np.empty_like(X)
    result[:] = np.nan
    result[invalid_count:len(valid_indices)+invalid_count] = X[valid_indices]
    return result

def BARSCOUNT(X):
    """
    有效数据周期数。
    用法:BARSCOUNT(X) 第一个有效数据到当前的间隔周期数
    注意:判断范围为指标或条件选股计算时公式使用的数据,
          如果给画线指标的数据少(比如没有按下箭头取更多K线)或给条件选股给的数据少,这个有效值也可能少
    """
    valid_indices = np.where(~np.isnan(X))[0]
    if len(valid_indices) == 0:
        return 0
    first_valid_index = valid_indices[0]
    current_index = len(X) - 1
    bars_count = current_index - first_valid_index + 1
    return bars_count

def BARSLASTS(X, N):
    """
    倒数第N次成立时距今的周期数。
    用法:BARSLASTS(X,N): X倒数第N满足到现在的周期数,N支持变量
    """
    valid_indices = np.where(~np.isnan(X))[0]
    if len(valid_indices) == 0:
        return -1
    last_n_indices = valid_indices[-N:]
    if len(last_n_indices) < N:
        return -1
    current_index = len(X) - 1
    bars_since_last_n = current_index - last_n_indices[-1] + 1
    return bars_since_last_n

def ZIG(CLOSE, X=0.05):
    """
    未来函数,计算之字转向。
    用法:ZIG(CLOSE, 0.05) 5%之字转向
    """
    ZIG_STATE_START = 0
    ZIG_STATE_RISE = 1
    ZIG_STATE_FALL = 2
    x = X
    k = CLOSE
    peer_i = 0
    candidate_i = None
    scan_i = 0
    peers = [0]
    z = np.zeros(len(k))
    state = ZIG_STATE_START
    while True:
        scan_i += 1
        if scan_i == len(k) - 1:
            if candidate_i is None:
                peer_i = scan_i
                peers.append(peer_i)
            else:
                if state == ZIG_STATE_RISE:
                    if k[scan_i] >= k[candidate_i]:
                        peer_i = scan_i
                        peers.append(peer_i)
                    else:
                        peer_i = candidate_i
                        peers.append(peer_i)
                        peer_i = scan_i
                        peers.append(peer_i)
                elif state == ZIG_STATE_FALL:
                    if k[scan_i] <= k[candidate_i]:
                        peer_i = scan_i
                        peers.append(peer_i)
                    else:
                        peer_i = candidate_i
                        peers.append(peer_i)
                        peer_i = scan_i
                        peers.append(peer_i)
            break
        if state == ZIG_STATE_START:
            if k[scan_i] >= k[peer_i] * (1 + x):
                candidate_i = scan_i
                state = ZIG_STATE_RISE
            elif k[scan_i] <= k[peer_i] * (1 - x):
                candidate_i = scan_i
                state = ZIG_STATE_FALL
        elif state == ZIG_STATE_RISE:
            if k[scan_i] >= k[candidate_i]:
                candidate_i = scan_i
            elif k[scan_i] <= k[candidate_i] * (1 - x):
                peer_i = candidate_i
                peers.append(peer_i)
                state = ZIG_STATE_FALL
                candidate_i = scan_i
        elif state == ZIG_STATE_FALL:
            if k[scan_i] <= k[candidate_i]:
                candidate_i = scan_i
            elif k[scan_i] >= k[candidate_i] * (1 + x):
                peer_i = candidate_i
                peers.append(peer_i)
                state = ZIG_STATE_RISE
                candidate_i = scan_i
    for i in range(len(peers) - 1):
        peer_start_i = peers[i]
        peer_end_i = peers[i + 1]
        start_value = k[peer_start_i]
        end_value = k[peer_end_i]
        a = (end_value - start_value) / (peer_end_i - peer_start_i)
        for j in range(peer_end_i - peer_start_i + 1):
            z[j + peer_start_i] = start_value + a * j
    return pd.Series(z)
def calculate_zigzag(data, percent):
    """
    计算ZigZag指标。
    
    参数:
    data : pandas.DataFrame
        包含价格数据的DataFrame,必须包含'High'和'Low'列。
    percent : float
        百分比阈值,用于确定局部高点和低点。
        
    返回:
    zigzag : pandas.Series
        ZigZag指标值。
    """
    # 初始化ZigZag序列
    zigzag = pd.Series(index=data.index)
    
    # 初始方向为向上
    direction = 'up'
    
    # 遍历数据
    for i in range(1, len(data)):
        if direction == 'up':
            if data['high'][i] >= data['high'][i-1] * (1 + percent / 100):
                zigzag[i] = data['high'][i]
                direction = 'down'
            elif data['low'][i] <= data['low'][i-1] * (1 - percent / 100):
                zigzag[i] = data['low'][i]
                direction = 'down'
            else:
                zigzag[i] = zigzag[i-1]
        else:
            if data['low'][i] <= data['low'][i-1] * (1 - percent / 100):
                zigzag[i] = data['low'][i]
                direction = 'up'
            elif data['high'][i] >= data['high'][i-1] * (1 + percent / 100):
                zigzag[i] = data['high'][i]
                direction = 'up'
            else:
                zigzag[i] = zigzag[i-1]
    
    return zigzag

def TROUGHBARS(data, K, N, M):
    """
    计算前M个ZIG转向波谷到当前的周期数。
    
    参数:
    data : pandas.DataFrame
        包含价格数据的DataFrame,必须包含'High'和'Low'列。
    K : int
        百分比阈值,用于计算ZigZag指标。
    N : int
        未使用的参数,保留以符合函数签名。
    M : int
        前M个波谷的数量。
        
    返回:
    result : pandas.Series
        每个周期的前M个波谷到当前的周期数。
    """
    # 计算ZigZag指标
    zigzag = calculate_zigzag(data, K)
    
    # 找到波谷的位置
    valleys = zigzag[zigzag.notna() & (zigzag.shift(1) > zigzag)].index
    
    # 计算每个周期的前M个波谷到当前的周期数
    result = pd.Series(index=data.index)
    for i in range(len(data)):
        if i < len(valleys):
            result[i] = np.nan
        else:
            distances = [i - v for v in valleys[-M:]]
            result[i] = min(distances)
    
    return result
#df,DATE,CLOSE,OPEN,LOW,HIGH,VOL,CAPITAL,HSL,AMOUNT=set_start_data()
def params_data(test='test.txt',to_path='result.txt'):
    '''
    解析通达信公式
    test原来通达信公式文件
    to_path结果文件,python可以直接运行的文件
    '''
    test=open(r'{}'.format(test),'r',encoding='utf-8')
    result=test.readlines()
    columns=[]
    #挑选需要返回的数据
    for i in result:
        if ':' in i and ':=' not in i:
            name_list=i.split(':')
            columns.append(name_list[0])
    text=''.join(result)
    text1=text.replace(':=','=')
    text2=text1.replace(':','=')
    text4=text2.replace('&&',' and ')
    text5=text4.replace('||','or')
    text6=text5.replace('AND','and')
    text7=text6.replace('OR','or')
    text8=text7.replace('NOT','not')
    text9=text8.replace('DRAWNULL','None')
    text10=text9.replace(',NODRAW','')
    text11=text10.replace('MF0>MF1 and MF0>MF2','np.logical_and(MF0>MF1,MF0>MF2)')
    text12=text11.replace('MF0<MF1 and MF0<MF2','np.logical_and(MF0<MF1,MF0<MF2)')
    text3=text12.split(';')
    del text3[-1]
    fill=open(r'{}'.format(to_path),'w+',encoding='utf-8')
    fill.truncate()
    for i in text3:
        try:
            m=i.split('=')
            var=m[0]
            result=m[1]
            fill.write(var +'='+result)
        except:
           fill.write(var +'='+result)
    fill.write('\n')
    fill.write('return {}'.format(','.join(columns)))
    fill.close()
    print('公式分析成功')
def data_to_pandas(func=''):
    '''
    将函数的计算结果数据变成pandas数据,需要自动补充列名称
    func计算公式,例子data_to_pandas(CCI(CLOSE,HIGH,LOW)),CCI函数,也可以计算在返回
    print(data_to_pandas(CCI(CLOSE,HIGH,LOW)))
                   0       
    300          NaN       
    301          NaN       
    302          NaN       
    303          NaN       
    304          NaN       
    ...          ...       
    4634   10.314220       
    4635   68.462799       
    4636  106.677513       
    4637  116.201078       
    4638   85.026126  
    '''
    df=pd.DataFrame(func)
    #自己补充列明,列名称就是返回的参数
    columns=[]
    #df.columns=columns
    df1=df.T
    return df1
def CCI(CLOSE,HIGH,LOW,N=14):
    '''
    超卖超买类
    CCI商品路劲指标
    TYP赋值:(最高价+最低价+收盘价)/3
    输出CCI:(TYP-TYP的N日简单移动平均)*1000/(15*TYP的N日平均绝对偏差)
    '''
    TYP=(HIGH+LOW+CLOSE)/3
    result=(TYP-MA(TYP,N))*1000/(15*AVEDEV(TYP,N))
    return result
def KDJ(CLOSE,HIGH,LOW, N=9,M1=3,M2=3):
    '''
    超卖超买类
    RSV赋值:(收盘价-N日内最低价的最低值)/(N日内最高价的最高值-N日内最低价的最低值)*100
    输出K:RSV的M1日[1日权重]移动平均
    输出D:K的M2日[1日权重]移动平均
    输出J:3*K-2*D
    '''
    RSV=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100
    K=SMA(RSV,M1,1)
    D=SMA(K,M2,1)
    J=3*K-2*D
    return K,D,J
def MFI(CLOSE,HIGH,LOW,VOL,N=14):
    '''
    最近流量指标
    超卖超买类
    赋值: (最高价 + 最低价 + 收盘价)/3
    V1赋值:如果TYP>1日前的TYP,返回TYP*成交量(手),否则返回0的N日累和/如果TYP<1日前的TYP,返回TYP*成交量(手),否则返回0的N日累和
    输出资金流量指标:100-(100/(1+V1))
    '''
    TYP = (HIGH + LOW + CLOSE)/3
    V1=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N)  
    return 100-(100/(1+V1))  
def MTM(CLOSE,N=12,M=6):
    '''
    动量线指标
    超卖超买类
    输出动量线:收盘价-收盘价的有效数据周期数和N的较小值日前的收盘价
    输出MTMMA:MTM的M日简单移动平均
    '''
    MTM=CLOSE-REF(CLOSE,N)
    MTMMA=MA(MTM,M)
    return MTM,MTMMA
def EXPMEMA(data,N=20):
    '''
    data pandas.Series数据
    超卖超买类
    指数平滑移动平均
    '''
    result=data.ewm(com=N).mean()
    return result

def BARSCOUNT(CLOSE):
    df=pd.DataFrame()
    df['数据']=range(len(CLOSE))
    return df['数据']

def RSI(CLOSE, N1=6,N2=12,N3=24):
    '''
    相对强弱指标
    LC赋值:1日前的收盘价
    输出RSI1:收盘价-LC和0的较大值的N1日[1日权重]移动平均/收盘价-LC的绝对值的N1日[1日权重]移动平均*100
    输出RSI2:收盘价-LC和0的较大值的N2日[1日权重]移动平均/收盘价-LC的绝对值的N2日[1日权重]移动平均*100
    输出RSI3:收盘价-LC和0的较大值的N3日[1日权重]移动平均/收盘价-LC的绝对值的N3日[1日权重]移动平均*100
    '''
    LC=REF(CLOSE,1)
    RSI1=SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100
    RSI2=SMA(MAX(CLOSE-LC,0),N2,1)/SMA(ABS(CLOSE-LC),N2,1)*100
    RSI3=SMA(MAX(CLOSE-LC,0),N3,1)/SMA(ABS(CLOSE-LC),N3,1)*100
    return RSI1,RSI2,RSI3
def KD(CLOSE,LOW,HIGH,N=9,M1=3,M2=3):
    '''
    相对强弱指标
    RSV赋值:(收盘价-N日内最低价的最低值)/(N日内最高价的最高值-N日内最低价的最低值)*100
    输出K:RSV的M1日[1日权重]移动平均
    输出D:K的M2日[1日权重]移动平均
    '''
    RSV=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100
    K=SMA(RSV,M1,1)
    D=SMA(K,M2,1)
    return K,D
def SKDJ(CLOSE,LOW,HIGH,N=9,M=3):
    '''
    慢速随机指标
    LOWV赋值:N日内最低价的最低值
    HIGHV赋值:N日内最高价的最高值
    RSV赋值:(收盘价-LOWV)/(HIGHV-LOWV)*100的M日指数移动平均
    输出K:RSV的M日指数移动平均
    输出D:K的M日简单移动平均
    '''
    LOWV=LLV(LOW,N)
    HIGHV=HHV(HIGH,N)
    RSV=EMA((CLOSE-LOWV)/(HIGHV-LOWV)*100,M)
    K=EMA(RSV,M)
    D=MA(K,M)
    return K,D
def UDL(CLOSE,N1=3,N2=5,N3=10,N4=20,M=6):
    '''
    引力线
    输出引力线:(收盘价的N1日简单移动平均+收盘价的N2日简单移动平均+收盘价的N3日简单移动平均+收盘价的N4日简单移动平均)/4
    输出MAUDL:UDL的M日简单移动平均
    '''
    UDL=(MA(CLOSE,N1)+MA(CLOSE,N2)+MA(CLOSE,N3)+MA(CLOSE,N4))/4
    MAUDL=MA(UDL,M)
    return UDL,MAUDL
def WR(CLOSE,LOW,HIGH,N=10,N1=6):
    '''
    威廉指标
    输出WR1:100*(N日内最高价的最高值-收盘价)/(N日内最高价的最高值-N日内最低价的最低值)
    输出WR2:100*(N1日内最高价的最高值-收盘价)/(N1日内最高价的最高值-N1日内最低价的最低值)
    '''
    WR1=100*(HHV(HIGH,N)-CLOSE)/(HHV(HIGH,N)-LLV(LOW,N))
    WR2=100*(HHV(HIGH,N1)-CLOSE)/(HHV(HIGH,N1)-LLV(LOW,N1))
    return WR1,WR2
def LWR(CLOSE,LOW,HIGH,N=9,M1=3,M2=3):
    '''
    LWR指标
    RSV赋值: (N日内最高价的最高值-收盘价)/(N日内最高价的最高值-N日内最低价的最低值)*100
    输出LWR1:RSV的M1日[1日权重]移动平均
    输出LWR2:LWR1的M2日[1日权重]移动平均
    '''
    RSV= (HHV(HIGH,N)-CLOSE)/(HHV(HIGH,N)-LLV(LOW,N))*100
    LWR1=SMA(RSV,M1,1)
    LWR2=SMA(LWR1,M2,1)
    return LWR1,LWR2
def MEMA(S,N,M=1):
    '''
    平滑移动平均
    '''
    return SMA(S,N,M)
def MARSI(CLOSE,M1=10,M2=6):
    '''
    相对强弱平均线
    DIF赋值:收盘价-1日前的收盘价
    VU赋值:如果DIF>=0,返回DIF,否则返回0
    VD赋值:如果DIF<0,返回-DIF,否则返回0
    MAU1赋值:VU的M1日平滑移动平均
    MAD1赋值:VD的M1日平滑移动平均
    MAU2赋值:VU的M2日平滑移动平均
    '''
    DIF=CLOSE-REF(CLOSE,1)
    VU=IF(DIF>=0,DIF,0)
    VD=IF(DIF<0,-DIF,0)
    MAU1=MEMA(VU,M1)
    MAD1=MEMA(VD,M1)
    MAU2=MEMA(VU,M2)
    MAD2=MEMA(VD,M2)
    RSI1=MA(100*MAU1/(MAU1+MAD1),M1)
    RSI2=MA(100*MAU2/(MAU2+MAD2),M2)
    return RSI1,RSI2
def BIAS_QL(CLOSE,N=6,M=6):
    '''
    乖离率-传统版
    输出乖离率 :(收盘价-收盘价的N日简单移动平均)/收盘价的N日简单移动平均*100
    输出BIASMA :乖离率的M日简单移动平均
    '''
    BIAS=(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100
    BIASMA=MA(BIAS,M)
    return BIAS,BIASMA
def BIAS(CLOSE,N1=6,N2=12,N3=24):
    '''
    乖离率
    输出BIAS1 :(收盘价-收盘价的N1日简单移动平均)/收盘价的N1日简单移动平均*100
    输出BIAS2 :(收盘价-收盘价的N2日简单移动平均)/收盘价的N2日简单移动平均*100
    输出BIAS3 :(收盘价-收盘价的N3日简单移动平均)/收盘价的N3日简单移动平均*100
    '''
    BIAS1=(CLOSE-MA(CLOSE,N1))/MA(CLOSE,N1)*100
    BIAS2=(CLOSE-MA(CLOSE,N2))/MA(CLOSE,N2)*100
    BIAS3=(CLOSE-MA(CLOSE,N3))/MA(CLOSE,N3)*100
    return BIAS1,BIAS2,BIAS3
def BIAS36(CLOSE,M=6):
    '''
    三六乖离
    输出三六乖离:收盘价的3日简单移动平均-收盘价的6日简单移动平均
    输出BIAS612:收盘价的6日简单移动平均-收盘价的12日简单移动平均
    输出MABIAS:BIAS36的M日简单移动平均
    '''
    BIAS36=MA(CLOSE,3)-MA(CLOSE,6)
    BIAS612=MA(CLOSE,6)-MA(CLOSE,12)
    MABIAS=MA(BIAS36,M)
    return BIAS36,BIAS612,MABIAS
def ACCER(CLOSE,N=8):
    '''
    幅度涨速
    输出幅度涨速:收盘价的N日线性回归斜率/收盘价
    '''
    ACCER=SLOPE(CLOSE,N)/CLOSE
    return ACCER
#需要编写活力函数
def CYD(CLOSE,CAPITAL,N=21):
    '''
    承接因子
    输出CYDS:以收盘价计算的获利盘比例/(成交量(手)/当前流通股本(手))
    输出CYDN:以收盘价计算的获利盘比例/成交量(手)/当前流通股本(手)的N日简单移动平均
    '''
    CYDS=WINNER(CLOSE)/(VOL/CAPITAL)
    CYDN=WINNER(CLOSE)/MA(VOL/CAPITAL,N);   
    return CYDS,CYDN
def CYF(HSL,N=21):
    '''
    市场能量
    输出市场能量:100-100/(1+换手线的N日指数移动平均)
    '''
    CYF=100-100/(1+EMA(HSL,N))
    return CYF
def SFL(CLOSE,VOL):
    '''
    分水岭
    输出SWL:(收盘价的5日指数移动平均*7+收盘价的10日指数移动平均*3)/10
    输出SWS:以1和100*(成交量(手)的5日累和/(3*当前流通股本(手)))的较大值为权重收盘价的12日指数移动平均的动态移动平均
    '''
    SWL=(EMA(CLOSE,5)*7+EMA(CLOSE,10)*3)/10
    IF(100*(SUM(VOL,5)/(3*CAPITAL)>1),100*(SUM(VOL,5)/(3*CAPITAL)),1)
    SWS=DMA(EMA(CLOSE,12),MAX(1,1))
    return SWL,SWS
def ATR(CLOSE,HIGH,LOW,N=14):
    '''
    真实波幅
    输出MTR:(最高价-最低价)和1日前的收盘价-最高价的绝对值的较大值和1日前的收盘价-最低价的绝对值的较大值
    输出真实波幅:MTR的N日简单移动平均
    '''
    MTR=MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW))
    ATR=MA(MTR,N)
    return MTR,ATR
def DKX(CLOSE,LOW,OPEN,HIGH,M=10):
    '''
    多空线
    MID赋值:(3*收盘价+最低价+开盘价+最高价)/6
    输出多空线:(20*MID+19*1日前的MID+18*2日前的MID+17*3日前的MID+16*4日前的MID+15*5日前的MID+14*6日前的MID+13*7日前的MID+12*8日前的MID+11*9日前的MID+10*10日前的MID+9*11日前的MID+8*12日前的MID+7*13日前的MID+6*14日前的MID+5*15日前的MID+4*16日前的MID+3*17日前的MID+2*18日前的MID+20日前的MID)/210
    输出MADKX:DKX的M日简单移动平均
    '''
    MID=(3*CLOSE+LOW+OPEN+HIGH)/6
    DKX=(20*MID+19*REF(MID,1)+18*REF(MID,2)+17*REF(MID,3)+
    16*REF(MID,4)+15*REF(MID,5)+14*REF(MID,6)+
    13*REF(MID,7)+12*REF(MID,8)+11*REF(MID,9)+
    10*REF(MID,10)+9*REF(MID,11)+8*REF(MID,12)+
    7*REF(MID,13)+6*REF(MID,14)+5*REF(MID,15)+
    4*REF(MID,16)+3*REF(MID,17)+2*REF(MID,18)+REF(MID,20))/210
    MADKX=MA(DKX,M)
    return DKX,MADKX
#*******************************************
#******************************************
#趋势类型
def ASI(OPEN,CLOSE,HIGH,LOW,M1=26,M2=10):   
    '''
    振动升降指标
    '''        
    LC=REF(CLOSE,1)
    AA=ABS(HIGH-LC)   
    BB=ABS(LOW-LC)
    CC=ABS(HIGH-REF(LOW,1))  
    DD=ABS(LC-REF(OPEN,1))
    R=IF( (AA>BB) & (AA>CC),AA+BB/2+DD/4,IF( (BB>CC) & (BB>AA),BB+AA/2+DD/4,CC+DD/4))
    X=(CLOSE-LC+(CLOSE-OPEN)/2+LC-REF(OPEN,1))
    SI=16*X/R*MAX(AA,BB)
    ASI=SUM(SI,M1)
    ASIT=MA(ASI,M2)
    return ASI,ASIT  
def CHO(CLOSE,OPEN,LOW,HIGH,VOL,N1=10,N2=20,M=6):
    '''
    佳庆指标
    MID赋值:成交量(手)*(2*收盘价-最高价-最低价)/(最高价+最低价)的历史累和
    输出佳庆指标:MID的N1日简单移动平均-MID的N2日简单移动平均
    输出MACHO:CHO的M日简单移动平均
    '''
    MID=SUM(VOL*(2*CLOSE-HIGH-LOW)/(HIGH+LOW),0)
    CHO=MA(MID,N1)-MA(MID,N2)
    MACHO=MA(CHO,M)
    return CHO,MACHO
def DMA_XT(CLOSE,N1=10,N2=50,M=10):
    '''
    平均差
    输出DIF:收盘价的N1日简单移动平均-收盘价的N2日简单移动平均
    输出DIFMA:DIF的M日简单移动平均
    '''
    DIF=MA(CLOSE,N1)-MA(CLOSE,N2)
    DIFMA=MA(DIF,M)
    return DIF,DIFMA
def DMI(CLOSE,HIGH,LOW,N=14,M=6):
    '''
    趋向指标
    MTR赋值:最高价-最低价和最高价-1日前的收盘价的绝对值的较大值和1日前的收盘价-最低价的绝对值的较大值的N日累和
    赋值:最高价-1日前的最高价
    赋值:1日前的最低价-最低价
    DMP赋值:如果HD>0并且HD>LD,返回HD,否则返回0的N日累和
    DMM赋值:如果LD>0并且LD>HD,返回LD,否则返回0的N日累和
    输出PDI: DMP*100/MTR
    输出MDI: DMM*100/MTR
    输出ADX: MDI-PDI的绝对值/(MDI+PDI)*100的M日简单移动平均
    输出ADXR:(ADX+M日前的ADX)/2
    '''
    MTR=SUM(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(REF(CLOSE,1)-LOW)),N)
    HD =HIGH-REF(HIGH,1)
    LD =REF(LOW,1)-LOW
    list_A=[]
    list_B=[]
    for m,n in zip(LD>0,LD>HD):
        if m==n and m==True:
            list_A.append(True)
        else:
            list_A.append(False)
    for i,j in zip(LD>0,LD>HD):
        if i==j and i==True:
            list_B.append(True)
        else:
            list_B.append(False)
    DMP=SUM(IF(list_A,HD,0),N)
    DMM=SUM(IF(list_B,LD,0),N)
    PDI= DMP*100/MTR
    MDI=DMM*100/MTR
    ADX=MA(ABS(MDI-PDI)/(MDI+PDI)*100,M)
    ADXR=(ADX+REF(ADX,M))/2
    return PDI,MDI,ADX,ADXR
def DPO(CLOSE,N=21,M=6):
    '''
    区间震荡线
    输出区间震荡线:收盘价-N/2+1日前的收盘价的N日简单移动平均
    输出MADPO:DPO的M日简单移动平均
    '''
    #print(REF(MA(CLOSE,N),N/2))
    DPO=CLOSE-REF(MA(CLOSE,7),6)
    MADPO=MA(DPO,M)
    return DPO,MADPO
def EMV(HIGH,LOW,VOL,N=14,M=9):
    '''
    简易波动指标
    VOLUME赋值:成交量(手)的N日简单移动平均/成交量(手)
    MID赋值:100*(最高价+最低价-1日前的最高价+最低价)/(最高价+最低价)
    输出EMV:MID*VOLUME*(最高价-最低价)/最高价-最低价的N日简单移动平均的N日简单移动平均
    输出MAEMV:EMV的M日简单移动平均
    '''
    VOLUME=MA(VOL,N)/VOL
    MID=100*(HIGH+LOW-REF(HIGH+LOW,1))/(HIGH+LOW)
    EMV=MA(MID*VOLUME*(HIGH-LOW)/MA(HIGH-LOW,N),N)
    MAEMV=MA(EMV,M)
    return EMV,MAEMV
def MACD(CLOSE,SHORT=12,LONG=26,MID=9):
    '''
    平滑异同平均线
    输出DIF:收盘价的SHORT日指数移动平均-收盘价的LONG日指数移动平均
    输出DEA:DIF的MID日指数移动平均
    输出平滑异同平均线:(DIF-DEA)*2,COLORSTICK
    '''
    DIF=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG)
    DEA=EMA(DIF,MID)
    MACD=(DIF-DEA)*2
    return DIF,DEA,MACD

def VMACD(VOL,SHORT=12,LONG=26,MID=9):
    '''
    量平滑异同平均线
    输出DIF:成交量(手)的SHORT日指数移动平均-成交量(手)的LONG日指数移动平均
    输出DEA:DIF的MID日指数移动平均
    输出平滑异同平均线:DIF-DEA,COLORSTICK
    '''
    DIF=EMA(VOL,SHORT)-EMA(VOL,LONG)
    DEA=EMA(DIF,MID)
    MACD=DIF-DEA
    return DIF,DEA,MACD
def SMACD(CLOSE,SHORT=12,LONG=26,MID=9):
    '''
    单线平滑异同平均线
    DIF赋值:收盘价的SHORT日指数移动平均-收盘价的LONG日指数移动平均
    输出DEA:DIF的MID日指数移动平均
    输出平滑异同平均线:DIF,COLORSTICK
    '''
    DIF=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG)
    DEA=EMA(DIF,MID)
    MACD=DIF
    return DEA,MACD
def QACD(CLOSE,N1=12,N2=12,M=9):
    '''
    快速异同平均线
    输出DIF:收盘价的N1日指数移动平均-收盘价的N2日指数移动平均
    输出平滑异同平均线:DIF的M日指数移动平均
    输出DDIF:DIF-MACD
    '''
    DIF=EMA(CLOSE,N1)-EMA(CLOSE,N2)
    MACD=EMA(DIF,M)
    DDIF=DIF-MACD
    return DIF,MACD,DDIF
def TRIX(CLOSE,N=12,M=9):
    '''
    三重指数平均线
    MTR赋值:收盘价的N日指数移动平均的N日指数移动平均的N日指数移动平均
    输出三重指数平均线:(MTR-1日前的MTR)/1日前的MTR*100
    输出MATRIX:TRIX的M日简单移动平均 
    '''
    MTR=EMA(EMA(EMA(CLOSE,N),N),N)
    TRIX=(MTR-REF(MTR,1))/REF(MTR,1)*100
    MATRIX=MA(TRIX,M) 
    return TRIX,MATRIX
def UOS(CLOSE,HIGH,LOW,N1=7,N2=14,N3=28,M=6):
    '''
    终极指标
    TH赋值:最高价和1日前的收盘价的较大值
    TL赋值:最低价和1日前的收盘价的较小值
    ACC1赋值:收盘价-TL的N1日累和/TH-TL的N1日累和
    ACC2赋值:收盘价-TL的N2日累和/TH-TL的N2日累和
    ACC3赋值:收盘价-TL的N3日累和/TH-TL的N3日累和
    输出终极指标:(ACC1*N2*N3+ACC2*N1*N3+ACC3*N1*N2)*100/(N1*N2+N1*N3+N2*N3)
    输出MAUOS:UOS的M日指数平滑移动平均
    '''
    TH=MAX(HIGH,REF(CLOSE,1))
    TL=MIN(LOW,REF(CLOSE,1))
    ACC1=SUM(CLOSE-TL,N1)/SUM(TH-TL,N1)
    ACC2=SUM(CLOSE-TL,N2)/SUM(TH-TL,N2)
    ACC3=SUM(CLOSE-TL,N3)/SUM(TH-TL,N3)
    UOS=(ACC1*N2*N3+ACC2*N1*N3+ACC3*N1*N2)*100/(N1*N2+N1*N3+N2*N3)
    MAUOS=EXPMEMA(pd.Series(UOS),M)
    return UOS,np.array(MAUOS)
def VTP(CLOSE,VOL,N=51,M=6):
    '''
    量价曲线
    输出量价曲线:成交量(手)*(收盘价-1日前的收盘价)/1日前的收盘价的N日累和
    输出MAVPT:VPT的M日简单移动平均
    '''
    VPT=SUM(VOL*(CLOSE-REF(CLOSE,1))/REF(CLOSE,1),N)
    MAVP=MA(VPT,M)
    return VPT,MAVP
def WVAD(CLOSE,OPEN,HIGH,LOW,VOL,N=24,M=6):
    '''
    威廉变异离散量
    输出WVAD:(收盘价-开盘价)/(最高价-最低价)*成交量(手)的N日累和/10000
    输出MAWVAD:WVAD的M日简单移动平均
    '''
    WVAD=SUM((CLOSE-OPEN)/(HIGH-LOW)*VOL,N)/10000
    MAWVAD=MA(WVAD,M)
    return WVAD,MAWVAD
def DBQR(CLOSE,INDEXC,N=5,M1=10,M2=20,M3=60):
    '''
    对比强弱(需下载日线)
    输出ZS:(大盘的收盘价-N日前的大盘的收盘价)/N日前的大盘的收盘价
    输出GG:(收盘价-N日前的收盘价)/N日前的收盘价
    输出MADBQR1:GG的M1日简单移动平均
    输出MADBQR2:GG的M2日简单移动平均
    输出MADBQR3:GG的M3日简单移动平均
    '''
    ZS=(INDEXC-REF(INDEXC,N))/REF(INDEXC,N)
    GG=(CLOSE-REF(CLOSE,N))/REF(CLOSE,N)
    MADBQR1=MA(GG,M1)
    MADBQR2=MA(GG,M2)
    MADBQR3=MA(GG,M3)
    return ZS,GG,MADBQR1,MADBQR2,MADBQR3
def JS(CLOSE,N=5,M1=5,M2=10,M3=20):
    '''
    加数线
    输出加速线:100*(收盘价-N日前的收盘价)/(N*N日前的收盘价)
    输出MAJS1:JS的M1日简单移动平均
    输出MAJS2:JS的M2日简单移动平均
    输出MAJS3:JS的M3日简单移动平均
    '''
    JS=100*(CLOSE-REF(CLOSE,N))/(N*REF(CLOSE,N))
    MAJS1=MA(JS,M1)
    MAJS2=MA(JS,M2)
    MAJS3=MA(JS,M3)
    return JS,MAJS1,MAJS2,MAJS3
def CYE(CLOSE):
    '''
    市场趋势
    MAL赋值:收盘价的5日简单移动平均
    MAS赋值:收盘价的20日简单移动平均的5日简单移动平均
    输出CYEL:(MAL-1日前的MAL)/1日前的MAL*100
    输出CYES:(MAS-1日前的MAS)/1日前的MAS*100
    '''
    MAL=MA(CLOSE,5)
    MAS=MA(MA(CLOSE,20),5)
    CYEL=(MAL-REF(MAL,1))/REF(MAL,1)*100
    CYES=(MAS-REF(MAS,1))/REF(MAS,1)*100
    return CYEL,CYES
def QR(CLOSE,INDEXC,N=21):
    '''
    强弱指标(需下载日线)
    NN赋值:收盘价的有效数据周期数和N的较小值
    输出 个股: (收盘价-NN日前的收盘价)/NN日前的收盘价*100
    输出 大盘: (大盘的收盘价-NN日前的大盘的收盘价)/NN日前的大盘的收盘价*100
    输出 强弱值:个股-大盘的2日指数移动平均,COLORSTICK
    '''
    NN=MIN(BARSCOUNT(CLOSE),N)
    GG=(CLOSE-REF(CLOSE,NN))/REF(CLOSE,NN)*100
    DP=(INDEXC-REF(INDEXC,NN))/REF(INDEXC,NN)*100
    value=EMA(GG-DP,2)
    return GG,DP,value
def GDX(CLOSE,HIGH,LOW,N=30,M=9):
    '''
    轨道线
    AA赋值:(2*收盘价+最高价+最低价)/4-收盘价的N日简单移动平均的绝对值/收盘价的N日简单移动平均
    输出 轨道:以AA为权重收盘价的动态移动平均
    输出压力线:(1+M/100)*轨道
    输出 支撑线:(1-M/100)*轨道
    '''
    AA=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,N))/MA(CLOSE,N)
    轨道 =DMA(AA,0.5)
    压力线=(1+M/100)*轨道 
    支撑线=(1-M/100)*轨道
    return 轨道,压力线,支撑线
def JLHB(CLOSE,LOW,HIGH,N=7,M=5):
    '''
    绝路航标
    VAR1赋值:(收盘价-60日内最低价的最低值)/(60日内最高价的最高值-60日内最低价的最低值)*80
    输出 B:VAR1的N日[1日权重]移动平均
    输出 VAR2:B的M日[1日权重]移动平均
    输出 绝路航标:如果B上穿VAR2ANDB<40,返回50,否则返回0
    '''
    VAR1=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*80
    B=SMA(VAR1,N,1)
    VAR2=SMA(B,M,1)
    绝路航标=IF(np.logical_and(B,VAR2),50,0)
    return B,VAR2,绝路航标
#********************************************
#********************************************
#能量类型
def BRAR(OPEN,HIGH,LOW,CLOSE,N=26):
    '''
    情绪指标
    输出BR:0和最高价-1日前的收盘价的较大值的N日累和/0和1日前的收盘价-最低价的较大值的N日累和*100
    输出AR:最高价-开盘价的N日累和/开盘价-最低价的N日累和*100
    '''
    BR=SUM(MAX(0,HIGH-REF(CLOSE,1)),N)/SUM(MAX(0,REF(CLOSE,1)-LOW),N)*100
    AR=SUM(HIGH-OPEN,N)/SUM(OPEN-LOW,N)*100
    return BR,AR
def CR(HIGH,LOW,N=26,M1=10,M2=20,M3=40,M4=60):
    '''
    带状能量线
    MID赋值:1日前的最高价+最低价/2
    输出带状能量线:0和最高价-MID的较大值的N日累和/0和MID-最低价的较大值的N日累和*100
    输出MA1:M1/2.5+1日前的CR的M1日简单移动平均
    输出均线:M2/2.5+1日前的CR的M2日简单移动平均
    输出MA3:M3/2.5+1日前的CR的M3日简单移动平均
    输出MA4:M4/2.5+1日前的CR的M4日简单移动平均
    '''
    MID=REF(HIGH+LOW,1)/2
    CR=SUM(MAX(0,HIGH-MID),N)/SUM(MAX(0,MID-LOW),N)*100
    MA1=pd.DataFrame(CR).shift(11).mean()
    MA2=pd.DataFrame(CR).shift(5).mean()
    MA3=pd.DataFrame(CR).shift(17).mean()
    MA4=pd.DataFrame(CR).shift(25).mean()
    return CR,MA1,MA2,MA3,MA4
def MASS(HIGH,LOW,N1=9,N2=25,M=6):
    '''
    梅斯线
    输出梅斯线:最高价-最低价的N1日简单移动平均/最高价-最低价的N1日简单移动平均的N1日简单移动平均的N2日累和
    输出MAMASS:MASS的M日简单移动平均
    '''
    MASS=SUM(MA(HIGH-LOW,N1)/MA(MA(HIGH-LOW,N1),N1),N2)
    MAMASS=MA(MASS,M)
    return MASS,MAMASS
def PSY(CLOSE,N=12,M=6):
    '''
    心理线
    输出PSY:统计N日中满足收盘价>1日前的收盘价的天数/N*100
    输出PSYMA:PSY的M日简单移动平均
    '''
    PSY=COUNT(CLOSE>REF(CLOSE,1),N)/N*100
    PSYMA=MA(PSY,M)
    return PSY,PSYMA
def VR(CLOSE,VOL,N=26,M=6):
    '''
    成交量变异率
    TH赋值:如果收盘价>1日前的收盘价,返回成交量(手),否则返回0的N日累和
    TL赋值:如果收盘价<1日前的收盘价,返回成交量(手),否则返回0的N日累和
    TQ赋值:如果收盘价=1日前的收盘价,返回成交量(手),否则返回0的N日累和
    输出VR:100*(TH*2+TQ)/(TL*2+TQ)
    输出MAVR:VR的M日简单移动平均
    '''
    TH=SUM(IF(CLOSE>REF(CLOSE,1),VOL,0),N)
    TL=SUM(IF(CLOSE<REF(CLOSE,1),VOL,0),N)
    TQ=SUM(IF(CLOSE==REF(CLOSE,1),VOL,0),N)
    VR=100*(TH*2+TQ)/(TL*2+TQ)
    MAVR=MA(VR,M)
    return VR,MAVR
def WAD(CLOSE,LOW,HIGH,M=30):
    '''
    威廉多空力度线
    MIDA赋值:收盘价-1日前的收盘价和最低价的较小值
    MIDB赋值:如果收盘价<1日前的收盘价,返回收盘价-1日前的收盘价和最高价的较大值,否则返回0
    输出威廉多空力度线:如果收盘价>1日前的收盘价,返回MIDA,否则返回MIDB的历史累和
    输出MAWAD:WAD的M日简单移动平均
    '''
    MIDA=CLOSE-MIN(REF(CLOSE,1),LOW)
    MIDB=IF(CLOSE<REF(CLOSE,1),CLOSE-MAX(REF(CLOSE,1),HIGH),0)
    WAD=SUM(IF(CLOSE>REF(CLOSE,1),MIDA,MIDB),0)
    MAWAD=MA(WAD,M)
    return WAD,MAWAD
def EXPMEMA(CLOSE,M=5):
    '''
    指数平滑
    '''
    return pd.Series(CLOSE).ewm(span=M, adjust=False).mean().values
def PCNT(CLOSE,M=5):
    '''
    输出幅度比:(收盘价-1日前的收盘价)/收盘价*100
    输出MAPCNT:PCNT的M日指数平滑移动平均
    '''
    PCNT=(CLOSE-REF(CLOSE,1))/CLOSE*100
    MAPCNT=EXPMEMA(PCNT,M)
    return PCNT,MAPCNT
def CYR(AMOUNT,VOL,N=13,M=5):
    '''
    市场强弱
    AMOUNT成交量=price*volume
    DIVE赋值:0.01*成交额(元)的N日指数移动平均/成交量(手)的N日指数移动平均
    输出市场强弱:(DIVE/1日前的DIVE-1)*100
    输出MACYR:CYR的M日简单移动平均
    '''
    DIVE=0.01*EMA(AMOUNT,N)/EMA(VOL,N)
    CYR=(DIVE/REF(DIVE,1)-1)*100
    MACYR=MA(CYR,M)
    return CYR,MACYR
#*********************************************
#*********************************************
#能量型
def AMO(AMOUNT,M1=5,M2=10):
    '''
    成交金额
    输出AMOW:成交额(元)/10000.0,VOLSTICK
    输出AMO1:AMOW的M1日简单移动平均
    输出AMO2:AMOW的M2日简单移动平均
    '''
    AMOW=AMOUNT/10000.0
    AMO1=MA(AMOW,M1)
    AMO2=MA(AMOW,M2)
    return AMOW,AMO1,AMO2
def OBV(VOL,CLOSE,M=30):
    '''
    累积能量线
    VA赋值:如果收盘价>1日前的收盘价,返回成交量(手),否则返回-成交量(手)
    输出OBV:如果收盘价=1日前的收盘价,返回0,否则返回VA的历史累和
    输出MAOBV:OBV的M日简单移动平均
    '''
    VA=IF(CLOSE>REF(CLOSE,1),VOL,-VOL)
    OBV=SUM(IF(CLOSE==REF(CLOSE,1),0,VA),0)
    MAOBV=MA(OBV,M)
    return OBV,MAOBV
def VOL_XT(VOL,M1=5,M2=10):
    '''
    成交量
    输出VOLUME:成交量(手),VOLSTICK
    输出MAVOL1:VOLUME的M1日简单移动平均
    输出MAVOL2:VOLUME的M2日简单移动平均
    '''
    VOLUME=VOL
    MAVOL1=MA(VOLUME,M1)
    MAVOL2=MA(VOLUME,M2)
    return MAVOL1,MAVOL2
def VRSI(VOL,N1=6,N2=12,N3=24):
    '''
    相对强弱量
    LC赋值:1日前的成交量(手)
    输出RSI1:成交量(手)-LC和0的较大值的N1日[1日权重]移动平均/成交量(手)-LC的绝对值的N1日[1日权重]移动平均*100
    输出RSI2:成交量(手)-LC和0的较大值的N2日[1日权重]移动平均/成交量(手)-LC的绝对值的N2日[1日权重]移动平均*100
    输出RSI3:成交量(手)-LC和0的较大值的N3日[1日权重]移动平均/成交量(手)-LC的绝对值的N3日[1日权重]移动平均*100
    '''
    LC=REF(VOL,1)
    RSI1=SMA(MAX(VOL-LC,0),N1,1)/SMA(ABS(VOL-LC),N1,1)*100
    RSI2=SMA(MAX(VOL-LC,0),N2,1)/SMA(ABS(VOL-LC),N2,1)*100
    RSI3=SMA(MAX(VOL-LC,0),N3,1)/SMA(ABS(VOL-LC),N3,1)*100
    return RSI1,RSI2,RSI3
def HSL(HSL,N=5):
    '''
    换手线
    '''
    HSL=HSL
    MAHSL=MA(HSL,N)
    return HSL,MAHSL
#******************************************
#******************************************
#均线系统
def MA_XT(CLOSE,M1=5,M2=10,M3=20,M4=60):
    '''
    均线
    输出MA1:收盘价的M1日简单移动平均
    输出均线:收盘价的M2日简单移动平均
    输出MA3:收盘价的M3日简单移动平均
    输出MA4:收盘价的M4日简单移动平均
    输出MA5:收盘价的M5日简单移动平均
    输出MA6:收盘价的M6日简单移动平均
    输出MA7:收盘价的M7日简单移动平均
    输出MA8:收盘价的M8日简单移动平均
    '''
    MA1=MA(CLOSE,M1)
    MA2=MA(CLOSE,M2)
    MA3=MA(CLOSE,M3)
    MA4=MA(CLOSE,M4)
    return MA1,MA2,MA3,MA4
def MA2(CLOSE,M1=5,M2=10,M3=20,M4=60,M5=120,M6=240,M7=360,M8=420,M9=680,M10=720):
    '''
    均线2
    输出MA1:收盘价的M1日简单移动平均
    输出均线:收盘价的M2日简单移动平均
    输出MA3:收盘价的M3日简单移动平均
    输出MA4:收盘价的M4日简单移动平均
    输出MA5:收盘价的M5日简单移动平均
    输出MA6:收盘价的M6日简单移动平均
    输出MA7:收盘价的M7日简单移动平均
    输出MA8:收盘价的M8日简单移动平均
    输出MA9:收盘价的M9日简单移动平均
    输出MA10:收盘价的M10日简单移动平均
    '''
    MA1=MA(CLOSE,M1)
    MA2=MA(CLOSE,M2)
    MA3=MA(CLOSE,M3)
    MA4=MA(CLOSE,M4)
    MA5=MA(CLOSE,M5)
    MA6=MA(CLOSE,M6)
    MA7=MA(CLOSE,M7)
    MA8=MA(CLOSE,M8)
    MA9=MA(CLOSE,M9)
    MA10=MA(CLOSE,M10)
    return MA1,MA2,MA3,MA4,MA5,MA6,MA7,MA8,MA8,MA9,MA10
def ACD(CLOSE,HIGH,LOW,M=20):
    '''
    升降线
    LC赋值:1日前的收盘价
    DIF赋值:收盘价-如果收盘价>LC,返回最低价和LC的较小值,否则返回最高价和LC的较大值
    输出升降线:如果收盘价=LC,返回0,否则返回DIF的历史累和
    输出MAACD:ACD的M日指数平滑移动平均
    '''
    LC=REF(CLOSE,1)
    DIF=CLOSE-IF(CLOSE>LC,MIN(LOW,LC),MAX(HIGH,LC))
    ACD=SUM(IF(CLOSE==LC,0,DIF),0)
    MAACD=EXPMEMA(ACD,M)
    return ACD,MAACD
def BBI(CLOSE,M1=3,M2=6,M3=12,M4=24):
    '''
    多空均线
    输出多空均线:(收盘价的M1日简单移动平均+收盘价的M2日简单移动平均+收盘价的M3日简单移动平均+收盘价的M4日简单移动平均)/4
    '''
    BBI=(MA(CLOSE,M1)+MA(CLOSE,M2)+MA(CLOSE,M3)+MA(CLOSE,M4))/4
    return BBI
def EXPMA(CLOSE,M1=12,M2=50):
    '''
    指数平均线
    输出EXP1:收盘价的M1日指数移动平均
    输出EXP2:收盘价的M2日指数移动平均
    '''
    EXP1=EMA(CLOSE,M1)
    EXP2=EMA(CLOSE,M2)
    return EXP1,EXP2
def HMA(HIGH,M1=6,M2=12,M3=30,M4=70,M5=90):
    '''
    高价平均线
    输出HMA1:最高价的M1日简单移动平均
    输出HMA2:最高价的M2日简单移动平均
    输出HMA3:最高价的M3日简单移动平均
    输出HMA4:最高价的M4日简单移动平均
    输出HMA5:最高价的M5日简单移动平均
    '''
    HMA1=MA(HIGH,M1)
    HMA2=MA(HIGH,M2)
    HMA3=MA(HIGH,M3)
    HMA4=MA(HIGH,M4)
    HMA5=MA(HIGH,M5)
    return HMA1,HMA2,HMA3,HMA4,HMA5
def LMA(LOW,M1=6,M2=12,M3=30,M4=70,M5=90):
    '''
    低价平均线
    输出LMA1:最低价的M1日简单移动平均
    输出LMA2:最低价的M2日简单移动平均
    输出LMA3:最低价的M3日简单移动平均
    输出LMA4:最低价的M4日简单移动平均
    输出LMA5:最低价的M5日简单移动平均
    '''
    LMA1=MA(LOW,M1)
    LMA2=MA(LOW,M2)
    LMA3=MA(LOW,M3)
    LMA4=MA(LOW,M4)
    LMA5=MA(LOW,M5)
    return LMA1,LMA2,LMA3,LMA4,LMA5
def VMA(HIGH,OPEN,LOW,CLOSE,M1=6,M2=12,M3=30,M4=70,M5=90):
    '''
    变异平均线
    VV赋值:(最高价+开盘价+最低价+收盘价)/4
    输出VMA1:VV的M1日简单移动平均
    输出VMA2:VV的M2日简单移动平均
    输出VMA3:VV的M3日简单移动平均
    输出VMA4:VV的M4日简单移动平均
    输出VMA5:VV的M5日简单移动平均
    '''
    VV=(HIGH+OPEN+LOW+CLOSE)/4
    VMA1=MA(VV,M1)
    VMA2=MA(VV,M2)
    VMA3=MA(VV,M3)
    VMA4=MA(VV,M4)
    VMA5=MA(VV,M5)
    return VMA1,VMA2,VMA3,VMA4,VMA5
def AMV(OPEN,CLOSE,VOL,M1=5,M2=13,M3=34,M4=60):
    '''
    成本均线
    AMOV赋值:成交量(手)*(开盘价+收盘价)/2
    输出AMV1:AMOV的M1日累和/成交量(手)的M1日累和
    输出AMV2:AMOV的M2日累和/成交量(手)的M2日累和
    输出AMV3:AMOV的M3日累和/成交量(手)的M3日累和
    输出AMV4:AMOV的M4日累和/成交量(手)的M4日累和
    '''
    AMOV=VOL*(OPEN+CLOSE)/2
    AMV1=SUM(AMOV,M1)/SUM(VOL,M1)
    AMV2=SUM(AMOV,M2)/SUM(VOL,M2)
    AMV3=SUM(AMOV,M3)/SUM(VOL,M3)
    AMV4=SUM(AMOV,M4)/SUM(VOL,M4)
    return AMV1,AMV2,AMV3,AMV4
def BBIBOLL(CLOSE,N=11,M=6):
    '''
    多空布林线
    CV赋值:收盘价
    输出多空布林线:(CV的3日简单移动平均+CV的6日简单移动平均+CV的12日简单移动平均+CV的24日简单移动平均)/4
    输出UPR:BBIBOLL+M*BBIBOLL的N日估算标准差
    输出DWN:BBIBOLL-M*BBIBOLL的N日估算标准差
    '''
    CV=CLOSE
    BBIBOLL=(MA(CV,3)+MA(CV,6)+MA(CV,12)+MA(CV,24))/4
    UPR=BBIBOLL+M*STD(BBIBOLL,N)
    DWN=BBIBOLL-M*STD(BBIBOLL,N)
    return BBIBOLL,UPR,DWN
def ALLIGAT(HIGH,LOW):
    '''
    鳄鱼线
    NN赋值:(最高价+最低价)/2
    输出上唇:3日前的NN的5日简单移动平均,COLOR40FF40
    输出牙齿:5日前的NN的8日简单移动平均,COLOR0000C0
    输出下颚:8日前的NN的13日简单移动平均,COLORFF4040
    '''
    H=HIGH
    L=LOW
    NN=(H+L)/2
    上唇=REF(MA(NN,5),3)
    牙齿=REF(MA(NN,8),5)
    下颚=REF(MA(NN,13),8)
    return 上唇,牙齿,下颚
def GMMA(CLOSE):
    '''
    顾比均线
    '''
    MA3=EMA(CLOSE,3)
    MA5=EMA(CLOSE,5)
    MA8=EMA(CLOSE,8)
    MA10=EMA(CLOSE,10)
    MA12=EMA(CLOSE,12)
    MA15=EMA(CLOSE,15)
    MA30=EMA(CLOSE,30)
    MA35=EMA(CLOSE,35)
    MA40=EMA(CLOSE,40)
    MA45=EMA(CLOSE,45)
    MA50=EMA(CLOSE,50)
    MA60=EMA(CLOSE,60)
    return MA3,MA5,MA8,MA10,MA12,MA15,MA30,MA35,MA40,MA45,MA50,MA60
#*******************************************
#*******************************************
#路径类
def BOLL(CLOSE,M=20):
    '''
    布林线
    输出BOLL:收盘价的M日简单移动平均
    输出UB:BOLL+2*收盘价的M日估算标准差
    输出LB:BOLL-2*收盘价的M日估算标准差
    '''
    BOLL=MA(CLOSE,M)
    UB=BOLL+2*STD(CLOSE,M)
    LB=BOLL-2*STD(CLOSE,M)
    return BOLL,UB,LB
def PBX(CLOSE,M1=4,M2=6,M3=9,M4=13,M5=18,M6=24):
    '''
    瀑布线
    输出PBX1:(收盘价的M1日指数移动平均+收盘价的M1*2日简单移动平均+收盘价的M1*4日简单移动平均)/3
    输出PBX2:(收盘价的M2日指数移动平均+收盘价的M2*2日简单移动平均+收盘价的M2*4日简单移动平均)/3
    输出PBX3:(收盘价的M3日指数移动平均+收盘价的M3*2日简单移动平均+收盘价的M3*4日简单移动平均)/3
    输出PBX4:(收盘价的M4日指数移动平均+收盘价的M4*2日简单移动平均+收盘价的M4*4日简单移动平均)/3
    输出PBX5:(收盘价的M5日指数移动平均+收盘价的M5*2日简单移动平均+收盘价的M5*4日简单移动平均)/3
    输出PBX6:(收盘价的M6日指数移动平均+收盘价的M6*2日简单移动平均+收盘价的M6*4日简单移动平均)/3
    '''
    PBX1=(EMA(CLOSE,M1)+MA(CLOSE,M1*2)+MA(CLOSE,M1*4))/3
    PBX2=(EMA(CLOSE,M2)+MA(CLOSE,M2*2)+MA(CLOSE,M2*4))/3
    PBX3=(EMA(CLOSE,M3)+MA(CLOSE,M3*2)+MA(CLOSE,M3*4))/3
    PBX4=(EMA(CLOSE,M4)+MA(CLOSE,M4*2)+MA(CLOSE,M4*4))/3
    PBX5=(EMA(CLOSE,M5)+MA(CLOSE,M5*2)+MA(CLOSE,M5*4))/3
    PBX6=(EMA(CLOSE,M6)+MA(CLOSE,M6*2)+MA(CLOSE,M6*4))/3
    return PBX1,PBX2,PBX3,PBX4,PBX5,PBX6
def ENE(CLOSE,N=25,M1=6,M2=6):
    '''
    轨道线
    输出UPPER:(1+M1/100)*收盘价的N日简单移动平均
    输出LOWER:(1-M2/100)*收盘价的N日简单移动平均
    输出轨道线:(UPPER+LOWER)/2
    '''
    UPPER=(1+M1/100)*MA(CLOSE,N)
    LOWER=(1-M2/100)*MA(CLOSE,N)
    ENE=(UPPER+LOWER)/2
    return UPPER,LOWER,ENE
def MIKE(HIGH,LOW,CLOSE,N=10):
    '''
    麦克支撑压力
    HLC赋值:1日前的(最高价+最低价+收盘价)/3的N日简单移动平均
    HV赋值:N日内最高价的最高值的3日指数移动平均
    LV赋值:N日内最低价的最低值的3日指数移动平均
    输出STOR:2*HV-LV的3日指数移动平均
    输出MIDR:HLC+HV-LV的3日指数移动平均
    输出WEKR:HLC*2-LV的3日指数移动平均
    '''
    HLC=REF(MA((HIGH+LOW+CLOSE)/3,N),1)
    HV=EMA(HHV(HIGH,N),3)
    LV=EMA(LLV(LOW,N),3)
    STOR=EMA(2*HV-LV,3)
    MIDR=EMA(HLC+HV-LV,3)
    WEKR=EMA(HLC*2-LV,3)
    WEKS=EMA(HLC*2-HV,3)
    MIDS=EMA(HLC-HV+LV,3)
    STOS=EMA(2*LV-HV,3)
    return STOR,MIDR,WEKR,WEKS,MIDS,STOS
def XS(CLOSE,VOL,N=13):
    '''
    薛斯通道
    VAR2赋值:收盘价*成交量(手)
    VAR3赋值:(VAR2的3日指数移动平均/成交量(手)的3日指数移动平均+VAR2的6日指数移动平均/成交量(手)的6日指数移动平均+VAR2的12日指数移动平均/成交量(手)的12日指数移动平均+VAR2的24日指数移动平均/成交量(手)的24日指数移动平均)/4的N日指数移动平均
    输出SUP:1.06*VAR3
    输出SDN:VAR3*0.94
    VAR4赋值:收盘价的9日指数移动平均
    输出LUP:VAR4*1.14的5日指数移动平均
    输出LDN:VAR4*0.86的5日指数移动平均
    '''
    VAR2=CLOSE*VOL
    VAR3=EMA((EMA(VAR2,3)/EMA(VOL,3)+EMA(VAR2,6)/EMA(VOL,6)+EMA(VAR2,12)/EMA(VOL,12)+EMA(VAR2,24)/EMA(VOL,24))/4,N)
    SUP=1.06*VAR3
    SDN=VAR3*0.94
    VAR4=EMA(CLOSE,9)
    LUP=EMA(VAR4*1.14,5)
    LDN=EMA(VAR4*0.86,5)
    return SUP,SDN,LUP,LDN
def XS2(CLOSE,HIGH,LOW,N=102,M=7):
    '''
    薛斯通道II
    AA赋值:(2*收盘价+最高价+最低价)/4的5日简单移动平均
    输出 通道1:AA*N/100
    输出 通道2:AA*(200-N)/100
    CC赋值:(2*收盘价+最高价+最低价)/4-收盘价的20日简单移动平均的绝对值/收盘价的20日简单移动平均
    DD赋值:以CC为权重收盘价的动态移动平均
    输出 通道3:(1+M/100)*DD
    '''
    AA=MA((2*CLOSE+HIGH+LOW)/4,5)
    通道1=AA*N/100
    通道2=AA*(200-N)/100
    CC=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,20))/MA(CLOSE,20)
    DD=DMA(CLOSE,0.5)
    通道3=(1+M/100)*DD
    通道4=(1-M/100)*DD
    return 通道1,通道2,通道3,通道4
def TQN(HIGH, LOW, X1=20, X2=20):
    '''
    唐奇安通道
    输出周期高点:1日前的X1日内最高价的最高值
    输出周期低点:1日前的X2日内最低价的最低值
    平空开多赋值:最高价>=周期高点
    平多开空赋值:最低价<=周期低点
    先平空仓再开多仓
    先平多仓再开空仓
    自动过滤交易信号
    '''
    # 计算周期高点:X1日内最高价的最高值,然后取1日前的值
    周期高点 = REF(HHV(HIGH, X1), 1)
    
    # 计算周期低点:X2日内最低价的最低值,然后取1日前的值
    周期低点 = REF(LLV(LOW, X2), 1)
    
    # 平空开多信号:最高价 >= 周期高点
    平空开多 = HIGH >= 周期高点
    
    # 平多开空信号:最低价 <= 周期低点
    平多开空 = LOW <= 周期低点
    
    return 周期高点, 周期低点, 平空开多, 平多开空
#*******************************************
#*******************************************
def SAR(HIGH, LOW, M=10, af=2, amax=20):
    '''
    抛物线指标
    '''
    af = af / 100
    amax = amax / 100
    
    # 转换为numpy数组,处理NaN
    high = np.array(HIGH, dtype=float)
    low = np.array(LOW, dtype=float)
    
    # 检查数据有效性
    if len(high) == 0 or np.isnan(high).all() or np.isnan(low).all():
        return pd.Series([np.nan] * len(HIGH))
    
    # 替换NaN为有效值(用前向填充或均值)
    high_clean = pd.Series(high).fillna(method='ffill').fillna(method='bfill').values
    low_clean = pd.Series(low).fillna(method='ffill').fillna(method='bfill').values
    
    n = len(high_clean)
    
    # 初始化结果数组
    sar = np.full(n, np.nan)
    
    # 需要至少 M+1 个数据点
    if n < M + 1:
        return pd.Series(sar, index=HIGH.index if hasattr(HIGH, 'index') else None)
    
    # 计算标准差,处理0值
    hl_std = np.std(high_clean - low_clean)
    if hl_std == 0 or np.isnan(hl_std):
        hl_std = 0.001  # 设置一个极小值避免除零
    
    # 起始值
    sig0 = True
    xpt0 = high_clean[M - 1] if M > 0 else high_clean[0]
    af0 = af
    
    # 第一个SAR值
    sar[0] = low_clean[0] - hl_std
    
    for i in range(1, n):
        sig1 = sig0
        xpt1 = xpt0
        af1 = af0
        
        if i < M:
            # 前M个数据点使用简单方式
            if i > 0:
                sar[i] = sar[i-1] + (xpt1 - sar[i-1]) * af1
            continue
        
        # 获取当前和前一个的高低点
        lmin = min(low_clean[i-1], low_clean[i])
        lmax = max(high_clean[i-1], high_clean[i])
        
        # 判断趋势方向
        if sig1:
            sig0 = low_clean[i] > sar[i-1]
            xpt0 = max(lmax, xpt1)
        else:
            sig0 = high_clean[i] >= sar[i-1]
            xpt0 = min(lmin, xpt1)
        
        # 计算SAR值
        if sig0 == sig1:
            sari = sar[i-1] + (xpt1 - sar[i-1]) * af1
            af0 = min(amax, af1 + af)
            
            if sig0:
                af0 = af0 if xpt0 > xpt1 else af1
                sari = min(sari, lmin)
            else:
                af0 = af0 if xpt0 < xpt1 else af1
                sari = max(sari, lmax)
        else:
            af0 = af
            sari = xpt0
        
        sar[i] = sari
    
    # 转换为pandas Series,保持索引一致
    if hasattr(HIGH, 'index'):
        return pd.Series(sar, index=HIGH.index)
    else:
        return pd.Series(sar)
#*******************************
#******************************
#交易类型
def MA_交易(CLOSE,SHORT=5,LONG=20):
    '''
    MA_交易
    MA1赋值:收盘价的SHORT日简单移动平均
    MA2赋值:收盘价的LONG日简单移动平均
    平空开多赋值:MA1上穿MA2
    平多开空赋值:MA2上穿MA1
    先平空仓再开多仓
    先平多仓再开空仓
    '''
    MA1=MA(CLOSE,SHORT)
    MA2=MA(CLOSE,LONG)
    平空开多=CROSS(MA1,MA2)
    平多开空=CROSS(MA2,MA1)
    return MA1,MA2,平空开多,平多开空
def MACD_交易(CLOSE,SHORT=12,LONG=26,MID=9):
    '''
    MACD交易
    DIFF赋值:收盘价的SHORT日指数移动平均-收盘价的LONG日指数移动平均
    DEA赋值:DIFF的MID日指数移动平均
    MACD赋值:2*(DIFF-DEA)
    平空开多赋值:MACD上穿0
    平多开空赋值:0上穿MACD
    先平空仓再开多仓
    '''
    DIFF=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG)
    DEA=EMA(DIFF,MID)
    MACD=2*(DIFF-DEA)
    平空开多=CROSS(MACD,0)
    平空开多=CROSS(0,MACD)
    return DIFF,DEA,MACD,平空开多,平空开多
def KDJ_交易(CLOSE,HIGH,LOW,N=9,M1=3):
    '''
    KDJ交易
    RSV赋值:(收盘价-N日内最低价的最低值)/(N日内最高价的最高值-N日内最低价的最低值)*100
    K赋值:RSV的M1日[1日权重]移动平均
    D赋值:K的M1日[1日权重]移动平均
    J赋值:3*K-2*D
    平空开多赋值:J上穿0
    平多开空赋值:100上穿J
    先平空仓再开多仓
    先平多仓再开空仓
    自动过滤交易信号
    '''
    RSV=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100
    K=SMA(RSV,M1,1)
    D=SMA(K,M1,1)
    J=3*K-2*D
    平空开多=CROSS(J,0)
    平多开空=CROSS(100,J)
    return K,D,J,平空开多,平多开空
#*****************************************
#*****************************************
#神系
def SG_XDT(CLOSE,INDEXC,P1=5,P2=10):
    '''
    心电图(需下载日线)
    输出强弱指标(需下载日线):收盘价/大盘的收盘价*1000
    输出MQR1:QR的5日简单移动平均
    输出MQR2:QR的10日简单移动平均
    ''' 
    QR=CLOSE/INDEXC*1000
    MQR1=MA(QR,5)
    MQR2=MA(QR,10)
    return QR,MQR1,MQR2
def SG_NDB(CLOSE,HIGH,LOW,P1=5,P2=10):
    '''
    脑电波(神系)
    HH赋值:如果收盘价/1日前的收盘价>1.093ANDL>1日前的最高价,返回2*收盘价-1日前的收盘价-最高价,否则返回2*收盘价-最高价-最低价
    V1赋值:收盘价的有效数据周期数
    V2赋值:2*V1日前的收盘价-V1日前的最高价-V1日前的最低价
    输出DK:HH的历史累和+V2
    输出MDK1:DK的P1日简单移动平均
    输出MDK2:DK的P2日简单移动平均
    '''
    C=CLOSE
    H=HIGH
    L=LOW
    HH=IF(np.logical_or(C/REF(C,1)>1.093 ,L>REF(H,1)),2*C-REF(C,1)-H,2*C-H-L)
    V1=1
    V2=2*REF(C,V1)-REF(H,V1)-REF(L,V1)
    DK=SUM(HH,0)+V2
    MDK1=MA(DK,P1)
    MDK2=MA(DK,P2)
    return DK,MDK1,MDK2
def SG_SMX(CLOSE,HIGH,LOW,INDEXH,INDEXL,INDEXC,N=50):
    '''
    生命线(需下载日线)
    INDEXH,INDEXL,INDEXC指数的高,低收盘价,可以通过akshare.stock_zh_a_daily(sybol='sh000001')获取
    H1赋值:N日内最高价的最高值
    L1赋值:N日内最低价的最低值
    H2赋值:N日内大盘的最高价的最高值
    L2赋值:N日内大盘的最低价的最低值
    ZY赋值:收盘价/大盘的收盘价*2000
    输出ZY1:ZY的3日指数移动平均
    输出ZY2:ZY的17日指数移动平均
    输出ZY3:ZY的34日指数移动平均
    '''
    H1=HHV(HIGH,N)
    L1=LLV(LOW,N)
    H2=HHV(INDEXH,N)
    L2=LLV(INDEXL,N)
    ZY=CLOSE/INDEXC*2000
    ZY1=EMA(ZY,3)
    ZY2=EMA(ZY,17)
    ZY3=EMA(ZY,34)
    return ZY1,ZY2,ZY3
def SG_LB(VOL,INDEXV):
    '''
    量比(需下载日线)
    VOl个股成交量,INDXEXV大盘成交量,可以通过ak.stock_zh_a_daily()获取
    ZY2赋值:成交量(手)/大盘的成交量*1000
    输出量比:ZY2
    输出MA5:ZY2的5日简单移动平均
    输出MA10:ZY2的10日简单移动平均
    '''
    ZY2=VOL/INDEXV*1000
    量比=ZY2
    MA5=MA(ZY2,5)
    MA10=MA(ZY2,10)
    return 量比,MA5,MA10
def SG_PF(CLOSE,INDEXC):
    '''
    强势股评分(需下载日线)
    ZY1赋值:收盘价/大盘的收盘价*1000
    A1赋值:如果ZY1>3日内ZY1的最高值,返回10,否则返回0
    A2赋值:如果ZY1>5日内ZY1的最高值,返回15,否则返回0
    A3赋值:如果ZY1>10日内ZY1的最高值,返回20,否则返回0
    A4赋值:如果ZY1>2日内ZY1的最高值,返回10,否则返回0
    A5赋值:统计9日中满足ZY1>1日前的ZY1的天数*5
    输出强势股评分:A1+A2+A3+A4+A5
    '''
    ZY1=CLOSE/INDEXC*1000
    A1=IF(ZY1>HHV(ZY1,3),10,0)
    A2=IF(ZY1>HHV(ZY1,5),15,0)
    A3=IF(ZY1>HHV(ZY1,10),20,0)
    A4=IF(ZY1>HHV(ZY1,2),10,0)
    A5=COUNT(ZY1>REF(ZY1,1) ,9)*5
    强势股评分=A1+A2+A3+A4+A5
    return 强势股评分
#*************************************************
#*************************************************
#龙系
def RAD(OPEN,HIGH,CLOSE,LOW,INDEXO,INDEXH,INDEXL,INDEXC,D=3,S=30,M=30):
    '''
    威力雷达(需下载日线)
    OPEN+HIGH+CLOSE+LOW个股
    INDEXO+INDEXH+INDEXL+INDEXC大盘数据,可以通过akshare获取
    SM赋值:(开盘价+最高价+收盘价+最低价)/4
    SMID赋值:SM的D日简单移动平均
    IM赋值:(大盘的开盘价+大盘的最高价+大盘的最低价+大盘的收盘价)/4
    IMID赋值:IM的D日简单移动平均
    SI1赋值:(SMID-1日前的SMID)/SMID
    II赋值:(IMID-1日前的IMID)/IMID
    输出RADER1:(SI1-II)*2的S日累和*1000
    输出RADERMA:RADER1的M日[1日权重]移动平均
    '''
    SM=(OPEN+HIGH+CLOSE+LOW)/4
    SMID=MA(SM,D)
    IM=(INDEXO+INDEXH+INDEXL+INDEXC)/4
    IMID=MA(IM,D)
    SI1=(SMID-REF(SMID,1))/SMID
    II=(IMID-REF(IMID,1))/IMID
    RADER1=SUM((SI1-II)*2,S)*1000
    RADERMA=SMA(RADER1,M,1)
    return RADER1,RADERMA
    return 
def LON(CLOSE,HIGH,LOW,VOL,N=10):
    '''
    龙系长线
    赋值: 1日前的收盘价
    赋值: 成交量(手)的2日累和/(((2日内最高价的最高值-2日内最低价的最低值))*100)
    赋值: (收盘价-LC)*VID
    赋值: RC的历史累和
    赋值: LONG的10日[1日权重]移动平均
    赋值: LONG的20日[1日权重]移动平均
    输出龙系长线 : DIFF-DEA
    输出LONMA : 龙系长线的N日简单移动平均
    输出LONT : 龙系长线, COLORSTICK
    '''
    LC = REF(CLOSE,1)
    VID = SUM(VOL,2)/(((HHV(HIGH,2)-LLV(LOW,2)))*100)
    RC = (CLOSE-LC)*VID
    LONG = SUM(RC,0)
    DIFF = SMA(LONG,10,1)
    DEA = SMA(LONG,20,1)
    LON = DIFF-DEA
    LONMA = MA(LON,N)
    LONT = LON
    return LON,LONMA,LONT
def SHT(CLOSE,VOL,N=5):
    '''
    龙系短线
    VAR1赋值:(成交量(手)-1日前的成交量(手))/1日前的成交量(手)的5日简单移动平均
    VAR2赋值:(收盘价-收盘价的24日简单移动平均)/收盘价的24日简单移动平均*100
    输出MY: VAR2*(1+VAR1)
    输出龙系短线: MY, COLORSTICK
    输出SHTMA: SHT的N日简单移动平均
    '''
    VAR1=MA((VOL-REF(VOL,1))/REF(VOL,1),5)
    VAR2=(CLOSE-MA(CLOSE,24))/MA(CLOSE,24)*100
    MY= VAR2*(1+VAR1)
    SHT= MY#COLORSTICK
    SHTMA= MA(SHT,N)
    return SHT,SHTMA
def ZLJC(CLOSE,LOW,HIGH,VOL):
    '''
    主力进出
    VAR1赋值:(收盘价+最低价+最高价)/3
    VAR2赋值:((VAR1-1日前的最低价)-(最高价-VAR1))*成交量(手)/100000/(最高价-最低价)的历史累和
    VAR3赋值:VAR2的1日指数移动平均
    输出 JCS:VAR3
    输出 JCM:VAR3的12日简单移动平均
    输出 JCL:VAR3的26日简单移动平均
    '''
    VAR1=(CLOSE+LOW+HIGH)/3
    VAR2=SUM(((VAR1-REF(LOW,1))-(HIGH-VAR1))*VOL/100000/(HIGH-LOW),0)
    VAR3=EMA(VAR2,1)
    JCS=VAR3
    JCM=MA(VAR3,12)
    JCL=MA(VAR3,26)
    return JCS,JCM,JCL
def ZLMM(CLOSE):
    '''
    赋值:1日前的收盘价
    RSI2赋值:收盘价-LC和0的较大值的12日[1日权重]移动平均/收盘价-LC的绝对值的12日[1日权重]移动平均*100
    RSI3赋值:收盘价-LC和0的较大值的18日[1日权重]移动平均/收盘价-LC的绝对值的18日[1日权重]移动平均*100
    输出MMS:3*RSI2-2*收盘价-LC和0的较大值的16日[1日权重]移动平均/收盘价-LC的绝对值的16日[1日权重]移动平均*100的3日简单移动平均
    输出MMM:MMS的8日指数移动平均
    输出MML:3*RSI3-2*收盘价-LC和0的较大值的12日[1日权重]移动平均/收盘价-LC的绝对值的12日[1日权重]移动平均*100的5日简单移动平均
    '''
    LC =REF(CLOSE,1)
    RSI2=SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100
    RSI3=SMA(MAX(CLOSE-LC,0),18,1)/SMA(ABS(CLOSE-LC),18,1)*100
    MMS=MA(3*RSI2-2*SMA(MAX(CLOSE-LC,0),16,1)/SMA(ABS(CLOSE-LC),16,1)*100,3)
    MMM=EMA(MMS,8)
    MML=MA(3*RSI3-2*SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100,5)
    return MMS,MMM,MML
def SLZT(CLOSE,LOW,HIGH):
    '''
    神龙在天
    输出白龙: 收盘价的125日简单移动平均
    输出黄龙: 白龙+2*收盘价的170日估算标准差
    输出紫龙: 白龙-2*收盘价的145日估算标准差
    输出青龙: 步长为1极限值为7的125日抛物转向, LINESTICK
    VAR2赋值:70日内最高价的最高值
    VAR3赋值:20日内最高价的最高值
    输出红龙: VAR2*0.83
    输出蓝龙: VAR3*0.91
    '''
    白龙=MA(CLOSE,125)
    黄龙=白龙+2*STD(CLOSE,170)
    紫龙=白龙-2*STD(CLOSE,145)
    青龙=SAR(HIGH,LOW,125,1,7)# LINESTICK;
    VAR2=HHV(HIGH,70)
    VAR3=HHV(HIGH,20)
    红龙= VAR2*0.83
    蓝龙=VAR3*0.91
    return 白龙,黄龙,紫龙,青龙,红龙,蓝龙
def ADVOL(CLOSE,HIGH,LOW,VOL):
    '''
    龙系离散量
    A赋值:((收盘价-最低价)-(最高价-收盘价))*成交量(手)/10000/(最高价-最低价)的历史累和
    输出龙系离散量:A
    输出MA1:A的30日简单移动平均
    输出均线:MA1的100日简单移动平均
    '''
    A=SUM(((CLOSE-LOW)-(HIGH-CLOSE))*VOL/10000/(HIGH-LOW),0)
    ADVOL=A
    MA1=MA(A,30)
    MA2=MA(MA1,100)
    return ADVOL,MA1,MA2
#*********************************************
#*********************************************
#鬼系
def CYC(code='sh600031',start_date='20210101',end_date='20221022',P1=5,P2=13,P3=34):
    '''
    成本均线
    JJJ赋值:如果总量>0.01,简单理解流通股,返回0.01*总金额/总量,否则返回昨收盘价
    DDD赋值:(最高价<0.01 或者 最低价<0.01)
    JJJT赋值:如果DDD,返回1,否则返回(JJJ<(最高价+0.01)并且JJJ>(最低价-0.01))
    输出CYC1:如果JJJT,返回0.01*成交额(元)的P1日指数移动平均/成交量(手)的P1日指数移动平均,否则返回(最高价+最低价+收盘价)/3的P1日指数移动平均
    输出CYC2:如果JJJT,返回0.01*成交额(元)的P2日指数移动平均/成交量(手)的P2日指数移动平均,否则返回(最高价+最低价+收盘价)/3的P2日指数移动平均
    输出CYC3:如果JJJT,返回0.01*成交额(元)的P3日指数移动平均/成交量(手)的P3日指数移动平均,否则返回(最高价+最低价+收盘价)/3的P3日指数移动平均
    输出CYC∞:如果JJJT,返回以100*成交量(手)/流通股本(股)为权重成交额(元)/(100*成交量(手))的动态移动平均,否则返回(最高价+最低价+收盘价)/3的120日指数移动平均
    '''
    pass
    def DYNAINFO_10(M=10):
        '''
        总金额=price*volume
        '''
        result=df['close']*df['volume']
        return result
    def DYNAINFO_3(M=3):
        '''
        昨日收盘价
        '''
        return df['close'].shift(1)
    def DYNAINFO_5(M=5):
        '''
        最高价
        '''
        return df['high']
    def DYNAINFO_6(M=6):
        '''
        最低价
        '''
        return df['low']
    AMOUNT=AMOUNT=df['close']*df['volume']
    VOL=df['volume']
    HIGH=df['high']
    LOW=df['low']
    CLOSE=df['close']
    def FINANCE_7(M=7):
        '''
        100*成交量
        '''
        return 100*df['volume']
    JJJ=IF(DYNAINFO_8(8)>0.01,0.01*DYNAINFO_10(10)/DYNAINFO_8(8),DYNAINFO_3(3))
    DDD=np.logical_or(DYNAINFO_5(5)<0.01,DYNAINFO_6(6)<0.01)
    JJJT=IF(DDD,False,np.logical_and(JJJ<(DYNAINFO_5(5)+0.01),JJJ>(DYNAINFO_6(6)-0.01)))
    CYC1=IF(JJJT,0.01*EMA(AMOUNT,P1)/EMA(VOL,P1),EMA((HIGH+LOW+CLOSE)/3,P1))
    CYC2=IF(JJJT,0.01*EMA(AMOUNT,P2)/EMA(VOL,P2),EMA((HIGH+LOW+CLOSE)/3,P2))
    CYC3=IF(JJJT,0.01*EMA(AMOUNT,P3)/EMA(VOL,P3),EMA((HIGH+LOW+CLOSE)/3,P3))
    #CYC_a=IF(JJJT,DMA(AMOUNT/(100*VOL),100*VOL/FINANCE_7(7)),EMA((HIGH+LOW+CLOSE)/3,120))
    return CYC1,CYC2,CYC3
def CYS(CLOSE,AMOUNT,VOL):
    '''
    市场盈亏
    AMOUNT成交额,VOL成交量
    CYC13赋值:0.01*成交额(元)的13日指数移动平均/成交量(手)的13日指数移动平均
    输出市场盈亏:(收盘价-CYC13)/CYC13*100
    '''
    CYC13=0.01*EMA(AMOUNT,13)/EMA(VOL,13)
    CYS=(CLOSE-CYC13)/CYC13*100
    return CYS
def CYQKL(CLOSE,OPEN):
    '''
    博弈K线长度
    输出KL:100*(以收盘价计算的获利盘比例-以开盘价计算的获利盘比例)
    '''
    KL=100*(WINNER(CLOSE)-WINNER(OPEN))
    return KL
def CYW(CLOSE,HIGH,LOW,VOL):
    '''
    主力控盘
    VAR1赋值:收盘价-最低价
    VAR2赋值:最高价-最低价
    VAR3赋值:收盘价-最高价
    VAR4赋值:如果最高价>最低价,返回(VAR1/VAR2+VAR3/VAR2)*成交量(手),否则返回0
    输出主力控盘: VAR4的10日累和/10000, COLORSTICK
    '''
    VAR1=CLOSE-LOW
    VAR2=HIGH-LOW
    VAR3=CLOSE-HIGH
    VAR4=IF(HIGH>LOW,(VAR1/VAR2+VAR3/VAR2)*VOL,0)
    CYW=SUM(VAR4,10)/10000 #COLORSTICK
    return CYW
#***************************************************
#***************************************************
#其他系
def PEAK(CLOSE,N,n=1):
    '''
    计算倾效
    np.polyfit(range(N),x,deg=1)
    '''
    pass
def TROUGH(CLOSE,N,n=1):
    '''
    箱底
    '''
    pass
def XT(CLOSE):
    '''
    箱体
    '''
    箱顶=PEAK(CLOSE,N,1)*0.98
    箱底=TROUGH(CLOSE,N,1)*1.02
    箱高=100*(箱顶-箱底)/箱底,#NODRAW
def  MOD(M,N):
    '''
    计算模
    M/N的余数
    '''
    return M//N
def SQJZ(CLSOE):
    '''
    N赋值:到最后交易的周期
    B赋值:收盘价<4日前的收盘价
    T1赋值: 条件连续成立次数
    A_B1赋值:(T1>9) AND T1关于9的模=1
    A_B2赋值:(T1>9) AND T1关于9的模=2
    A_B8赋值:(T1>9) AND T1关于9的模=8
    A_B9赋值:(T1>9) AND T1关于9的模=0
    B1赋值:(N=6 AND 5日后的(平滑处理)统计6日中满足B的天数=6) OR (N=7 AND 6日后的(平滑处理)统计7日中满足B的天数=7) OR (N=8 AND 7日后的(平滑处理)统计8日中满足B的天数=8) OR (N>=9 AND 8日后的(平滑处理)统计9日中满足B的天数=9)
    当满足条件B1AND(1日前的B=0ORA_B1)时,在最低价位置书写数字,画洋红色
    B2赋值:(N=5 AND 4日后的(平滑处理)统计6日中满足B的天数=6) OR (N=6 AND 5日后的(平滑处理)统计7日中满足B的天数=7) OR (N=7 AND 6日后的(平滑处理)统计8日中满足B的天数=8) OR (N>=8 AND 7日后的(平滑处理)统计9日中满足B的天数=9)
    当满足条件B2AND(2日前的B=0ORA_B2)时,在最低价位置书写数字,画洋红色
    B8赋值:(N=1 AND 统计8日中满足B的天数=8) OR (N>=2 AND 1日后的(平滑处理)统计9日中满足B的天数=9)
    当满足条件B8AND(8日前的B=0ORA_B8)时,在最低价位置书写数字,画洋红色
    B9赋值:(N>=1 AND 统计9日中满足B的天数=9)
    当满足条件B9AND(9日前的B=0ORA_B9)时,在最低价位置书写数字,画红色
    S赋值:收盘价>4日前的收盘价
    T2赋值: 条件连续成立次数
    A_S1赋值:(T2>9) AND T2关于9的模=1
    A_S2赋值:(T2>9) AND T2关于9的模=2
    A_S8赋值:(T2>9) AND T2关于9的模=8
    A_S9赋值:(T2>9) AND T2关于9的模=0
    S1赋值:(N=6 AND 5日后的(平滑处理)统计6日中满足S的天数=6) OR (N=7 AND 6日后的(平滑处理)统计7日中满足S的天数=7) OR (N=8 AND 7日后的(平滑处理)统计8日中满足S的天数=8) OR (N>=9 AND 8日后的(平滑处理)统计9日中满足S的天数=9)
    当满足条件S1AND(1日前的S=0ORA_S1)时,在最高价位置书写数字,画洋红色,显示在位置之上
    S2赋值:(N=5 AND 4日后的(平滑处理)统计6日中满足S的天数=6) OR (N=6 AND 5日后的(平滑处理)统计7日中满足S的天数=7) OR (N=7 AND 6日后的(平滑处理)统计8日中满足S的天数=8) OR (N>=8 AND 7日后的(平滑处理)统计9日中满足S的天数=9)
    当满足条件S2AND(2日前的S=0ORA_S2)时,在最高价位置书写数字,画洋红色,显示在位置之上
    S8赋值:(N=1 AND 统计8日中满足S的天数=8) OR (N>=2 AND 1日后的(平滑处理)统计9日中满足S的天数=9)
    当满足条件S8AND(8日前的S=0ORA_S8)时,在最高价位置书写数字,画洋红色,显示在位置之上
    S9赋值:(N>=1 AND 统计9日中满足S的天数=9)
    当满足条件S9AND(9日前的S=0ORA_S9)时,在最高价位置书写数字,画绿色,显示在位置之上
    C=CLOSE
    N=CURRBARSCOUNT()
    B=C<REF(C,4)
    T1= BARSLASTCOUNT(B)
    A_B1=IF(T1>=9,1,None)
    A_B2=IF(T1>9,2,None)
    A_B8=IF(T1>9,8,None)
    A_B9=IF(T1>9,0,None)
    B1:=(N=6 AND REFXV(COUNT(B,6),5)=6) OR (N=7 AND REFXV(COUNT(B,7),6)=7) OR (N=8 AND REFXV(COUNT(B,8),7)=8) OR (N>=9 AND REFXV(COUNT(B,9),8)=9);
    DRAWNUMBER(B1 AND (REF(B,1)=0 OR A_B1),L,1),COLORMAGENTA;
    B2:=(N=5 AND REFXV(COUNT(B,6),4)=6) OR (N=6 AND REFXV(COUNT(B,7),5)=7) OR (N=7 AND REFXV(COUNT(B,8),6)=8) OR (N>=8 AND REFXV(COUNT(B,9),7)=9);
    DRAWNUMBER(B2 AND(REF(B,2)=0 OR A_B2),L,2),COLORMAGENTA;
    B8:=(N=1 AND COUNT(B,8)=8) OR (N>=2 AND REFXV(COUNT(B,9),1)=9);
    DRAWNUMBER(B8 AND (REF(B,8)=0 OR A_B8),L,8),COLORMAGENTA;
    B9:=(N>=1 AND COUNT(B,9)=9);
    DRAWNUMBER(B9 AND (REF(B,9)=0 OR A_B9),L,9),COLORRED;
    S:=C>REF(C,4);
    T2:= BARSLASTCOUNT(S);
    A_S1:=(T2>9) AND MOD(T2,9)=1;
    A_S2:=(T2>9) AND MOD(T2,9)=2;
    A_S8:=(T2>9) AND MOD(T2,9)=8;
    A_S9:=(T2>9) AND MOD(T2,9)=0;
    S1:=(N=6 AND REFXV(COUNT(S,6),5)=6) OR (N=7 AND REFXV(COUNT(S,7),6)=7) OR (N=8 AND REFXV(COUNT(S,8),7)=8) OR (N>=9 AND REFXV(COUNT(S,9),8)=9);
    DRAWNUMBER(S1 AND (REF(S,1)=0 OR A_S1),H,1),COLORMAGENTA,DRAWABOVE;
    S2:=(N=5 AND REFXV(COUNT(S,6),4)=6) OR (N=6 AND REFXV(COUNT(S,7),5)=7) OR (N=7 AND REFXV(COUNT(S,8),6)=8) OR (N>=8 AND REFXV(COUNT(S,9),7)=9);
    DRAWNUMBER(S2 AND (REF(S,2)=0 OR A_S2),H,2),COLORMAGENTA,DRAWABOVE;
    S8:=(N=1 AND COUNT(S,8)=8) OR (N>=2 AND REFXV(COUNT(S,9),1)=9);
    DRAWNUMBER(S8 AND (REF(S,8)=0 OR A_S8),H,8),COLORMAGENTA,DRAWABOVE;
    S9:=(N>=1 AND COUNT(S,9)=9);
    DRAWNUMBER(S9 AND (REF(S,9)=0 OR A_S9),H,9),COLORGREEN,DRAWABOVE;
    '''
    pass
def JAX(CLOSE,HIGH,LOW,N=30):
    '''
    济安线
    AA赋值:(2*收盘价+最高价+最低价)/4-收盘价的N日简单移动平均的绝对值/收盘价的N日简单移动平均
    输出济安线:以AA为权重(2*收盘价+最低价+最高价)/4的动态移动平均,线宽为3,画洋红色
    CC赋值:(收盘价/济安线)
    MA1赋值:CC*(2*收盘价+最高价+最低价)/4的3日简单移动平均
    MAAA赋值:((MA1-济安线)/济安线)/3
    TMP赋值:MA1-MAAA*MA1
    输出J:如果TMP<=济安线,返回济安线,否则返回无效数,线宽为3,画青色
    输出A:TMP,线宽为2,画棕色
    输出X:如果TMP<=济安线,返回TMP,否则返回无效数,线宽为2,画绿色
    '''
    AA=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,N))/MA(CLOSE,N)
    data=pd.DataFrame()
    data['数据']=(2*CLOSE+LOW+HIGH)/4
    #alpha中值0.5
    济安线=data['数据'].ewm(alpha=0.5, adjust=True).mean()#LINETHICK3,COLORMAGENTA
    CC=(CLOSE/济安线)
    MA1=MA(CC*(2*CLOSE+HIGH+LOW)/4,3)
    MAAA=((MA1-济安线)/济安线)/3
    TMP=MA1-MAAA*MA1
    J=IF(TMP<=济安线,济安线,None)#LINETHICK3,COLORCYAN
    A=TMP#LINETHICK2,COLORBROWN
    X=IF(TMP<=济安线,TMP,None)#LINETHICK2,COLORGREEN
    return J,A,X
def XJDX(CLOSE,HIGH,LOW):
    '''
    超级短线
    VAR1赋值:(2*收盘价+最高价+最低价)/4
    VAR2赋值:VAR1的4日指数移动平均的4日指数移动平均的4日指数移动平均
    输出J: (VAR2-1日前的VAR2)/1日前的VAR2*100, COLORSTICK
    输出D: J的3日简单移动平均
    输出K: J的1日简单移动平均
    '''
    VAR1=(2*CLOSE+HIGH+LOW)/4
    VAR2=EMA(EMA(EMA(VAR1,4),4),4)
    J=(VAR2-REF(VAR2,1))/REF(VAR2,1)*100# COLORSTICK
    D=MA(J,3)
    K= MA(J,1)
    return J,D,K
def ZJTJ(CLOSE):
    '''
    庄家抬轿
    获利盘,和成本函数需要写
    VAR1赋值:收盘价的9日指数移动平均的9日指数移动平均
    控盘赋值:(VAR1-1日前的VAR1)/1日前的VAR1*1000
    当满足条件控盘<0时,在控盘和0位置之间画柱状线,宽度为1,0不为0则画空心柱.,画白色
    A10赋值:控盘上穿0
    输出无庄控盘:如果控盘<0,返回控盘,否则返回0,画白色,NODRAW
    输出开始控盘:如果A10,返回5,否则返回0,线宽为1,画棕色
    当满足条件控盘>1日前的控盘AND控盘>0时,在控盘和0位置之间画柱状线,宽度为1,0不为0则画空心柱.,画红色
    输出有庄控盘:如果控盘>1日前的控盘AND控盘>0,返回控盘,否则返回0,画红色,NODRAW
    VAR2赋值:100*以收盘价*0.95计算的获利盘比例
    当满足条件VAR2>50ANDCOST(85)<CLOSEAND控盘>0时,在控盘和0位置之间画柱状线,宽度为1,0不为0则画空心柱.,COLORFF00FF
    输出高度控盘:如果VAR2>50ANDCOST(85)<CLOSEAND控盘>0,返回控盘,否则返回0,COLORFF00FF,NODRAW
    当满足条件控盘<1日前的控盘AND控盘>0时,在控盘和0位置之间画柱状线,宽度为1,0不为0则画空心柱.,COLOR00FF00
    输出主力出货:如果控盘<1日前的控盘AND控盘>0,返回控盘,否则返回0,COLOR00FF00,NODRAW
    '''
    VAR1=EMA(EMA(CLOSE,9),9)
    控盘=(VAR1-REF(VAR1,1))/REF(VAR1,1)*1000
    #STICKLINE(控盘<0,控盘,0,1,0),COLORWHITE;
    A10=CROSS(控盘,0)
    无庄控盘=IF(控盘<0,控盘,0)#COLORWHITE,NODRAW;
    开始控盘=IF(A10,1,0)#LINETHICK1,COLORBROWN;
    #STICKLINE(控盘>REF(控盘,1) AND 控盘>0,控盘,0,1,0),COLORRED;
    有庄控盘=IF(np.logical_and(控盘>REF(控盘,1),控盘>0),控盘,0)#COLORRED,NODRAW;
    #VAR2=100*WINNER(CLOSE*0.95)
    #STICKLINE(VAR2>50 AND COST(85)<CLOSE AND 控盘>0,控盘,0,1,0),COLORFF00FF;
    #高度控盘:IF(VAR2>50 AND COST(85)<CLOSE AND 控盘>0,控盘,0),COLORFF00FF,NODRAW;
    #STICKLINE(控盘<REF(控盘,1) AND 控盘>0,控盘,0,1,0),COLOR00FF00;
    主力出货=IF(np.logical_and(控盘<REF(控盘,1),控盘>0),控盘,0)#COLOR00FF00,NODRAW;
    return 无庄控盘,开始控盘,有庄控盘,主力出货
def ZBCD(HIGH,LOW,OPEN,AMOUNT,VOL,CLOSE,N=10):
    '''
    准备抄底
    VAR1赋值:成交额(元)/成交量(手)/7
    VAR2赋值:(3*最高价+最低价+开盘价+2*收盘价)/7
    VAR3赋值:成交额(元)的N日累和/VAR1/7
    VAR4赋值:以成交量(手)/VAR3为权重VAR2的动态移动平均
    输出抄底:(收盘价-VAR4)/VAR4*100,画淡洋红色
    当满足条件-7.0上穿抄底时,在抄底位置画1号图标
    '''
    VAR1=AMOUNT/VOL/7
    VAR2=(3*HIGH+LOW+OPEN+2*CLOSE)/7
    VAR3=SUM(AMOUNT,N)/VAR1/7
    VAR4=DMA(VAR2,VOL/VAR3)
    抄底=(CLOSE-VAR4)/VAR4*100#COLORLIMAGENTA
    #DRAWICON(CROSS(-7.0,抄底),抄底,1)
    return 抄底
def BDZX(HIGH,LOW,CLOSE):
    '''
    波段之星
    VAR2赋值:(最高价+最低价+收盘价*2)/4
    VAR3赋值:VAR2的21日指数移动平均
    VAR4赋值:VAR2的21日估算标准差
    VAR5赋值:((VAR2-VAR3)/VAR4*100+200)/4
    VAR6赋值:(VAR5的5日指数移动平均-25)*1.56
    输出AK: VAR6的2日指数移动平均*1.22
    输出AD1: AK的2日指数移动平均
    输出AJ: 3*AK-2*AD1
    输出AA:100
    输出布林极限:0
    输出CC:80
    输出买进: 如果AK上穿AD1,返回58,否则返回20
    输出卖出: 如果AD1上穿AK,返回58,否则返回20
    '''
    VAR2=(HIGH+LOW+CLOSE*2)/4
    VAR3=EMA(VAR2,21)
    VAR4=STD(VAR2,21)
    VAR5=((VAR2-VAR3)/VAR4*100+200)/4
    VAR6=(EMA(VAR5,5)-25)*1.56
    AK= EMA(VAR6,2)*1.22
    AD1= EMA(AK,2)
    AJ= 3*AK-2*AD1
    AA=100
    BB=0
    CC=80
    买进= IF(CROSS(AK,AD1),58,20)
    卖出= IF(CROSS(AD1,AK),58,20)
    return AK,AD1,AJ,AA,BB,CC,买进,卖出
def LHXJ(HIGH,LOW,CLOSE):
    '''
    猎狐先觉
    VAR1赋值:(收盘价*2+最高价+最低价)/4
    VAR2赋值:VAR1的13日指数移动平均-VAR1的34日指数移动平均
    VAR3赋值:VAR2的5日指数移动平均
    输出主力弃盘: (-2)*(VAR2-VAR3)*3.8
    输出主力控盘: 2*(VAR2-VAR3)*3.8
    '''
    VAR1=(CLOSE*2+HIGH+LOW)/4
    VAR2=EMA(VAR1,13)-EMA(VAR1,34)
    VAR3=EMA(VAR2,5)
    主力弃盘=(-2)*(VAR2-VAR3)*3.8
    主力控盘=2*(VAR2-VAR3)*3.8
    return 主力弃盘,主力控盘
def LYJH(CLOSE,HIGH,LOW,M=80,M1=50):
    '''
    猎鹰歼狐
    VAR1赋值:(36日内最高价的最高值-收盘价)/(36日内最高价的最高值-36日内最低价的最低值)*100
    输出机构做空能量线: VAR1的2日[1日权重]移动平均
    VAR2赋值:(收盘价-9日内最低价的最低值)/(9日内最高价的最高值-9日内最低价的最低值)*100
    输出机构做多能量线: VAR2的5日[1日权重]移动平均-8
    输出LH: M
    输出LH1: M1
    '''
    VAR1=(HHV(HIGH,36)-CLOSE)/(HHV(HIGH,36)-LLV(LOW,36))*100
    机构做空能量线=SMA(VAR1,2,1)
    VAR2=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100
    机构做多能量线=SMA(VAR2,5,1)-8
    LH=M
    LH1=M1
    return 机构做空能量线,机构做多能量线,LH,LH1
def JFZX(OPEN,CLOSE,VOL,N=30):
    '''
    飓风智能中线
    VAR2赋值:如果收阳线,返回成交量(手),否则返回0的N日累和/成交量(手)的N日累和*100
    VAR3赋值:100-如果收阳线,返回成交量(手),否则返回0的N日累和/成交量(手)的N日累和*100
    输出多头力量: VAR2
    输出空头力量: VAR3
    输出多空平衡: 50
    '''
    VAR2=SUM(IF(CLOSE>OPEN,VOL,0),N)/SUM(VOL,N)*100
    VAR3=100-SUM(IF(CLOSE>OPEN,VOL,0),N)/SUM(VOL,N)*100
    多头力量= VAR2
    空头力量= VAR3
    多空平衡= 50
    return 多头力量,空头力量,多空平衡
def CYHT(CLOSE,HIGH,LOW,OPEN):
    '''
    财运亨通
    VAR1赋值:(2*收盘价+最高价+最低价+开盘价)/5
    输出高抛: 80
    VAR2赋值:34日内最低价的最低值
    VAR3赋值:34日内最高价的最高值
    输出SK: (VAR1-VAR2)/(VAR3-VAR2)*100的13日指数移动平均
    输出SD: SK的3日指数移动平均
    输出低吸: 20
    输出强弱分界: 50
    VAR4赋值:如果SK上穿SD,返回40,否则返回22
    VAR5赋值:如果SD上穿SK,返回60,否则返回78
    输出卖出: VAR5
    输出买进: VAR4
    '''
    VAR1=(2*CLOSE+HIGH+LOW+OPEN)/5
    高抛= 80
    VAR2=LLV(LOW,34)
    VAR3=HHV(HIGH,34)
    SK= EMA((VAR1-VAR2)/(VAR3-VAR2)*100,13)
    SD= EMA(SK,3)
    低吸= 20
    强弱分界= 50
    VAR4=IF(CROSS(SK,SD),40,22)
    VAR5=IF(CROSS(SD,SK),60,78)
    卖出= VAR5
    买进= VAR4
    return 高抛,SK,SD,低吸,强弱分界,卖出,买进
def BSQJ(CLOSE):
    '''
    买卖区间
    买线赋值:收盘价的2日指数移动平均
    卖线赋值:收盘价的21日线性回归斜率*20+收盘价的42日指数移动平均
    当满足条件买线>=卖线时,在日期日0日内最高价的最高值和日期日0日内最低价的最低值位置之间画柱状线,宽度为6,0不为0则画空心柱.,COLOR001050
    当满足条件买线<卖线时,在日期日0日内最高价的最高值和日期日0日内最低价的最低值位置之间画柱状线,宽度为6,0不为0则画空心柱.,COLOR404050
    K线
    指导赋值:(收盘价的4日指数移动平均+收盘价的6日指数移动平均+收盘价的12日指数移动平均+收盘价的24日指数移动平均)/4的2日指数移动平均
    界赋值:收盘价的27日简单移动平均
    输出B买:如果指导上穿界ORCROSS(买线,卖线),返回收盘价,否则返回无效数,画洋红色,NODRAW
    输出持仓:如果买线>=卖线,返回收盘价,否则返回无效数,画红色,NODRAW
    输出S卖:如果界上穿指导ORCROSS(卖线,买线),返回收盘价,否则返回无效数,画淡灰色,NODRAW
    输出空仓:如果买线<卖线,返回收盘价,否则返回无效数,画绿色,NODRAW
    当满足条件买线上穿卖线时,在最低价位置画1号图标
    当满足条件卖线上穿买线时,在最高价位置画2号图标
    '''
    C=CLOSE
    买线=EMA(C,2)
    卖线=EMA(SLOPE(C,21)*20+C,42)
    #STICKLINE(买线>=卖线,REFDATE(HHV(H,0),DATE),REFDATE(LLV(L,0),DATE),6,0),COLOR001050
    #STICKLINE(买线<卖线,REFDATE(HHV(H,0),DATE),REFDATE(LLV(L,0),DATE),6,0),COLOR404050;
    #DRAWKLINE(H,O,L,C);
    指导=EMA((EMA(CLOSE,4)+EMA(CLOSE,6)+EMA(CLOSE,12)+EMA(CLOSE,24))/4,2)
    界=MA(CLOSE,27)
    B买=IF(np.logical_or(CROSS(指导,界),CROSS(买线,卖线)),C,None)#COLORMAGENTA,NODRAW;
    持仓=IF(买线>=卖线,C,None)#COLORRED,NODRAW
    S卖=IF(np.logical_or(CROSS(界,指导),CROSS(卖线,买线)),C,None)#COLORLIGRAY,NODRAW
    空仓=IF(买线<卖线,C,None)#COLORGREEN,NODRAW
    #DRAWICON(CROSS(买线,卖线),L,1);
    #DRAWICON(CROSS(卖线,买线),H,2);
    return B买,持仓,S卖,空仓
def CDP_STD(CLOSE, HIGH, LOW):
    '''
    逆势操作
    CH赋值:1日前的最高价
    CL赋值:1日前的最低价
    CC赋值:1日前的收盘价
    输出CDP:(CH+CL+CC)/3
    输出AH:2*CDP+CH-2*CL
    输出NH:CDP+CDP-CL
    输出NL:CDP+CDP-CH
    输出AL:2*CDP-2*CH+CL
    '''
    CH = REF(HIGH, 1)
    CL = REF(LOW, 1)
    CC = REF(CLOSE, 1)
    CDP = (CH + CL + CC) / 3
    AH = 2 * CDP + CH - 2 * CL
    NH = CDP + CDP - CL
    NL = CDP + CDP - CH
    AL = 2 * CDP - 2 * CH + CL
    return CDP, AH, NH, NL, AL
def TBP_STD(HIGH,LOW,CLOSE):
    '''
    趋势平衡点
    APX赋值:(最高价+最低价+收盘价)/3
    TR0赋值:最高价-最低价和最高价-1日前的收盘价的绝对值和最低价-1日前的收盘价的绝对值的较大值的较大值
    MF0赋值:收盘价-2日前的收盘价
    MF1赋值:1日前的MF0
    MF2赋值:2日前的MF0
    DIRECT1赋值:上次MF0>MF1ANDMF0>MF2距今天数
    DIRECT2赋值:上次MF0<MF1ANDMF0<MF2距今天数
    DIRECT0赋值:如果DIRECT1<DIRECT2,返回100,否则返回-100
    输出TBP:1日前的1日前的收盘价+如果DIRECT0>50,返回MF0和MF1的较小值,否则返回MF0和MF1的较大值
    输出多头获利:1日前的如果DIRECT0>50,返回APX*2-最低价,否则返回无效数,NODRAW
    输出多头停损:1日前的如果DIRECT0>50,返回APX-TR0,否则返回无效数,NODRAW
    输出空头回补:1日前的如果DIRECT0<-50,返回APX*2-最高价,否则返回无效数,NODRAW
    输出空头停损:1日前的如果DIRECT0<-50,返回APX+TR0,否则返回无效数,NODRAW
    '''
    H=HIGH
    L=LOW
    C=CLOSE
    APX=(H+L+C)/3
    TR0=MAX(H-L,MAX(ABS(H-REF(C,1)),ABS(L-REF(C,1))))
    MF0=C-REF(C,2)
    MF1=REF(MF0,1)
    MF2=REF(MF0,2)
    DIRECT1=BARSLAST(np.logical_and(MF0>MF1,MF0>MF2))
    DIRECT2=BARSLAST(np.logical_and(MF0<MF1,MF0<MF2))
    DIRECT0=IF(DIRECT1<DIRECT2,100,-100)
    TBP=REF(REF(C,1)+IF(DIRECT0>50,MIN(MF0,MF1),MAX(MF0,MF1)),1)
    多头获利=REF(IF(DIRECT0>50,APX*2-L,None),1)
    多头停损=REF(IF(DIRECT0>50,APX-TR0,None),1)
    空头回补=REF(IF(DIRECT0<-50,APX*2-H,None),1)
    空头停损=REF(IF(DIRECT0<-50,APX+TR0,None),1)
    return TBP,多头获利,多头停损,空头回补,空头停损
#***********************************************
#***********************************************
#****************有空写****************************

源码模块:alpha.py

WorldQuant Alpha 批量函数版

import numpy as np
import pandas as pd
from scipy import stats
from sklearn import preprocessing
from functools import *
from functools import *
def alpha001(data, dependencies=['closePrice','openPrice','turnoverVol'], max_window=7):
    # (-1*CORR(RANK(DELTA(LOG(VOLUME),1)),RANK(((CLOSE-OPEN)/OPEN)),6)
    rank_sizenl = np.log(data['turnoverVol']).diff(1).rank(axis=0, pct=True)
    rank_ret = (data['closePrice'] / data['openPrice']) .rank(axis=0, pct=True)
    rel = rank_sizenl.rolling(window=6,min_periods=6).corr(rank_ret).iloc[-1] * (-1)
    return rel
    
def alpha002(data, dependencies=['closePrice','lowestPrice','highestPrice'], max_window=2):
    # -1*delta(((close-low)-(high-close))/(high-low),1)
    win_ratio = (2*data['closePrice']-data['lowestPrice']-data['highestPrice'])/(data['highestPrice']-data['lowestPrice'])
    return win_ratio.diff(1).iloc[-1] * (-1)

def alpha003(data, dependencies=['closePrice','lowestPrice','highestPrice'], max_window=6):
    # -1*SUM((CLOSE=DELAY(CLOSE,1)?0:CLOSE-(CLOSE>DELAY(CLOSE,1)?MIN(LOW,DELAY(CLOSE,1)):MAX(HIGH,DELAY(CLOSE,1)))),6)
    # \u8fd9\u91ccSUM\u5e94\u8be5\u4e3aTSSUM
    alpha = data['closePrice']
    condition2 = data['closePrice'].diff(periods=1) > 0.0
    condition3 = data['closePrice'].diff(periods=1) < 0.0
    alpha[condition2] = data['closePrice'][condition2] - np.minimum(data['closePrice'][condition2].shift(1).replace(np.NaN,10000), data['lowestPrice'][condition2])
    alpha[condition3] = data['closePrice'][condition3] - np.maximum(data['closePrice'][condition3].shift(1).replace(np.NaN,0), data['highestPrice'][condition3])
    return alpha.sum(axis=0) * (-1)

def alpha004(data, dependencies=['closePrice','turnoverVol'], max_window=20):
    # (((SUM(CLOSE,8)/8)+STD(CLOSE,8))<(SUM(CLOSE,2)/2))
    # ?-1:(SUM(CLOSE,2)/2<(SUM(CLOSE,8)/8-STD(CLOSE,8))
    #     ?1:(1<=(VOLUME/MEAN(VOLUME,20))
    #       ?1:-1))
#STD(CLOSE,8):过去8天的收盘价的标准差;VOLUME:成交量;MEAN(VOLUME,20);过去20天的均值
    if MEAN(data['closePrice'],8)+STD(data['closePrice'],8)<MEAN(data['closePrice'],2):return -1
    elif MEAN(data['closePrice'],2)<MEAN(data['closePrice'],8)-STD(data['closePrice'],8):return 1
    elif 1<=data['turnoverVol'].iloc[19]/MEAN(data['turnoverVol'],20):return 1
    else: return -1

def alpha005(data, dependencies=['turnoverVol', 'highestPrice'], max_window=13):
    # -1*TSMAX(CORR(TSRANK(VOLUME,5),TSRANK(HIGH,5),5),3)
    ts_volume = data['turnoverVol'].rolling(window=5,min_periods=5).apply(lambda x: stats.rankdata(x)[-1]/5.0)
    ts_high = data['highestPrice'].rolling(window=5,min_periods=5).apply(lambda x: stats.rankdata(x)[-1]/5.0)
    corr_ts = ts_volume.rolling(window=5, min_periods=5).corr(ts_high)
    alpha = corr_ts.iloc[-3:].max(axis=0) * (-1)
    return alpha

def alpha006(data, dependencies=['openPrice', 'highestPrice'], max_window=5):
    # -1*RANK(SIGN(DELTA(OPEN*0.85+HIGH*0.15,4)))
    # \u6ce8:\u53d6\u503c\u6392\u5e8f\u6709\u968f\u673a\u6027
    return sorted(np.sign(DELTA(data['openPrice']*0.85+data['highestPrice']*0.15,4)))[0]*-1


def alpha007(data, dependencies=['turnoverVol', 'turnoverValue', 'closePrice'], max_window=4):
    # (RANK(MAX(VWAP-CLOSE,3))+RANK(MIN(VWAP-CLOSE,3)))*RANK(DELTA(VOLUME,3))
    # \u611f\u89c9MAX\u5e94\u8be5\u4e3aTSMAX
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = (vwap - data['closePrice']).rolling(window=3,min_periods=3).max().rank(axis=0, pct=True)
    part2 = (vwap - data['closePrice']).rolling(window=3,min_periods=3).min().rank(axis=0, pct=True)
    part3 = data['turnoverVol'].diff(3).rank(axis=0, pct=True).iloc[-1]
    alpha = (part1 + part2) * part3
    return alpha.iloc[-1]

def alpha008(data, dependencies=['turnoverVol', 'turnoverValue', 'highestPrice', 'lowestPrice'], max_window=5):
    # -1*RANK(DELTA((HIGH+LOW)/10+VWAP*0.8,4))
    # \u53d7\u80a1\u4ef7\u5355\u4ef7\u5f71\u54cd,\u53cd\u8f6c
    vwap = data['turnoverValue'] / data['turnoverVol']
    ma_price = data['highestPrice']*0.1 + data['lowestPrice']*0.1 + vwap*0.8
    alpha = ma_price.diff(4).iloc[-1] * (-1)
    return alpha

def alpha009(data, dependencies=['highestPrice', 'lowestPrice', 'turnoverVol'], max_window=8):
    # SMA(((HIGH+LOW)/2-(DELAY(HIGH,1)+DELAY(LOW,1))/2)*(HIGH-LOW)/VOLUME,7,2)
    part1 = (data['highestPrice']+data['lowestPrice'])*0.5-(data['highestPrice'].shift(1)+data['lowestPrice'].shift(1))*0.5
    part2 = part1 * (data['highestPrice']-data['lowestPrice']) / data['turnoverVol']
    alpha = part2.ewm(adjust=False, alpha=float(2)/7, min_periods=0, ignore_na=False).mean().iloc[-1]
    return alpha

def alpha010(data, dependencies=['closePrice'], max_window=25):
    # RANK(MAX(((RET<0)?STD(RET,20):CLOSE)^2,5))
    # \u6ca1\u6cd5\u89e3\u91ca,\u611f\u89c9MAX\u5e94\u8be5\u4e3aTSMAX
    ret = data['closePrice'].pct_change(periods=1)
    part1 = ret.rolling(window=20, min_periods=20).std()
    condition = ret >= 0.0
    part1[condition] = data['closePrice'][condition]
    alpha = (part1 ** 2).rolling(window=5,min_periods=5).max().rank(axis=0, pct=True)
    return alpha.iloc[-1]
    
def alpha011(data, dependencies=['closePrice','lowestPrice','highestPrice','turnoverVol'], max_window=6):
    # SUM(((CLOSE-LOW)-(HIGH-CLOSE))./(HIGH-LOW).*VOLUME,6)
    # \u8fd16\u5929\u83b7\u5229\u76d8\u6bd4\u4f8b
    return ((2*data['closePrice']-data['lowestPrice']-data['highestPrice'])/(data['highestPrice']-data['lowestPrice'])*data['turnoverVol']).sum(axis=0) * (-1)

def alpha012(data, dependencies=['openPrice','closePrice','turnoverVol', 'turnoverValue'], max_window=10):
    # RANK(OPEN-MA(VWAP,10))*RANK(ABS(CLOSE-VWAP))*(-1)
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = (data['openPrice']-vwap.rolling(window=10,center=False).mean()).rank(axis=0, pct=True).iloc[-1]
    part2 = abs(data['closePrice']-vwap).rank(axis=0, pct=True).iloc[-1]
    alpha = part1 * part2 * (-1)
    return alpha

def alpha013(data, dependencies=['highestPrice','lowestPrice','turnoverVol', 'turnoverValue'], max_window=1):
    # ((HIGH*LOW)^0.5)-VWAP
    # \u8981\u6ce8\u610fVWAP/price\u662f\u5426\u590d\u6743
    vwap = data['turnoverValue'] / data['turnoverVol']
    alpha = np.sqrt(data['highestPrice'] * data['lowestPrice']) - vwap
    return alpha.iloc[-1]

def alpha014(data, dependencies=['closePrice'], max_window=6):
    # CLOSE-DELAY(CLOSE,5)
    # \u4e0e\u80a1\u4ef7\u76f8\u5173\uff0c\u5229\u597d\u8305\u53f0
    return data['closePrice'].diff(5).iloc[-1]

def alpha015(data, dependencies=['openPrice', 'closePrice'], max_window=2):
    # OPEN/DELAY(CLOSE,1)-1
    # \u8df3\u7a7a\u9ad8\u5f00/\u4f4e\u5f00
    return (data['openPrice']/data['closePrice'].shift(1)-1.0).iloc[-1]

def alpha016(data, dependencies=['turnoverVol', 'turnoverValue'], max_window=10):
    # (-1*TSMAX(RANK(CORR(RANK(VOLUME),RANK(VWAP),5)),5))
    # \u611f\u89c9\u5176\u4e2d\u6709\u4e2aTSRANK
    vwap = data['turnoverValue'] / data['turnoverVol']
    corr_vol_vwap = data['turnoverVol'].rank(axis=0, pct=True).rolling(window=5,min_periods=5).corr(vwap.rank(axis=0, pct=True))
    alpha = corr_vol_vwap.rolling(window=5,min_periods=5).apply(lambda x: stats.rankdata(x)[-1]/5.0)
    alpha = alpha.iloc[-5:].max(axis=0) * (-1)
    return alpha

def alpha017(data, dependencies=['closePrice', 'turnoverVol', 'turnoverValue'], max_window=16):
    # RANK(VWAP-MAX(VWAP,15))^DELTA(CLOSE,5)
    vwap = data['turnoverValue'] / data['turnoverVol']
    delta_price = data['closePrice'].diff(5).iloc[-1]
    alpha = (vwap-vwap.rolling(window=15,min_periods=15).max()).rank(axis=0, pct=True).iloc[-1] ** delta_price
    return alpha

def alpha018(data, dependencies=['closePrice'], max_window=6):
    # CLOSE/DELAY(CLOSE,5)
    # \u8fd15\u65e5\u6da8\u5e45, REVS5
    return (data['closePrice'] / data['closePrice'].shift(5)).iloc[-1]

def alpha019(data, dependencies=['closePrice'], max_window=6):
    # (CLOSE<DELAY(CLOSE,5)?(CLOSE/DELAY(CLOSE,5)-1):(CLOSE=DELAY(CLOSE,5)?0:(1-DELAY(CLOSE,5)/CLOSE)))
    # \u7c7b\u4f3c\u4e8e\u8fd1\u4e94\u65e5\u6da8\u5e45
    condition1 = data['closePrice'] <= data['closePrice'].shift(5)
    alpha = data['closePrice']
    alpha[condition1] = data['closePrice'].pct_change(periods=5)[condition1]
    alpha[~condition1] = -data['closePrice'].pct_change(periods=5)[~condition1]
    return alpha.iloc[-1]

def alpha020(data, dependencies=['closePrice'], max_window=7):
    # (CLOSE/DELAY(CLOSE,6)-1)*100
    # \u8fd16\u65e5\u6da8\u5e45
    return (data['closePrice'].pct_change(periods=6) * 100.0).iloc[-1]

def alpha021(data, dependencies=['closePrice'], max_window=12):
    # REGBETA(MEAN(CLOSE,6),SEQUENCE(6))
    a=[MEAN(list(data['closePrice'])[:-x],6) for x in range(1,7)]
    return REGBETA(a,SEQUENCE(6),6)

def alpha022(data, dependencies=['closePrice'], max_window=21):
    # SMEAN((CLOSE/MEAN(CLOSE,6)-1-DELAY(CLOSE/MEAN(CLOSE,6)-1,3)),12,1)
    # \u731cSMEAN\u662fSMA
    ratio = data['closePrice'] / data['closePrice'].rolling(window=6,min_periods=6).mean() - 1.0
    alpha = ratio.diff(3).ewm(adjust=False, alpha=float(1)/12, min_periods=12, ignore_na=False).mean().iloc[-1]
    return alpha
    
def alpha023(data, dependencies=['closePrice'], max_window=40):
    # SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1) /
    # (SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)+SMA((CLOSE<=DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1))
    # *100
    prc_std = data['closePrice'].rolling(window=20, min_periods=20).std()
    condition1 = data['closePrice'] > data['closePrice'].shift(1)
    part1 = prc_std.copy(deep=True)
    part2 = prc_std.copy(deep=True)
    part1[~condition1] = 0.0
    part2[condition1] = 0.0
    alpha = part1.ewm(adjust=False, alpha=float(1)/20, min_periods=20, ignore_na=False).mean() / (part1.ewm(adjust=False, alpha=float(1)/20, min_periods=20, ignore_na=False).mean() + part2.ewm(adjust=False, alpha=float(1)/20, min_periods=20, ignore_na=False).mean()) * 100
    return alpha.iloc[-1]

def alpha024(data, dependencies=['closePrice'], max_window=10):
    # SMA(CLOSE-DELAY(CLOSE,5),5,1)
    return data['closePrice'].diff(5).ewm(adjust=False, alpha=float(1)/5, min_periods=5, ignore_na=False).mean().iloc[-1]

def alpha025(data, dependencies=['closePrice', 'turnoverVol'], max_window=251):
    # (-1*RANK(DELTA(CLOSE,7)*(1-RANK(DECAYLINEAR(VOLUME/MEAN(VOLUME,20),9)))))*(1+RANK(SUM(RET,250)))
    w = np.array(range(1, 10))
    ret = data['closePrice'].pct_change(periods=1)
    part1 = data['closePrice'].diff(7)
    part2 = data['turnoverVol']/(data['turnoverVol'].rolling(window=20,min_periods=20).mean())
    part2 = 1.0 - part2.rolling(window=9, min_periods=9).apply(lambda x: np.dot(x, w)).rank(axis=0, pct=True)
    part3 = 1.0 + ret.rolling(window=250, min_periods=250).sum().rank(axis=0, pct=True)
    alpha = (-1.0) * (part1 * part2).rank(axis=0, pct=True) * part3
    return alpha.iloc[-1]

def alpha026(data, dependencies=['closePrice', 'turnoverValue', 'turnoverVol'], max_window=235):
    # (SUM(CLOSE,7)/7-CLOSE+CORR(VWAP,DELAY(CLOSE,5),230))
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = data['closePrice'].rolling(window=7, min_periods=7).mean() - data['closePrice']
    part2 = vwap.rolling(window=230, min_periods=230).corr(data['closePrice'].shift(5))
    return (part1 + part2).iloc[-1]

def alpha027(data, dependencies=['closePrice'], max_window=18):
    # WMA((CLOSE-DELTA(CLOSE,3))/DELAY(CLOSE,3)*100+(CLOSE-DELAY(CLOSE,6))/DELAY(CLOSE,6)*100,12)
    part1 = data['closePrice'].pct_change(periods=3) * 100.0 + data['closePrice'].pct_change(periods=6) * 100.0
    # w = preprocessing.normalize(np.array([i for i in range(1, 13)]),norm='l1',axis=1).reshape(-1)
    w=np.array(range(1,13))
    alpha = part1.rolling(window=12, min_periods=12).apply(lambda x: np.dot(x, w))
    return alpha.iloc[-1]

def alpha028(data, dependencies=['KDJ_J'], max_window=13):
    # 3*SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1)
    # -2*SMA(SMA((CLOSE-TSMIN(LOW,9))/( TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1),3,1)
    # \u5c31\u662fKDJ_J
    part1 =data['closePrice']- data['closePrice'].rolling(window=9, min_periods=9).min()
    part2=data['highestPrice'].rolling(window=9, min_periods=9).max()-data['lowestPrice'].rolling(window=9, min_periods=9).min()
    part3= 3*SMA(list(part1/part2*100)[-3:],3,1)
    part4=[SMA(list(part1/part2*100)[-5:-2],3,1),SMA(list(part1/part2*100)[-4:-1],3,1),SMA(list(part1/part2*100)[-3:],3,1)]
    part5=part3-2*SMA(part4,3,1)
    return part5

def alpha029(data, dependencies=['closePrice', 'turnoverVol'], max_window=7):
    # (CLOSE-DELAY(CLOSE,6))/DELAY(CLOSE,6)*VOLUME
    # \u83b7\u5229\u6210\u4ea4\u91cf
    return (data['closePrice'].pct_change(periods=6)*data['turnoverVol']).iloc[-1]

def alpha030(data, dependencies=['closePrice', 'PB', 'MktValue'], max_window=81):
    # WMA((REGRESI(RET,MKT,SMB,HML,60))^2,20)
    # \u5373\u7279\u8d28\u6027\u6536\u76ca
    # MKT \u4e3a\u5e02\u503c\u52a0\u6743\u7684\u5e02\u573a\u5e73\u5747\u6536\u76ca\u7387\uff0c
    # SMB \u4e3a\u5e02\u503c\u6700\u5c0f\u768430%\u7684\u80a1\u7968\u7684\u5e73\u5747\u6536\u76ca\u51cf\u53bb\u5e02\u503c\u6700\u5927\u768430%\u7684\u80a1\u7968\u7684\u5e73\u5747\u6536\u76ca\uff0c
    # HML \u4e3aPB\u6700\u9ad8\u768430%\u7684\u80a1\u7968\u7684\u5e73\u5747\u6536\u76ca\u51cf\u53bbPB\u6700\u4f4e\u768430%\u7684\u80a1\u7968\u7684\u5e73\u5747\u6536\u76ca
    ret = data['closePrice'].pct_change(periods=1).fillna(0.0)
    mkt_ret = (ret * data['MktValue']).sum(axis=1) / data['MktValue'].sum(axis=1)
    me30 = (data['MktValue'].T <= data['MktValue'].quantile(0.3, axis=1)).T
    me70 = (data['MktValue'].T >= data['MktValue'].quantile(0.7, axis=1)).T
    pb30 = (data['PB'].T <= data['PB'].quantile(0.3, axis=1)).T
    pb70 = (data['PB'].T >= data['PB'].quantile(0.7, axis=1)).T
    smb_ret = ret[me30].mean(axis=1, skipna=True) - ret[me70].mean(axis=1, skipna=True)
    hml_ret = ret[pb70].mean(axis=1, skipna=True) - ret[pb30].mean(axis=1, skipna=True)
    xs = pd.concat([mkt_ret, smb_ret, hml_ret], axis=1)
    idxs = pd.Series(data=range(len(data['closePrice'].index)), index=data['closePrice'].index)

    def multi_var_linregress(idx, y, xs):
        X = xs.iloc[idx]
        Y = y.iloc[idx]
        X = sm.add_constant(X)
        try:
            res = np.array(sm.OLS(Y, X).fit().resid)
        except Exception as e:
            return np.nan
        return res[-1]

    # print(xs.tail(5), ret.tail(5))
    residual = [idxs.rolling(window=60, min_periods=60).apply(lambda x: multi_var_linregress(x, ret[col], xs)) for col in ret.columns]
    residual = pd.concat(residual, axis=1)
    residual.columns = ret.columns

    w = preprocessing.normalize(np.array([i for i in range(1, 21)]), norm='l1', axis=1).reshape(-1)
    alpha = (residual ** 2).rolling(window=20, min_periods=20).apply(lambda x: np.dot(x, w))
    return alpha.iloc[-1]

def alpha031(data, dependencies=['closePrice'], max_window=12):
    # (CLOSE-MEAN(CLOSE,12))/MEAN(CLOSE,12)*100
    return ((data['closePrice']/data['closePrice'].rolling(window=12,min_periods=12).mean()-1.0)*100).iloc[-1]

def alpha032(data, dependencies=['highestPrice', 'turnoverVol'], max_window=6):
    # (-1*SUM(RANK(CORR(RANK(HIGH),RANK(VOLUME),3)),3))
    # \u91cf\u4ef7\u9f50\u5347/\u53cd\u8f6c
    part1 = data['highestPrice'].rank(axis=0, pct=True).rolling(window=3, min_periods=3).corr(data['turnoverVol'].rank(axis=0, pct=True))
    alpha = part1.rank(axis=0, pct=True).iloc[-3:].sum(axis=0) * (-1)
    return alpha

def alpha033(data, dependencies=['lowestPrice', 'closePrice', 'turnoverVol'], max_window=241):
    # (-1*TSMIN(LOW,5)+DELAY(TSMIN(LOW,5),5))*RANK((SUM(RET,240)-SUM(RET,20))/220)*TSRANK(VOLUME,5)
    part1 = data['lowestPrice'].rolling(window=5, min_periods=5).min().diff(5) * (-1)
    ret = data['closePrice'].pct_change(periods=1)
    part2 = ((ret.rolling(window=240, min_periods=240).sum() - ret.rolling(window=20, min_periods=20).sum()) / 220).rank(axis=0, pct=True)
    part3 = data['turnoverVol'].iloc[-5:].rank(axis=0, pct=True)
    alpha = part1.iloc[-1] * part2.iloc[-1] * part3.iloc[-1]
    return alpha

def alpha034(data, dependencies=['closePrice'], max_window=12):
    # MEAN(CLOSE,12)/CLOSE
    return (data['closePrice'].rolling(window=12, min_periods=12).mean() / data['closePrice']).iloc[-1]

def alpha035(data, dependencies=['openPrice', 'closePrice', 'turnoverVol'], max_window=24):
    # (MIN(RANK(DECAYLINEAR(DELTA(OPEN,1),15)),RANK(DECAYLINEAR(CORR(VOLUME,OPEN*0.65+CLOSE*0.35,17),7)))*-1)
    # \u731c\u540e\u4e00\u9879OPEN\u4e3aCLOSE
    w7 =np.array(range(1, 8)).reshape(-1)
    w15 = np.array(range(1, 16)).reshape(-1)
    part1 = data['openPrice'].diff(periods=1).rolling(window=15, min_periods=15).apply(lambda x: np.dot(x, w15)).rank(axis=0, pct=True)
    part2 = (data['openPrice']*0.65+data['closePrice']*0.35).rolling(window=17, min_periods=17).corr(data['turnoverVol']).rolling(window=7, min_periods=7).apply(lambda x: np.dot(x, w7)).rank(axis=0, pct=True)
    alpha = np.minimum(part1, part2).iloc[-1] * (-1)
    return alpha

def alpha036(data, dependencies=['turnoverValue', 'turnoverVol'], max_window=9):
    # RANK(SUM(CORR(RANK(VOLUME),RANK(VWAP),6),2))
    # \u91cf\u4ef7\u9f50\u5347, TSSUM
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = data['turnoverVol'].rank(axis=0, pct=True).rolling(window=6,min_periods=6).corr(vwap.rank(axis=0, pct=True))
    alpha = part1.rolling(window=2, min_periods=2).sum().rank(axis=0, pct=True).iloc[-1]
    return alpha

def alpha037(data, dependencies=['openPrice', 'closePrice'], max_window=16):
    # (-1*RANK(SUM(OPEN,5)*SUM(RET,5)-DELAY(SUM(OPEN,5)*SUM(RET,5),10)))
    part1 = data['openPrice'].rolling(window=5, min_periods=5).sum() * (data['closePrice'].pct_change(periods=1).rolling(window=5, min_periods=5).sum())
    alpha = part1.diff(periods=10).iloc[-1] * (-1)
    return alpha
    
def alpha038(data, dependencies=['highestPrice'], max_window=20):
    # ((SUM(HIGH,20)/20)<HIGH)?(-1*DELTA(HIGH,2)):0
    # \u4e0e\u80a1\u4ef7\u76f8\u5173\uff0c\u5229\u597d\u8305\u53f0
    condition = data['highestPrice'].rolling(window=20, min_periods=20).mean() < data['highestPrice']
    alpha = data['highestPrice'].diff(periods=2) * (-1)
    alpha[~condition] = 0.0
    return alpha.iloc[-1]

def alpha039(data, dependencies=['closePrice', 'openPrice', 'turnoverValue', 'turnoverVol'], max_window=243):
    # (RANK(DECAYLINEAR(DELTA(CLOSE,2),8))-RANK(DECAYLINEAR(CORR(VWAP*0.3+OPEN*0.7,SUM(MEAN(VOLUME,180),37),14),12)))*-1
    w8 =np.array(range(1, 9)).reshape(-1)
    w12 = np.array(range(1, 13)).reshape(-1)
    parta = data['turnoverValue'] / data['turnoverVol'] * 0.3 + data['openPrice'] * 0.7
    partb = data['turnoverVol'].rolling(window=180, min_periods=180).mean().rolling(window=37, min_periods=37).sum()
    part1 = data['closePrice'].diff(periods=2).rolling(window=8, min_periods=8).apply(lambda x: np.dot(x, w8)).rank(axis=0,pct=True)
    part2 = parta.rolling(window=14, min_periods=14).corr(partb).rolling(window=12, min_periods=12).apply(lambda x: np.dot(x, w12)).rank(axis=0, pct=True)
    return (part1 - part2).iloc[-1] * (-1)

def alpha040(data, dependencies=['VR','turnoverVol'], max_window=27):
    # SUM(CLOSE>DELAY(CLOSE,1)?VOLUME:0,26)/SUM(CLOSE<=DELAY(CLOSE,1)?VOLUME:0,26)*100
    # \u5373VR\u6280\u672f\u6307\u6807
    part1=((data['closePrice'].diff(periods=1)>0)*data['turnoverVol']).sum()
    part2=((data['closePrice'].diff(periods=1)<=0)*data['turnoverVol']).sum()
    return part1/part2*100


def alpha041(data, dependencies=['turnoverValue', 'turnoverVol'], max_window=9):
    # RANK(MAX(DELTA(VWAP,3),5))*-1
    return (data['turnoverValue'] / data['turnoverVol']).diff(periods=3).rolling(window=5, min_periods=5).max().rank(axis=0, pct=True).iloc[-1] * (-1)

def alpha042(data, dependencies=['highestPrice', 'turnoverVol'], max_window=10):
    # (-1*RANK(STD(HIGH,10)))*CORR(HIGH,VOLUME,10)
    # \u4ef7\u7a33/\u91cf\u4ef7\u9f50\u5347
    part1 = data['highestPrice'].rolling(window=10,min_periods=10).std().rank(axis=0,pct=True) * (-1)
    part2 = data['highestPrice'].rolling(window=10,min_periods=10).corr(data['turnoverVol'])
    return (part1 * part2).iloc[-1]

def alpha043(data, dependencies=['OBV6'], max_window=7):
    # (SUM(CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0),6))
    # \u5373OBV6\u6307\u6807
    part1=((data['closePrice'].diff(periods=1)>0)*data['turnoverVol']).sum()
    part2=((data['closePrice'].diff(periods=1)<0)*-data['turnoverVol']).sum()
    return part1+part2

def alpha044(data, dependencies=['turnoverValue', 'turnoverVol', 'lowestPrice'], max_window=29):
    # (TSRANK(DECAYLINEAR(CORR(LOW,MEAN(VOLUME,10),7),6),4)+TSRANK(DECAYLINEAR(DELTA(VWAP,3),10),15))
    w10 = np.array(range(1, 11)).reshape(-1)
    w6 = np.array(range(1, 7)).reshape(-1)
    part1 = (data['turnoverVol'].rolling(window=10,min_periods=10).mean().rolling(window=7, min_periods=7).corr(data['lowestPrice'])).rolling(window=6,min_periods=6).apply(lambda x: np.dot(x, w6))
    part1 = part1.iloc[-4:].rank(axis=0, pct=True)
    part2 = (data['turnoverValue'] / data['turnoverVol']).diff(periods=3).rolling(window=10,min_periods=10).apply(lambda x: np.dot(x, w10))
    part2 = part2.iloc[-15:].rank(axis=0, pct=True)
    return (part1 + part2).iloc[-1]

def alpha045(data, dependencies=['openPrice', 'closePrice', 'turnoverValue', 'turnoverVol'], max_window=165):
    # (RANK(DELTA(CLOSE*0.6+OPEN*0.4,1))*RANK(CORR(VWAP,MEAN(VOLUME,150),15)))
    part1 = (data['closePrice'] * 0.6 + data['openPrice'] * 0.4).diff(periods=1).rank(axis=0,pct=True)
    part2 = ((data['turnoverValue']/data['turnoverVol']).rolling(window=15,min_periods=15).corr(data['turnoverVol'].rolling(window=150,min_periods=150).mean())).rank(axis=0,pct=True)
    return (part1 * part2).iloc[-1]

def alpha046(data, dependencies=['BBIC'], max_window=24):
    # (MEAN(CLOSE,3)+MEAN(CLOSE,6)+MEAN(CLOSE,12)+MEAN(CLOSE,24))/(4*CLOSE)
    # \u5373BBIC\u6280\u672f\u6307\u6807
    part1=[3,6,12,24]
    part2=[data['closePrice'].rolling(window=x,min_periods=x).mean().iloc[-1] for x in part1]
    return sum(part2)/data['closePrice'].iloc[-1]*4

def alpha047(data, dependencies=['closePrice', 'lowestPrice', 'highestPrice'], max_window=15):
    # SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,9,1)
    # RSV\u6280\u672f\u6307\u6807\u53d8\u79cd
    part1 = (data['highestPrice'].rolling(window=6,min_periods=6).max()-data['closePrice']) /  (data['highestPrice'].rolling(window=6,min_periods=6).max()- data['lowestPrice'].rolling(window=6,min_periods=6).min()) * 100
    alpha = part1.ewm(adjust=False, alpha=float(1)/9, min_periods=0, ignore_na=False).mean().iloc[-1]
    return alpha

def alpha048(data, dependencies=['closePrice', 'turnoverVol'], max_window=20):
    # -1*RANK(SIGN(CLOSE-DELAY(CLOSE,1))+SIGN(DELAY(CLOSE,1)-DELAY(CLOSE,2))+SIGN(DELAY(CLOSE,2)-DELAY(CLOSE,3)))*SUM(VOLUME,5)/SUM(VOLUME,20)
    # \u4e0b\u8dcc\u7f29\u91cf
    diff1 = data['closePrice'].diff(1)
    part1 = (np.sign(diff1) + np.sign(diff1.shift(1)) + np.sign(diff1.shift(2))).rank(axis=0, pct=True)
    part2 = data['turnoverVol'].rolling(window=5, min_periods=5).sum() / data['turnoverVol'].rolling(window=20, min_periods=20).sum()
    return (part1 * part2).iloc[-1] * (-1)

def alpha049(data, dependencies=['highestPrice', 'lowestPrice'], max_window=13):
    # SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
    # (SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)+
    # SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
    condition1 = (data['highestPrice'] + data['lowestPrice']) >= (data['highestPrice'] + data['lowestPrice']).shift(1)
    condition2 = (data['highestPrice'] + data['lowestPrice']) <= (data['highestPrice'] + data['lowestPrice']).shift(1)
    part1 = data['highestPrice']
    part2 = data['highestPrice']
    part1[~condition1] = np.maximum(abs(data['highestPrice'].diff(1)[~condition1]), abs(data['lowestPrice'].diff(1)[~condition1]))
    part2[~condition2] = np.maximum(abs(data['highestPrice'].diff(1)[~condition2]), abs(data['lowestPrice'].diff(1)[~condition2]))
    alpha = part1.rolling(window=12,min_periods=12).sum() / (part1.rolling(window=12,min_periods=12).sum() + part2.rolling(window=12,min_periods=12).sum())
    return alpha.iloc[-1]

def alpha050(data, dependencies=['highestPrice', 'lowestPrice'], max_window=13):
    # SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
    # (SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)
    # +SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
    # -SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)/
    # (SUM(HIGH+LOW>=DELAY(HIGH,1)+DELAY(LOW,1)?0: MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12)
    # +SUM(HIGH+LOW<=DELAY(HIGH,1)+DELAY(LOW,1)?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1))),12))
    condition1 = (data['highestPrice'] + data['lowestPrice']) >= (data['highestPrice'] + data['lowestPrice']).shift(1)
    condition2 = (data['highestPrice'] + data['lowestPrice']) <= (data['highestPrice'] + data['lowestPrice']).shift(1)
    part = np.maximum(abs(data['highestPrice'].diff(1)), abs(data['lowestPrice'].diff(1)))
    a=(part*condition2).sum()
    b=(part*condition1).sum()
    return a/(a+b)-b/(a+b)

def alpha051(data, dependencies=['highestPrice', 'lowestPrice'], max_window=13):
    # SUM(((HIGH+LOW)<=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12)/
    # (SUM(((HIGH+LOW)<=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12)
    # +SUM(((HIGH+LOW)>=(DELAY(HIGH,1)+DELAY(LOW,1))?0:MAX(ABS(HIGH-DELAY(HIGH,1)),ABS(LOW-DELAY(LOW,1)))),12))
    condition1 = (data['highestPrice'] + data['lowestPrice']) <= (data['highestPrice'] + data['lowestPrice']).shift(1)
    condition2 = (data['highestPrice'] + data['lowestPrice']) >= (data['highestPrice'] + data['lowestPrice']).shift(1)
    part1 = data['highestPrice']
    part2 = data['highestPrice']
    part1[~condition1] = np.maximum(abs(data['highestPrice'].diff(1)[~condition1]), abs(data['lowestPrice'].diff(1)[~condition1]))
    part2[~condition2] = np.maximum(abs(data['highestPrice'].diff(1)[~condition2]), abs(data['lowestPrice'].diff(1)[~condition2]))
    alpha = part1.rolling(window=12,min_periods=12).sum() / (part1.rolling(window=12,min_periods=12).sum() + part2.rolling(window=12,min_periods=12).sum())
    return alpha.iloc[-1]

def alpha052(data, dependencies=['highestPrice', 'lowestPrice', 'closePrice'], max_window=27):
    # SUM(MAX(0,HIGH-DELAY((HIGH+LOW+CLOSE)/3,1)),26)/SUM(MAX(0,DELAY((HIGH+LOW+CLOSE)/3,1)-L),26)*100
    ma = (data['highestPrice'] + data['lowestPrice'] + data['closePrice']) / 3.0
    part1 = (np.maximum(0.0, (data['highestPrice'] - ma.shift(1)))).rolling(window=26, min_periods=26).sum()
    part2 = (np.maximum(0.0, (ma.shift(1) - data['lowestPrice']))).rolling(window=26, min_periods=26).sum()
    return (part1 / part2 * 100.0).iloc[-1]

def alpha053(data, dependencies=['closePrice'], max_window=13):
    # COUNT(CLOSE>DELAY(CLOSE,1),12)/12*100
    return ((data['closePrice'].diff(1) > 0.0).rolling(window=12, min_periods=12).sum() / 12.0 * 100).iloc[-1]

def alpha054(data, dependencies=['closePrice', 'openPrice'], max_window=10):
    # (-1*RANK(STD(ABS(CLOSE-OPEN))+CLOSE-OPEN+CORR(CLOSE,OPEN,10)))
    # \u6ce8\uff0c\u8fd9\u91ccSTD\u6ca1\u6709\u6307\u660e\u5468\u671f
    part1 = abs(data['closePrice']-data['openPrice']).rolling(window=10, min_periods=10).std() + data['closePrice'] - data['openPrice'] + data['closePrice'].rolling(window=10, min_periods=10).corr(data['openPrice'])
    return part1.rank(axis=0, pct=True).iloc[-1] * (-1)

def alpha055(data, dependencies=['openPrice', 'lowestPrice', 'closePrice', 'highestPrice'], max_window=21):
    # SUM(16*(CLOSE+(CLOSE-OPEN)/2-DELAY(OPEN,1))/
    # ((ABS(HIGH-DELAY(CLOSE,1))>ABS(LOW-DELAY(CLOSE,1)) & ABS(HIGH-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) ? 
    # ABS(HIGH-DELAY(CLOSE,1))+ABS(LOW-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
    # (ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) & ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(CLOSE,1)) ?
    # ABS(LOW-DELAY(CLOSE,1))+ABS(HIGH-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
    # ABS(HIGH-DELAY(LOW,1))+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4)))
    # *MAX(ABS(HIGH-DELAY(CLOSE,1)),ABS(LOW-DELAY(CLOSE,1))),20)
    part1 = data['closePrice'] * 1.5 - data['openPrice'] * 0.5 - data['openPrice'].shift(1)
    part2 = abs(data['highestPrice']-data['closePrice'].shift(1)) + abs(data['lowestPrice']-data['closePrice'].shift(1)) / 2.0 + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    condition1 = np.logical_and(abs(data['highestPrice']-data['closePrice'].shift(1)) > abs(data['lowestPrice']-data['closePrice'].shift(1)), 
                               abs(data['highestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['lowestPrice'].shift(1)))
    condition2 = np.logical_and(abs(data['lowestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['lowestPrice'].shift(1)), 
                               abs(data['lowestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['closePrice'].shift(1)))
    part2[~condition1 & condition2] = abs(data['lowestPrice']-data['closePrice'].shift(1)) + abs(data['highestPrice']-data['closePrice'].shift(1)) / 2.0 + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    part2[~condition1 & ~condition2] = abs(data['highestPrice']-data['lowestPrice'].shift(1)) + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    part3 = np.maximum(abs(data['highestPrice']-data['closePrice'].shift(1)), abs(data['lowestPrice']-data['closePrice'].shift(1)))
    alpha = (part1 / part2 * part3 * 16.0).rolling(window=20, min_periods=20).sum().iloc[-1]
    return alpha

def alpha056(data, dependencies=['openPrice', 'highestPrice', 'lowestPrice', 'turnoverVol'], max_window=73):
    # RANK(OPEN-TSMIN(OPEN,12))<RANK(RANK(CORR(SUM((HIGH +LOW)/2,19),SUM(MEAN(VOLUME,40),19),13))^5)
    # \u8fd9\u91cc\u5c31\u4f1a\u6709\u968f\u673a\u6027,0/1
    part1 = (data['openPrice'] - data['openPrice'].rolling(window=12, min_periods=12).min()).rank(axis=0, pct=True)
    t1 = (data['highestPrice']*0.5+data['lowestPrice']*0.5).rolling(window=19, min_periods=19).sum()
    t2 = data['turnoverVol'].rolling(window=40,min_periods=40).mean().rolling(window=19, min_periods=19).sum()
    part2 = ((t1.rolling(window=13, min_periods=13).corr(t2).rank(axis=0, pct=True)) ** 5).rank(axis=0, pct=True)
    return (part2-part1).iloc[-1]

def alpha057(data, dependencies=['KDJ_K'], max_window=11):
    # SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1)
    # KDJ_K
    part1 =data['closePrice']- data['closePrice'].rolling(window=9, min_periods=9).min()
    part2=data['highestPrice'].rolling(window=9, min_periods=9).max()-data['lowestPrice'].rolling(window=9, min_periods=9).min()
    return SMA(list(part1/part2*100)[-3:],3,1)

def alpha058(data, dependencies=['closePrice'], max_window=20):
    # COUNT(CLOSE>DELAY(CLOSE,1),20)/20*100
    return ((data['closePrice'].diff(1) > 0.0).rolling(window=20, min_periods=20).sum() / 20.0 * 100).iloc[-1]

def alpha059(data, dependencies=['closePrice', 'lowestPrice', 'highestPrice'], max_window=21):
    # SUM((CLOSE=DELAY(CLOSE,1)?0:CLOSE-(CLOSE>DELAY(CLOSE,1)?MIN(LOW,DELAY(CLOSE,1)):MAX(HIGH,DELAY(CLOSE,1)))),20)
    # \u53d7\u4ef7\u683c\u5c3a\u5ea6\u5f71\u54cd
    alpha =data['closePrice']
    condition1 = data['closePrice'].diff(1) > 0.0
    condition2 = data['closePrice'].diff(1) < 0.0
    alpha[condition1] = data['closePrice'][condition1] - np.minimum(data['lowestPrice'][condition1], data['closePrice'].shift(1)[condition1])
    alpha[condition2] = data['closePrice'][condition2] - np.maximum(data['highestPrice'][condition2], data['closePrice'].shift(1)[condition2])
    alpha = alpha.rolling(window=20, min_periods=20).sum().iloc[-1]
    return alpha

def alpha060(data, dependencies=['closePrice', 'openPrice', 'lowestPrice', 'highestPrice', 'turnoverVol'], max_window=21):
    # SUM((2*CLOSE-LOW-HIGH)./(HIGH-LOW).*VOLUME,20)
    part1 = (2*data['closePrice']-data['lowestPrice']-data['highestPrice']) / (data['highestPrice']-data['lowestPrice']) * data['turnoverVol']
    return part1.rolling(window=20, min_periods=20).sum().iloc[-1]

def alpha061(data, dependencies=['lowestPrice', 'turnoverValue', 'turnoverVol'], max_window=106):
    # MAX(RANK(DECAYLINEAR(DELTA(VWAP,1),12)),RANK(DECAYLINEAR(RANK(CORR(LOW,MEAN(VOLUME,80),8)),17)))*-1
    w12 = np.array(range(1, 13)).reshape(-1)
    w17 = np.array(range(1, 18)).reshape(-1)
    turnover_ma = data['turnoverVol'].rolling(window=80, min_periods=80).mean()
    part1 = (data['turnoverValue']/data['turnoverVol']).diff(periods=1).rolling(window=12, min_periods=12).apply(lambda x: np.dot(x, w12)).rank(axis=0, pct=True)
    part2 = (turnover_ma.rolling(window=8, min_periods=8).corr(data['lowestPrice']).rank(axis=0,pct=True)).rolling(window=17, min_periods=17).apply(lambda x: np.dot(x, w17)).rank(axis=0, pct=True)
    alpha = np.maximum(part1, part2).iloc[-1] * (-1)
    return alpha

def alpha062(data, dependencies=['turnoverVol', 'highestPrice'], max_window=5):
    # -1*CORR(HIGH,RANK(VOLUME),5)
    return data['turnoverVol'].rank(axis=0, pct=True).rolling(window=5, min_periods=5).corr(data['highestPrice']).iloc[-1] * (-1)

def alpha063(data, dependencies=['closePrice'], max_window=7):
    # SMA(MAX(CLOSE-DELAY(CLOSE,1),0),6,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),6,1)*100
    part1 = (np.maximum(data['closePrice'].diff(1), 0.0)).ewm(adjust=False, alpha=float(1)/6, min_periods=0, ignore_na=False).mean()
    part2 = abs(data['closePrice']).diff(1).ewm(adjust=False, alpha=float(1)/6, min_periods=0, ignore_na=False).mean()
    return (part1/part2*100.0).iloc[-1]
    
def alpha064(data, dependencies=['closePrice', 'turnoverValue', 'turnoverVol'], max_window=93):
    # (MAX(RANK(DECAYLINEAR(CORR(RANK(VWAP),RANK(VOLUME),4),4)),RANK(DECAYLINEAR(MAX(CORR(RANK(CLOSE),RANK(MEAN(VOLUME,60)),4),13),14)))*-1)
    # \u770b\u4e0a\u53bb\u662fTSMAX
    vwap = data['turnoverValue'] / data['turnoverVol']
    w4 = np.array(range(1, 5)).reshape(-1)
    w14 = np.array(range(1, 15)).reshape(-1)
    part1 = (vwap.rank(axis=0, pct=True).rolling(window=4, min_periods=4).corr(data['turnoverVol'].rank(axis=0, pct=True))).rolling(window=4, min_periods=4).apply(lambda x: np.dot(x, w4)).rank(axis=0, pct=True)
    part2 = (data['turnoverVol'].rolling(window=60, min_periods=60).mean().rank(axis=0, pct=True)).rolling(window=4, min_periods=4).corr(data['closePrice'].rank(axis=0, pct=True))
    part2 = (part2.rolling(window=13, min_periods=13).max()).rolling(window=14, min_periods=14).apply(lambda x: np.dot(x, w14)).rank(axis=0,pct=True)
    alpha = np.maximum(part1, part2).iloc[-1] * (-1)
    return alpha

def alpha065(data, dependencies=['closePrice'], max_window=6):
    # MEAN(CLOSE,6)/CLOSE
    return (data['closePrice'].rolling(window=6, min_periods=6).mean() / data['closePrice']).iloc[-1]

def alpha066(data, dependencies=['BIAS5'], max_window=6):
    # (CLOSE-MEAN(CLOSE,6))/MEAN(CLOSE,6)*100
    # BIAS6\uff0c\u7528BIAS5\u7b80\u5355\u66ff\u6362\u4e0b
    part1=data['closePrice'].iloc[-1]-data['closePrice'].mean()
    return part1/data['closePrice'].mean()*100

def alpha067(data, dependencies=['closePrice'], max_window=25):
    # SMA(MAX(CLOSE-DELAY(CLOSE,1),0),24,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),24,1)*100
    # RSI24
    part1 = (np.maximum(data['closePrice'].diff(1), 0.0)).ewm(adjust=False, alpha=float(1)/24, min_periods=0, ignore_na=False).mean()
    part2 = (abs(data['closePrice'].diff(1))).ewm(adjust=False, alpha=float(1)/24, min_periods=0, ignore_na=False).mean()
    return (part1 / part2 * 100).iloc[-1]

def alpha068(data, dependencies=['highestPrice', 'lowestPrice', 'turnoverVol'], max_window=16):
    # SMA(((HIGH+LOW)/2-(DELAY(HIGH,1)+DELAY(LOW,1))/2)*(HIGH-LOW)/VOLUME,15,2)
    part1 = (data['highestPrice'].diff(1) * 0.5 + data['lowestPrice'].diff(1) * 0.5) * (data['highestPrice'] - data['lowestPrice']) / data['turnoverVol']
    return part1.ewm(adjust=False, alpha=float(2)/15, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha069(data, dependencies=['openPrice', 'highestPrice', 'lowestPrice'], max_window=21):
    # (SUM(DTM,20)>SUM(DBM,20)?
        #(SUM(DTM,20)-SUM(DBM,20))/SUM(DTM,20):
        #(SUM(DTM,20)=SUM(DBM,20)?0:
            #(SUM(DTM,20)-SUM(DBM,20))/SUM(DBM,20)))
    # DTM: (OPEN<=DELAY(OPEN,1)?0:MAX((HIGH-OPEN),(OPEN-DELAY(OPEN,1))))
    # DBM: (OPEN>=DELAY(OPEN,1)?0:MAX((OPEN-LOW),(OPEN-DELAY(OPEN,1))))
    dtm=(data['openPrice'].diff(1) <= 0) * np.maximum(data['highestPrice']-data['openPrice'],data['openPrice'].diff(1))
    dbm=(data['openPrice'].diff(1) >= 0) * np.maximum(data['openPrice']-data['lowestPrice'],data['openPrice'].diff(1))
    dtm_sum = dtm.rolling(window=20, min_periods=20).sum().iloc[-1]
    dbm_sum = dbm.rolling(window=20, min_periods=20).sum().iloc[-1]
    if dtm_sum>dbm_sum:
        return (dtm_sum-dbm_sum)/dtm_sum
    elif dtm_sum==dbm_sum:return 0
    else:return (dtm_sum-dbm_sum)/dbm_sum


def alpha070(data, dependencies=['turnoverValue'], max_window=6):
    # STD(AMOUNT,6)
    return data['turnoverValue'].rolling(window=6, min_periods=6).std().iloc[-1]

def alpha071(data, dependencies=['closePrice'], max_window=25):
    # (CLOSE-MEAN(CLOSE,24))/MEAN(CLOSE,24)*100
    # BIAS24
    close_ma = data['closePrice'].rolling(window=24, min_periods=24).mean()
    return ((data['closePrice'] - close_ma) / close_ma * 100).iloc[-1]

def alpha072(data, dependencies=['highestPrice', 'lowestPrice', 'closePrice'], max_window=22):
    # SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,15,1)
    part1 = (data['highestPrice'].rolling(window=6, min_periods=6).max() - data['closePrice']) / (data['highestPrice'].rolling(window=6, min_periods=6).max() - data['lowestPrice'].rolling(window=6,min_periods=6).min()) * 100.0
    return part1.ewm(adjust=False, alpha=float(1)/15, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha073(data, dependencies=['turnoverValue', 'turnoverVol', 'closePrice'], max_window=38):
    # ((TSRANK(DECAYLINEAR(DECAYLINEAR(CORR(CLOSE,VOLUME,10),16),4),5)-RANK(DECAYLINEAR(CORR(VWAP,MEAN(VOLUME,30),4),3)))*-1)
    vwap = data['turnoverValue'] / data['turnoverVol']
    w16 =np.array(range(1, 17)).reshape(-1)
    w4 =np.array(range(1, 5)).reshape(-1)
    w3 =np.array(range(1, 4)).reshape(-1)
    part1 = (data['closePrice'].rolling(window=10, min_periods=10).corr(data['turnoverVol'])).rolling(window=16, min_periods=16).apply(lambda x: np.dot(x, w16))
    part1 = (part1.rolling(window=4, min_periods=4).apply(lambda x: np.dot(x, w4))).rolling(window=5, min_periods=5).apply(lambda x: stats.rankdata(x)[-1]/5.0)
    part2 = data['turnoverVol'].rolling(window=30, min_periods=30).mean().rolling(window=4, min_periods=4).corr(vwap)
    part2 = part2.rolling(window=3, min_periods=3).apply(lambda x: np.dot(x, w3)).rank(axis=0, pct=True)
    return (part1 - part2).iloc[-1] * (-1)

def alpha074(data, dependencies=['lowestPrice', 'turnoverValue', 'turnoverVol'], max_window=68):
    # RANK(CORR(SUM(LOW*0.35+VWAP*0.65,20),SUM(MEAN(VOLUME,40),20),7))+RANK(CORR(RANK(VWAP),RANK(VOLUME),6))
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = ((data['lowestPrice'] * 0.35 + vwap * 0.65).rolling(window=20, min_periods=20).sum()).rolling(window=7, min_periods=7).corr((data['turnoverVol'].rolling(window=40,min_periods=40).mean()).rolling(window=20, min_periods=20).sum()).rank(axis=0, pct=True)
    part2 = (vwap.rank(axis=0,pct=True).rolling(window=6, min_periods=6).corr(data['turnoverVol'].rank(axis=0, pct=True))).rank(axis=0, pct=True)
    return (part1 + part2).iloc[-1]

def alpha075(data, dependencies=['closePrice', 'openPrice'], max_window=51):
    # COUNT(CLOSE>OPEN & BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN,50)/COUNT(BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN,50)
    # 简化为等权benchmark
    bm = (data['closePrice'].mean(axis=0) < data['openPrice'].mean(axis=0))
    print(bm)
    bm_den = pd.DataFrame(data=np.repeat(bm.reshape(len(bm),1), len(data['closePrice']), axis=0), index=data['closePrice'].index)
    alpha = np.logical_and(data['closePrice'] > data['openPrice'], bm_den).rolling(window=50, min_periods=50).sum() / bm_den.rolling(window=50, min_periods=50).sum()
    return alpha.iloc[-1]

def alpha076(data, dependencies=['closePrice', 'turnoverVol'], max_window=21):
    # STD(ABS(CLOSE/DELAY(CLOSE,1)-1)/VOLUME,20)/MEAN(ABS(CLOSE/DELAY(CLOSE,1)-1)/VOLUME,20)
    ret_vol = abs(data['closePrice'].pct_change(periods=1))/data['turnoverVol']
    return (ret_vol.rolling(window=20, min_periods=20).std() / ret_vol.rolling(window=20, min_periods=20).mean()).iloc[-1]

def alpha077(data, dependencies=['lowestPrice', 'highestPrice', 'turnoverValue', 'turnoverVol'], max_window=50):
    # MIN(RANK(DECAYLINEAR(HIGH*0.5+LOW*0.5-VWAP,20)),RANK(DECAYLINEAR(CORR(HIGH*0.5+LOW*0.5,MEAN(VOLUME,40),3),6)))
    w6 = np.array(range(1, 7)).reshape(-1)
    w20 = np.array(range(1, 21)).reshape(-1)
    part1 = (data['highestPrice'] * 0.5 + data['lowestPrice'] * 0.5 - data['turnoverValue'] / data['turnoverVol']).rolling(window=20, min_periods=20).apply(lambda x: np.dot(x, w20)).rank(axis=0, pct=True)
    part2 = ((data['highestPrice'] * 0.5 + data['lowestPrice'] * 0.5).rolling(window=3, min_periods=3).corr(data['turnoverVol'].rolling(window=40, min_periods=40).mean())).rolling(window=6, min_periods=6).apply(lambda x: np.dot(x, w6)).rank(axis=0, pct=True)
    return np.minimum(part1, part2).iloc[-1]
    
def alpha078(data, dependencies=['CCI10'], max_window=12):
    # ((HIGH+LOW+CLOSE)/3-MA((HIGH+LOW+CLOSE)/3,12))
    #/(0.015*MEAN(ABS(CLOSE-MEAN((HIGH+LOW+CLOSE)/3,12)),12))
    # \u76f8\u5f53\u4e8e\u662fCCI12, \u7528CCI10\u66ff\u4ee3
    part1=(data['highestPrice']+data['lowestPrice']+data['closePrice'])/3
    part2=part1.iloc[-1]-part1.rolling(window=12, min_periods=12).mean().iloc[-1]
    part3=(data['closePrice']-part1.rolling(window=12, min_periods=12).mean()).abs().mean()*0.015
    return part2/part3

def alpha079(data, dependencies=['closePrice', 'openPrice'], max_window=13):
    # SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100
    # \u5c31\u662fRSI12
    part1 = (np.maximum(data['closePrice'].diff(1), 0.0)).ewm(adjust=False, alpha=float(1)/12, min_periods=0, ignore_na=False).mean()
    part2 = (abs(data['closePrice'].diff(1))).ewm(adjust=False, alpha=float(1)/12, min_periods=0, ignore_na=False).mean()
    return (part1 / part2 * 100).iloc[-1]

def alpha080(data, dependencies=['turnoverVol'], max_window=6):
    # (VOLUME-DELAY(VOLUME,5))/DELAY(VOLUME,5)*100
    return (data['turnoverVol'].pct_change(periods=5) * 100.0).iloc[-1]

def alpha081(data, dependencies=['turnoverVol'], max_window=21):
    # SMA(VOLUME,21,2)
    return data['turnoverVol'].ewm(adjust=False, alpha=float(2)/21, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha082(data, dependencies=['lowestPrice', 'highestPrice', 'closePrice'], max_window=26):
    # SMA((TSMAX(HIGH,6)-CLOSE)/(TSMAX(HIGH,6)-TSMIN(LOW,6))*100,20,1)
    # RSV\u6280\u672f\u6307\u6807\u53d8\u79cd
    part1 = (data['highestPrice'].rolling(window=6,min_periods=6).max()-data['closePrice']) / (data['highestPrice'].rolling(window=6,min_periods=6).max()-data['lowestPrice'].rolling(window=6,min_periods=6).min()) * 100
    alpha = part1.ewm(adjust=False, alpha=float(1)/20, min_periods=0, ignore_na=False).mean().iloc[-1]
    return alpha

def alpha083(data, dependencies=['highestPrice', 'turnoverVol'], max_window=5):
    # (-1*RANK(COVIANCE(RANK(HIGH),RANK(VOLUME),5)))
    alpha = COVIANCE(sorted(data['highestPrice']),sorted(data['turnoverVol']),5)*-1
    return alpha

def alpha084(data, dependencies=['closePrice', 'turnoverVol'], max_window=21):
    # SUM((CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0)),20)
    part1 = np.sign(data['closePrice'].diff(1)) * data['turnoverVol']
    return part1.rolling(window=20, min_periods=20).sum().iloc[-1]

def alpha085(data, dependencies=['closePrice', 'turnoverVol'], max_window=40):
    # TSRANK(VOLUME/MEAN(VOLUME,20),20)*TSRANK(a-1*DELTA(CLOSE,7),8)
    part1 = (data['turnoverVol'] / data['turnoverVol'].rolling(window=20,min_periods=20).mean()).iloc[-20:].rank(axis=0, pct=True)
    part2 = (data['closePrice'].diff(7) * (-1)).iloc[-8:].rank(axis=0, pct=True)
    return (part1 * part2).iloc[-1]

def alpha086(data, dependencies=['closePrice'], max_window=21):
    # ((0.25<((DELAY(CLOSE,20)-DELAY(CLOSE,10))/10-(DELAY(CLOSE,10)-CLOSE)/10))?-1:((((DELAY(CLOSE,20)-DELAY(CLOSE,10))/10-(DELAY(CLOSE,10)-CLOSE)/10)<0)?1:(DELAY(CLOSE,1)-CLOSE)))
    condition1 = (data['closePrice'].shift(20) * 0.1 + data['closePrice'] * 0.1 - data['closePrice'].shift(10) * 0.2) > 0.25
    condition2 = (data['closePrice'].shift(20) * 0.1 + data['closePrice'] * 0.1 - data['closePrice'].shift(10) * 0.2) < 0.0
    alpha = data['closePrice']*-1
    alpha[~condition1 & condition2] = 1.0
    alpha[~condition1 & ~condition2] = data['closePrice'].diff(1)[~condition1 & ~condition2] * (-1)
    return alpha.iloc[-1]

def alpha087(data, dependencies=['turnoverValue', 'turnoverVol', 'lowestPrice', 'highestPrice', 'openPrice'], max_window=18):
    # (RANK(DECAYLINEAR(DELTA(VWAP,4),7))+TSRANK(DECAYLINEAR((LOW-VWAP)/(OPEN-(HIGH+LOW)/2),11),7))*-1
    vwap = data['turnoverValue'] / data['turnoverVol']
    w7 = np.array(range(1, 8)).reshape(-1)
    w11 = np.array(range(1, 12)).reshape(-1)
    part1 = (vwap.diff(4).rolling(window=7, min_periods=7).apply(lambda x: np.dot(x, w7))).rank(axis=0, pct=True)
    part2 = (data['lowestPrice']-vwap)/(data['openPrice']-data['highestPrice']*0.5-data['lowestPrice']*0.5)
    part2 = (part2.rolling(window=11, min_periods=11).apply(lambda x: np.dot(x, w11))).iloc[-7:].rank(axis=0, pct=True)
    return (part1 + part2).iloc[-1] * (-1)

def alpha088(data, dependencies=['REVS20'], max_window=20):
    # (CLOSE-DELAY(CLOSE,20))/DELAY(CLOSE,20)*100
    # \u5c31\u662fREVS20
    return (data['closePrice'].iloc[-1]-data['closePrice'].iloc[-20])/data['closePrice'].iloc[-20]*100

def alpha089(data, dependencies=['closePrice'], max_window=37):
    # 2*(SMA(CLOSE,13,2)-SMA(CLOSE,27,2)-SMA(SMA(CLOSE,13,2)-SMA(CLOSE,27,2),10,2))
    part1 = data['closePrice'].ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean() - data['closePrice'].ewm(adjust=False, alpha=float(2)/27, min_periods=0, ignore_na=False).mean()
    alpha = (part1 - part1.ewm(adjust=False, alpha=float(2)/10, min_periods=0, ignore_na=False).mean()) * 2.0
    return alpha.iloc[-1]

def alpha090(data, dependencies=['turnoverValue', 'turnoverVol'], max_window=5):
    # (RANK(CORR(RANK(VWAP),RANK(VOLUME),5))*-1)
    return CORR(sorted(data['highestPrice']),sorted(data['turnoverVol']),5)*-1
    

def alpha091(data, dependencies=['closePrice', 'turnoverVol', 'lowestPrice'], max_window=45):
    # ((RANK(CLOSE-MAX(CLOSE,5))*RANK(CORR(MEAN(VOLUME,40),LOW,5)))*-1)
    # \u611f\u89c9\u662fTSMAX
    part1 = (data['closePrice'] - data['closePrice'].rolling(window=5, min_periods=5).max()).rank(axis=0, pct=True)
    part2 = (data['turnoverVol'].rolling(window=40, min_periods=40).mean()).rolling(window=5, min_periods=5).corr(data['lowestPrice']).rank(axis=0, pct=True)
    return (part1 * part2).iloc[-1] * (-1)

def alpha092(data, dependencies=['closePrice', 'turnoverValue', 'turnoverVol'], max_window=209):
    # (MAX(RANK(DECAYLINEAR(DELTA(CLOSE*0.35+VWAP*0.65,2),3)),TSRANK(DECAYLINEAR(ABS(CORR((MEAN(VOLUME,180)),CLOSE,13)),5),15))*-1)
    w3 = np.array(range(1, 4)).reshape(-1)
    w5 = np.array(range(1, 6)).reshape(-1)
    part1 = ((data['closePrice'] * 0.35 + data['turnoverValue'] / data['turnoverVol'] * 0.65).diff(2)).rolling(window=3, min_periods=3).apply(lambda x: np.dot(x, w3)).rank(axis=0, pct=True)
    part2 = abs((data['turnoverVol'].rolling(window=180, min_periods=180).mean()).rolling(window=13, min_periods=13).corr(data['closePrice']))
    part2 = (part2.rolling(window=5, min_periods=5).apply(lambda x: np.dot(x, w5))).iloc[-15:].rank(axis=0, pct=True)
    return np.maximum(part1.iloc[-1], part2.iloc[-1]) * (-1)

def alpha093(data, dependencies=['openPrice', 'lowestPrice'], max_window=21):
    # SUM(OPEN>=DELAY(OPEN,1)?0:MAX(OPEN-LOW,OPEN-DELAY(OPEN,1)),20)
    condition = data['openPrice'].diff(1) >= 0.0
    alpha= data['openPrice']
    alpha[~condition] = np.maximum(data['openPrice'] - data['lowestPrice'], data['openPrice'].diff(1))[~condition]
    return alpha.rolling(window=20, min_periods=20).sum().iloc[-1]

def alpha094(data, dependencies=['closePrice', 'turnoverVol'], max_window=31):
    # SUM((CLOSE>DELAY(CLOSE,1)?VOLUME:(CLOSE<DELAY(CLOSE,1)?-VOLUME:0)),30)
    part1 = np.sign(data['closePrice'].diff(1)) * data['turnoverVol']
    return part1.rolling(window=30, min_periods=30).sum().iloc[-1]

def alpha095(data, dependencies=['turnoverValue'], max_window=20):
    # STD(AMOUNT,20), \u8fd9\u91cc\u5e94\u8be5\u6ca1\u6709\u590d\u6743
    return data['turnoverValue'].rolling(window=20, min_periods=20).std().iloc[-1]

def alpha096(data, dependencies=['KDJ_D'], max_window=13):
    # SMA(SMA((CLOSE-TSMIN(LOW,9))/(TSMAX(HIGH,9)-TSMIN(LOW,9))*100,3,1),3,1)
    # \u5c31\u662fKDJ_D
    part1 =data['closePrice']- data['closePrice'].rolling(window=9, min_periods=9).min()
    part2=data['highestPrice'].rolling(window=9, min_periods=9).max()-data['lowestPrice'].rolling(window=9, min_periods=9).min()
    part4=[SMA(list(part1/part2*100)[-5:-2],3,1),SMA(list(part1/part2*100)[-4:-1],3,1),SMA(list(part1/part2*100)[-3:],3,1)]
    part5=SMA(part4,3,1)
    return part5

def alpha097(data, dependencies=['VSTD10'], max_window=10):
    # STD(VOLUME,10)
    # \u5c31\u662fVSTD10
    return STD(data['turnoverVol'],10)

def alpha098(data, dependencies=['closePrice'], max_window=201):
    # (DELTA(SUM(CLOSE,100)/100,100)/DELAY(CLOSE,100)<=0.05)?(-1*(CLOSE-TSMIN(CLOSE,100))):(-1*DELTA(CLOSE,3))
    condition1 = (data['closePrice'].rolling(window=100, min_periods=100).sum() / 100).diff(periods=100) / data['closePrice'].shift(100) <= 0.05
    alpha = (data['closePrice'] - data['closePrice'].rolling(window=100, min_periods=100).min()) * (-1)
    alpha[~condition1] = data['closePrice'].diff(3)[~condition1] * (-1)
    return alpha.iloc[-1]

def alpha099(data, dependencies=['closePrice', 'turnoverVol'], max_window=5):
    # (-1*RANK(COVIANCE(RANK(CLOSE),RANK(VOLUME),5)))
    return COVIANCE(sorted(data['closePrice']),sorted(data['turnoverVol']),5)*-1


def alpha100(data, dependencies=['VSTD20'], max_window=20):
    # STD(VOLUME,20), \u5c31\u662fVSTD20
    return STD(data['turnoverVol'],20)

def alpha101(data, dependencies=['turnoverValue', 'turnoverVol', 'highestPrice', 'closePrice'], max_window=82):
    # (RANK(CORR(CLOSE,SUM(MEAN(VOLUME,30),37),15)) < RANK(CORR(RANK(HIGH*0.1+VWAP*0.9),RANK(VOLUME),11)))*-1
    part1 = (data['turnoverVol'].rolling(window=30, min_periods=30).mean()).rolling(window=37, min_periods=37).sum()
    part1 = (part1.rolling(window=15, min_periods=15).corr(data['closePrice'])).rank(axis=0, pct=True)
    part2 = (data['highestPrice'] * 0.1 + data['turnoverValue'] / data['turnoverVol'] * 0.9).rank(axis=0, pct=True)
    part2 = (part2.rolling(window=11, min_periods=11).corr(data['turnoverVol'].rank(axis=0, pct=True))).rank(axis=0, pct=True)
    return (part2 - part1).iloc[-1] * (-1)

def alpha102(data, dependencies=['turnoverVol'], max_window=7):
    # SMA(MAX(VOLUME-DELAY(VOLUME,1),0),6,1)/SMA(ABS(VOLUME-DELAY(VOLUME,1)),6,1)*100
    part1 = (np.maximum(data['turnoverVol'].diff(1), 0.0)).ewm(adjust=False, alpha=float(1)/6, min_periods=0, ignore_na=False).mean()
    part2 = abs(data['turnoverVol'].diff(1)).ewm(adjust=False, alpha=float(1)/6, min_periods=0, ignore_na=False).mean()
    return (part1 / part2).iloc[-1] * 100

def alpha103(data, dependencies=['lowestPrice'], max_window=20):
    # ((20-LOWDAY(LOW,20))/20)*100
    return (20 - data['lowestPrice'].rolling(window=20, min_periods=20).apply(lambda x: 19-x.argmin(axis=0))).iloc[-1] * 5.0

def alpha104(data, dependencies=['highestPrice', 'turnoverVol', 'closePrice'], max_window=20):
    # -1*(DELTA(CORR(HIGH,VOLUME,5),5)*RANK(STD(CLOSE,20)))
    part1 = (data['highestPrice'].rolling(window=5, min_periods=5).corr(data['turnoverVol'])).diff(5)
    part2 = (data['closePrice'].rolling(window=20, min_periods=20).std()).rank(axis=0, pct=True)
    return (part1 * part2).iloc[-1] * (-1)

def alpha105(data, dependencies=['openPrice', 'turnoverVol'], max_window=10):
    # -1*CORR(RANK(OPEN),RANK(VOLUME),10)
    alpha = (data['openPrice'].rank(axis=0, pct=True)).rolling(window=10, min_periods=10).corr(data['turnoverVol'].rank(axis=0, pct=True))
    return alpha.iloc[-1] * (-1)

def alpha106(data, dependencies=['closePrice'], max_window=21):
    # CLOSE-DELAY(CLOSE,20)
    return data['closePrice'].diff(20).iloc[-1]

def alpha107(data, dependencies=['openPrice', 'closePrice', 'highestPrice', 'lowestPrice'], max_window=2):
    # (-1*RANK(OPEN-DELAY(HIGH,1)))*RANK(OPEN-DELAY(CLOSE,1))*RANK(OPEN-DELAY(LOW,1))
    part1 = data['openPrice'] - data['highestPrice'].shift(1)
    part2 = data['openPrice'] - data['closePrice'].shift(1)
    part3 = data['openPrice'] - data['lowestPrice'].shift(1)
    return (part1 * part2 * part3).iloc[-1] * (-1)

def alpha108(data, dependencies=['highestPrice', 'turnoverValue', 'turnoverVol'], max_window=126):
    # (RANK(HIGH-MIN(HIGH,2))^RANK(CORR(VWAP,MEAN(VOLUME,120),6)))*-1
    part1 = (data['highestPrice'] - data['highestPrice'].rolling(window=2,min_periods=2).min()).rank(axis=0, pct=True)
    part2 = ((data['turnoverVol'].rolling(window=120, min_periods=120).mean()).rolling(window=6, min_periods=6).corr(data['turnoverValue']/data['turnoverVol'])).rank(axis=0, pct=True)
    return (part1 ** part2).iloc[-1] * (-1)

def alpha109(data, dependencies=['highestPrice', 'lowestPrice'], max_window=20):
    # SMA(HIGH-LOW,10,2)/SMA(SMA(HIGH-LOW,10,2),10,2)
    part1 = (data['highestPrice']-data['lowestPrice']).ewm(adjust=False, alpha=float(2)/10, min_periods=0, ignore_na=False).mean()
    return (part1 / part1.ewm(adjust=False, alpha=float(2)/10, min_periods=0, ignore_na=False).mean()).iloc[-1]

def alpha110(data, dependencies=['closePrice', 'highestPrice', 'lowestPrice'], max_window=21):
    # SUM(MAX(0,HIGH-DELAY(CLOSE,1)),20)/SUM(MAX(0,DELAY(CLOSE,1)-LOW),20)*100
    part1 = (np.maximum(data['highestPrice']-data['closePrice'].shift(1), 0.0)).rolling(window=20,min_periods=20).sum()
    part2 = (np.maximum(data['closePrice'].shift(1)-data['lowestPrice'], 0.0)).rolling(window=20,min_periods=20).sum()
    return (part1 / part2).iloc[-1] * 100.0

def alpha111(data, dependencies=['lowestPrice', 'highestPrice', 'closePrice', 'turnoverVol'], max_window=11):
    # SMA(VOL*(2*CLOSE-LOW-HIGH)/(HIGH-LOW),11,2)-SMA(VOL*(2*CLOSE-LOW-HIGH)/(HIGH-LOW),4,2)
    win_vol = data['turnoverVol'] * (data['closePrice']*2-data['lowestPrice']-data['highestPrice']) / (data['highestPrice']-data['lowestPrice'])
    alpha = win_vol.ewm(adjust=False, alpha=float(2)/11, min_periods=0, ignore_na=False).mean() - win_vol.ewm(adjust=False, alpha=float(2)/4, min_periods=0, ignore_na=False).mean()
    return alpha.iloc[-1]

def alpha112(data, dependencies=['closePrice'], max_window=13):
    # (SUM((CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0),12)-SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12))
    # /(SUM((CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0),12)+SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12))*100
    part1 = (np.maximum(data['closePrice'].diff(1), 0.0)).rolling(window=12, min_periods=12).sum()
    part2 = abs(np.minimum(data['closePrice'].diff(1), 0.0)).rolling(window=12, min_periods=12).sum()
    return ((part1-part2) / (part1+part2)).iloc[-1] * 100

def alpha113(data, dependencies=['closePrice', 'turnoverVol'], max_window=28):
    # -1*RANK(SUM(DELAY(CLOSE,5),20)/20)*CORR(CLOSE,VOLUME,2)*RANK(CORR(SUM(CLOSE,5),SUM(CLOSE,20),2))
    part1 = (data['closePrice'].shift(5).rolling(window=20, min_periods=20).mean()).rank(axis=0, pct=True)
    part2 = data['closePrice'].rolling(window=2, min_periods=2).corr(data['turnoverVol'])
    part3 = ((data['closePrice'].rolling(window=5, min_periods=5).sum()).rolling(window=2, min_periods=2).corr(data['closePrice'].rolling(window=20, min_periods=20).sum())).rank(axis=0, pct=True)
    return (part1 * part2 * part3).iloc[-1] * (-1)

def alpha114(data, dependencies=['highestPrice', 'lowestPrice', 'closePrice', 'turnoverValue', 'turnoverVol'], max_window=8):
    # RANK(DELAY((HIGH-LOW)/(SUM(CLOSE,5)/5),2))*RANK(RANK(VOLUME))/((HIGH-LOW)/(SUM(CLOSE,5)/5)/(VWAP-CLOSE))
    # RANK/RANK\u8c8c\u4f3c\u6ca1\u5fc5\u8981
    part1 = ((data['highestPrice']-data['lowestPrice'])/(data['closePrice'].rolling(window=5,min_periods=5).mean())).shift(2).rank(axis=0,pct=True)
    part2 = data['turnoverVol'].rank(axis=0, pct=True).rank(axis=0, pct=True)
    part3 = (data['highestPrice']-data['lowestPrice'])/(data['closePrice'].rolling(window=5,min_periods=5).mean())/(data['turnoverValue']/data['turnoverVol']-data['closePrice'])
    return (part1*part2*part3).iloc[-1]

def alpha115(data, dependencies=['highestPrice', 'lowestPrice', 'turnoverVol', 'closePrice'], max_window=40):
    # (RANK(CORR(HIGH*0.9+CLOSE*0.1,MEAN(VOLUME,30),10))^RANK(CORR(TSRANK((HIGH+LOW)/2,4),TSRANK(VOLUME,10),7)))
    part1 = ((data['highestPrice'] * 0.9 + data['closePrice'] * 0.1).rolling(window=10, min_periods=10).corr(
        data['turnoverVol'].rolling(window=30, min_periods=30).mean())).rank(axis=0, pct=True)
    part2 = (((data['highestPrice'] * 0.5 + data['lowestPrice'] * 0.5).rolling(window=4, min_periods=4).apply(lambda x: stats.rankdata(x)[-1]/4.0)).rolling(window=7, min_periods=7) .corr(data['turnoverVol'].rolling(window=10, min_periods=10).apply(lambda x: stats.rankdata(x)[-1]/10.0))).rank(axis=0,pct=True)
    return (part1 ** part2).iloc[-1]
    
def alpha116(data, dependencies=['closePrice'], max_window=20):
    # REGBETA(CLOSE,SEQUENCE,20)
    alpha = REGBETA(data['closePrice'],list(range(1,21)),20)
    return alpha

def alpha117(data, dependencies=['turnoverVol', 'closePrice', 'highestPrice', 'lowestPrice'], max_window=32):
    # TSRANK(VOLUME,32)*(1-TSRANK(CLOSE+HIGH-LOW,16))*(1-TSRANK(RET,32))
    part1 = data['turnoverVol'].iloc[-32:].rank(axis=0, pct=True)
    part2 = 1.0 - (data['closePrice']+data['highestPrice']-data['lowestPrice']).iloc[-16:].rank(axis=0, pct=True)
    part3 = 1.0 - data['closePrice'].pct_change(periods=1).iloc[-32:].rank(axis=0, pct=True)
    return (part1 * part2 * part3).iloc[-1]

def alpha118(data, dependencies=['highestPrice', 'openPrice', 'lowestPrice'], max_window=20):
    # SUM(HIGH-OPEN,20)/SUM(OPEN-LOW,20)*100
    alpha = (data['highestPrice']-data['openPrice']).rolling(window=20,min_periods=20).sum() / (data['openPrice']-data['lowestPrice']).rolling(window=20,min_periods=20).sum() * 100.0
    return alpha.iloc[-1]

def alpha119(data, dependencies=['turnoverValue', 'turnoverVol', 'openPrice'], max_window=62):
    # RANK(DECAYLINEAR(CORR(VWAP,SUM(MEAN(VOLUME,5),26),5),7))-RANK(DECAYLINEAR(TSRANK(MIN(CORR(RANK(OPEN),RANK(MEAN(VOLUME,15)),21),9),7),8))
    # \u611f\u89c9\u6709\u4e2aTSMIN
    w7 = np.array(range(1, 8))
    w8 = np.array(range(1, 9))
    part1 = ((data['turnoverVol'].rolling(window=5,min_periods=5).mean()).rolling(window=26, min_periods=26).sum()).rolling(window=5, min_periods=5).corr(data['turnoverValue']/data['turnoverVol'])
    part1 = (part1.rolling(window=7,min_periods=7).apply(lambda x:np.dot(x,w7))).rank(axis=0,pct=True)
    part2 = ((data['turnoverVol'].rolling(window=15, min_periods=15).mean()).rank(axis=0,pct=True)).rolling(window=21,min_periods=21).corr(data['openPrice'].rank(axis=0,pct=True))
    part2 = (((part2.rolling(window=9, min_periods=9).min()).rolling(window=7,min_periods=7).apply(lambda x: stats.rankdata(x)[-1]/7.0)).rolling(window=8,min_periods=8).apply(lambda x:np.dot(x,w8))).rank(axis=0, pct=True)
    return (part1-part2).iloc[-1]

def alpha120(data, dependencies=['turnoverValue', 'turnoverVol', 'closePrice'], max_window=1):
    # RANK(VWAP-CLOSE)/RANK(VWAP+CLOSE)
    vwap = data['turnoverValue'] / data['turnoverVol']
    return ((vwap-data['closePrice']) / (vwap+data['closePrice'])).iloc[-1]

def alpha121(data, dependencies=['turnoverValue', 'turnoverVol'], max_window=83):
    # (RANK(VWAP-MIN(VWAP,12))^TSRANK(CORR(TSRANK(VWAP,20),TSRANK(MEAN(VOLUME,60),2),18),3))*-1
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = (vwap - vwap.rolling(window=12, min_periods=12).min()).rank(axis=0, pct=True)
    part2 = (data['turnoverVol'].rolling(window=60, min_periods=60).mean()).rolling(window=2, min_periods=2).apply(lambda x: stats.rankdata(x)[-1]/2.0)
    part2 = ((vwap.rolling(window=20, min_periods=20).apply(lambda x: stats.rankdata(x)[-1]/20.0)).rolling(window=18, min_periods=18).corr(part2)) .rolling(window=3, min_periods=3).apply(lambda x: stats.rankdata(x)[-1]/3.0)
    return (part1 ** part2).iloc[-1] * (-1)

def alpha122(data, dependencies=['closePrice'], max_window=40):
    # (SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2)-DELAY(SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2),1))/DELAY(SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2),1)
    part1 = (np.log(data['closePrice'])).ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()
    part1 = (part1.ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()).ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()
    return part1.pct_change(periods=1).iloc[-1]

def alpha123(data, dependencies=['highestPrice', 'lowestPrice', 'turnoverVol'], max_window=89):
    # (RANK(CORR(SUM((HIGH+LOW)/2,20),SUM(MEAN(VOLUME,60),20),9)) < RANK(CORR(LOW,VOLUME,6)))*-1
    part1 = (data['highestPrice']*0.5+data['lowestPrice']*0.5).rolling(window=20, min_periods=20).sum()
    part1 = ((data['turnoverVol'].rolling(window=60,min_periods=60).mean()).rolling(window=20,min_periods=20).sum()).rolling(window=9,min_periods=9).corr(part1).rank(axis=0, pct=True)
    part2 = (data['lowestPrice'].rolling(window=6,min_periods=6).corr(data['turnoverVol'])).rank(axis=0, pct=True)
    return (part2 - part1).iloc[-1] * (-1)

def alpha124(data, dependencies=['closePrice', 'turnoverValue', 'turnoverVol'], max_window=32):
    # (CLOSE-VWAP)/DECAYLINEAR(RANK(TSMAX(CLOSE,30)),2)
    vwap = data['turnoverValue'] / data['turnoverVol']
    w2 = np.array(range(1, 3))
    part1 = data['closePrice'] - vwap
    part2 = ((data['closePrice'].rolling(window=30,min_periods=30).max()).rank(axis=0,pct=True)).rolling(window=2,min_periods=2).apply(lambda x:np.dot(x,w2))
    return (part1 / part2).iloc[-1]

def alpha125(data, dependencies=['closePrice', 'turnoverValue', 'turnoverVol'], max_window=117):
    # RANK(DECAYLINEAR(CORR(VWAP,MEAN(VOLUME,80),17),20))/RANK(DECAYLINEAR(DELTA(CLOSE*0.5+VWAP*0.5,3),16))
    vwap = data['turnoverValue'] / data['turnoverVol']
    w20 = np.array(range(1, 21))
    w16 = np.array(range(1, 17))
    part1 = (data['turnoverVol'].rolling(window=80,min_periods=80).mean()).rolling(window=17,min_periods=17).corr(vwap)
    part1 = (part1.rolling(window=20,min_periods=20).apply(lambda x:np.dot(x,w20))).rank(axis=0, pct=True)
    part2 = ((data['closePrice']*0.5+vwap*0.5).diff(periods=3)).rolling(window=16,min_periods=16).apply(lambda x:np.dot(x,w16)).rank(axis=0,pct=True)
    return (part1 / part2).iloc[-1]

def alpha126(data, dependencies=['highestPrice', 'lowestPrice', 'closePrice'], max_window=1):
    # (CLOSE+HIGH+LOW)/3
    return (data['closePrice'] + data['highestPrice'] + data['lowestPrice']).iloc[-1] / 3.0

def alpha127(data, dependencies=['closePrice'], max_window=24):
    # MEAN((100*(CLOSE-MAX(CLOSE,12))/MAX(CLOSE,12))^2)^(1/2)
    # \u8fd9\u91cc\u8c8c\u4f3c\u662fTSMAX,MEAN\u5c11\u4e00\u4e2a\u53c2\u6570
    alpha = (data['closePrice'] - data['closePrice'].rolling(window=12,min_periods=12).max()) / data['closePrice'].rolling(window=12,min_periods=12).max() * 100
    alpha = (alpha ** 2).rolling(window=12, min_periods=12).mean().iloc[-1] ** 0.5
    return alpha

def alpha128(data, dependencies=['highestPrice', 'lowestPrice', 'closePrice', 'turnoverVol'], max_window=14):
    # 100-(100/(1+SUM(((HIGH+LOW+CLOSE)/3>DELAY((HIGH+LOW+CLOSE)/3,1)?(HIGH+LOW+CLOSE)/3*VOLUME:0),14)/
    # SUM(((HIGH+LOW+CLOSE)/3<DELAY((HIGH+LOW+CLOSE)/3,1)?(HIGH+LOW+CLOSE)/3*VOLUME:0),14)))
    condition1 = ((data['highestPrice']+data['lowestPrice']+data['closePrice'])/3.0).diff(1) > 0.0
    condition2 = ((data['highestPrice']+data['lowestPrice']+data['closePrice'])/3.0).diff(1) < 0.0
    part1 = (data['highestPrice']+data['lowestPrice']+data['closePrice'])/3.0*data['turnoverVol']
    part2 = part1.copy(deep=True)
    part1[~condition1] = 0.0
    part1 = part1.rolling(window=14, min_periods=14).sum()
    part2[~condition2] = 0.0
    part2 = part2.rolling(window=14, min_periods=14).sum()
    return (100.0-(100.0/(1+part1/part2))).iloc[-1]

def alpha129(data, dependencies=['closePrice'], max_window=13):
    # SUM((CLOSE-DELAY(CLOSE,1)<0?ABS(CLOSE-DELAY(CLOSE,1)):0),12)
    return (abs(np.minimum(data['closePrice'].diff(1), 0.0))).rolling(window=12, min_periods=12).sum().iloc[-1]

def alpha130(data, dependencies=['lowestPrice', 'highestPrice', 'turnoverVol', 'turnoverValue'], max_window=59):
    # (RANK(DECAYLINEAR(CORR((HIGH+LOW)/2,MEAN(VOLUME,40),9),10))/RANK(DECAYLINEAR(CORR(RANK(VWAP),RANK(VOLUME),7),3)))
    vwap = data['turnoverValue'] / data['turnoverVol']
    w10 = np.array(range(1, 11))
    w3 = np.array(range(1, 4))
    part1 = (data['turnoverVol'].rolling(window=40,min_periods=40).mean()).rolling(window=9,min_periods=9).corr(data['highestPrice']*0.5+data['lowestPrice']*0.5)
    part1 = part1.rolling(window=10,min_periods=10).apply(lambda x: np.dot(x, w10)).rank(axis=0, pct=True)
    part2 = (data['turnoverVol'].rank(axis=0, pct=True)).rolling(window=7,min_periods=7).corr(vwap.rank(axis=0, pct=True))
    part2 = part2.rolling(window=3,min_periods=3).apply(lambda x: np.dot(x, w3)).rank(axis=0, pct=True)
    return (part1 / part2).iloc[-1]

def alpha131(data, dependencies=['turnoverValue', 'turnoverVol', 'closePrice'], max_window=86):
    # (RANK(DELAT(VWAP,1))^TSRANK(CORR(CLOSE,MEAN(VOLUME,50),18),18))
    part1 = (data['turnoverValue'] / data['turnoverVol']).diff(1).rank(axis=0, pct=True).iloc[-1:]
    part2 = (data['turnoverVol'].rolling(window=50, min_periods=50).mean()).rolling(window=18, min_periods=18).corr(data['closePrice'])
    part2 = part2.iloc[-18:].rank(axis=0, pct=True)
    return (part1 ** part2).iloc[-1]

def alpha132(data, dependencies=['turnoverValue'], max_window=20):
    # MEAN(AMOUNT,20)
    return data['turnoverValue'].rolling(window=20, min_periods=20).mean().iloc[-1]

def alpha133(data, dependencies=['lowestPrice', 'highestPrice'], max_window=20):
    # ((20-HIGHDAY(HIGH,20))/20)*100-((20-LOWDAY(LOW,20))/20)*100
    part1 = (20 - data['highestPrice'].rolling(window=20, min_periods=20).apply(lambda x: 19-x.argmax(axis=0))) * 5.0
    part2 = (20 - data['lowestPrice'].rolling(window=20, min_periods=20).apply(lambda x: 19-x.argmin(axis=0))) * 5.0
    return (part1 -part2).iloc[-1]

def alpha134(data, dependencies=['closePrice', 'turnoverVol'], max_window=13):
    # (CLOSE-DELAY(CLOSE,12))/DELAY(CLOSE,12)*VOLUME
    return (data['closePrice'].pct_change(periods=12) * data['turnoverVol']).iloc[-1]

def alpha135(data, dependencies=['closePrice'], max_window=42):
    # SMA(DELAY(CLOSE/DELAY(CLOSE,20),1),20,1)
    alpha = (data['closePrice']/data['closePrice'].shift(20)).shift(1)
    return alpha.ewm(adjust=False, alpha=float(1)/20, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha136(data, dependencies=['closePrice', 'openPrice', 'turnoverVol'], max_window=10):
    # -1*RANK(DELTA(RET,3))*CORR(OPEN,VOLUME,10)
    part1 = data['closePrice'].pct_change(periods=1).diff(3).rank(axis=0,pct=True)
    part2 = data['openPrice'].rolling(window=10, min_periods=10).corr(data['turnoverVol'])
    return (part1 * part2).iloc[-1] * (-1)

def alpha137(data, dependencies=['openPrice', 'lowestPrice', 'closePrice', 'highestPrice'], max_window=2):
    # 16*(CLOSE+(CLOSE-OPEN)/2-DELAY(OPEN,1))/
    # ((ABS(HIGH-DELAY(CLOSE,1))>ABS(LOW-DELAY(CLOSE,1))&ABS(HIGH-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1))?ABS(HIGH-DELAY(CLOSE,1))+ABS(LOW-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:
    # (ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(LOW,1)) & ABS(LOW-DELAY(CLOSE,1))>ABS(HIGH-DELAY(CLOSE,1))?ABS(LOW-DELAY(CLOSE,1))+ABS(HIGH-DELAY(CLOSE,1))/2+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4:ABS(HIGH-DELAY(LOW,1))+ABS(DELAY(CLOSE,1)-DELAY(OPEN,1))/4)))
    # *MAX(ABS(HIGH-DELAY(CLOSE,1)),ABS(LOW-DELAY(CLOSE,1)))
    part1 = data['closePrice'] * 1.5 - data['openPrice'] * 0.5 - data['openPrice'].shift(1)
    part2 = abs(data['highestPrice']-data['closePrice'].shift(1)) + abs(data['lowestPrice']-data['closePrice'].shift(1)) / 2.0 + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    condition1 = np.logical_and(abs(data['highestPrice']-data['closePrice'].shift(1)) > abs(data['lowestPrice']-data['closePrice'].shift(1)), 
                               abs(data['highestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['lowestPrice'].shift(1)))
    condition2 = np.logical_and(abs(data['lowestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['lowestPrice'].shift(1)), 
                               abs(data['lowestPrice']-data['closePrice'].shift(1)) > abs(data['highestPrice']-data['closePrice'].shift(1)))
    part2[~condition1 & condition2] = abs(data['lowestPrice']-data['closePrice'].shift(1)) + abs(data['highestPrice']-data['closePrice'].shift(1)) / 2.0 + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    part2[~condition1 & ~condition2] = abs(data['highestPrice']-data['lowestPrice'].shift(1)) + abs(data['closePrice']-data['openPrice']).shift(1) / 4.0
    part3 = np.maximum(abs(data['highestPrice']-data['closePrice'].shift(1)), abs(data['lowestPrice']-data['closePrice'].shift(1)))
    alpha = (part1 / part2 * part3 * 16.0).iloc[-1]
    return alpha

def alpha138(data, dependencies=['lowestPrice','turnoverValue','turnoverVol'], max_window=126):
    # ((RANK(DECAYLINEAR(DELTA(LOW*0.7+VWAP*0.3,3),20))
    # -TSRANK(DECAYLINEAR(TSRANK(
        # CORR(TSRANK(LOW,8),TSRANK(MEAN(VOLUME,60),17),5)
        # ,19),16),7))* -1)
    w20 = np.array(range(1, 21))
    w16 = np.array(range(1, 17))
    part1 = ((data['lowestPrice']*0.7+data['turnoverValue']/data['turnoverVol']*0.3).diff(3)).rolling(window=20,min_periods=20).apply(lambda x: np.dot(x,w20)).rank(axis=0, pct=True)
    part2 = (data['turnoverVol'].rolling(window=60, min_periods=60).mean()).rolling(window=17,min_periods=17).apply(lambda x: stats.rankdata(x)[-1]/17.0)
    part2 = part2.rolling(window=5,min_periods=5).corr(data['lowestPrice'].rolling(window=8,min_periods=8).apply(lambda x: stats.rankdata(x)[-1]/8.0))
    part2 = ((part2.rolling(window=19,min_periods=19).apply(lambda x: stats.rankdata(x)[-1]/19.0)).rolling(window=16,min_periods=16).apply(lambda x:np.dot(x,w16))).rolling(window=7,min_periods=7).apply(lambda x: stats.rankdata(x)[-1]/7.0)
    return (part1-part2).iloc[-1] * (-1)

def alpha139(data, dependencies=['openPrice', 'turnoverVol'], max_window=10):
    # (-1*CORR(OPEN,VOLUME,10))
    return data['openPrice'].rolling(window=10,min_periods=10).corr(data['turnoverVol']).iloc[-1] * (-1)

def alpha140(data, dependencies=['openPrice', 'lowestPrice', 'highestPrice', 'closePrice', 'turnoverVol'], max_window=99):
    # MIN(RANK(DECAYLINEAR(RANK(OPEN)+RANK(LOW)-RANK(HIGH)-RANK(CLOSE),8)),TSRANK(DECAYLINEAR(CORR(TSRANK(CLOSE,8),TSRANK(MEAN(VOLUME,60),20),8),7),3))
    w8 = np.array(range(1, 9))
    w7 = np.array(range(1, 8))
    part1 = data['openPrice'].rank(axis=0,pct=True)+data['lowestPrice'].rank(axis=0,pct=True)-data['highestPrice'].rank(axis=0,pct=True)-data['closePrice'].rank(axis=0,pct=True)
    part1 = part1.rolling(window=8,min_periods=8).apply(lambda x:np.dot(x,w8)).rank(axis=0,pct=True)
    part2 = (data['turnoverVol'].rolling(window=60, min_periods=60).mean()).rolling(window=20,min_periods=20).apply(lambda x: stats.rankdata(x)[-1]/20.0)
    part2 = part2.rolling(window=8,min_periods=8).corr(data['closePrice'].rolling(window=8,min_periods=8).apply(lambda x: stats.rankdata(x)[-1]/8.0))
    part2 = (part2.rolling(window=7,min_periods=7).apply(lambda x:np.dot(x,w7))).rolling(window=3,min_periods=3).apply(lambda x: stats.rankdata(x)[-1]/3.0)  
    return np.minimum(part1,part2).iloc[-1]

def alpha141(data, dependencies=['highestPrice', 'turnoverVol'], max_window=25):
    # (RANK(CORR(RANK(HIGH),RANK(MEAN(VOLUME,15)),9))*-1)
    alpha = ((data['turnoverVol'].rolling(window=15,min_periods=15).mean().rank(axis=0,pct=True)).rolling(window=9,min_periods=9).corr(data['highestPrice'].rank(axis=0,pct=True))).rank(axis=0,pct=True)
    return alpha.iloc[-1] * (-1)

def alpha142(data, dependencies=['closePrice', 'turnoverVol'], max_window=25):
    # -1*RANK(TSRANK(CLOSE,10))*RANK(DELTA(DELTA(CLOSE,1),1))*RANK(TSRANK(VOLUME/MEAN(VOLUME,20),5))
    part1 = (data['closePrice'].rolling(window=10,min_periods=10).apply(lambda x: stats.rankdata(x)[-1]/10.0)).rank(axis=0,pct=True)
    part2 = (data['closePrice'].diff(1)).diff(1).rank(axis=0,pct=True)
    part3 = (data['turnoverVol']/data['turnoverVol'].rolling(window=20,min_periods=20).mean()).rolling(window=5,min_periods=5).apply(lambda x: stats.rankdata(x)[-1]/5.0).rank(axis=0,pct=True)
    return (part1 * part2 * part3).iloc[-1] * (-1)

def alpha143():
    # CLOSE>DELAY(CLOSE,1)?(CLOSE-DELAY(CLOSE,1))/DELAY(CLOSE,1)*SELF:SELF
    # \u8868\u793a t-1 \u65e5\u7684 Alpha143 \u56e0\u5b50\u8ba1\u7b97\u7ed3\u679c
    return

def alpha144(data, dependencies=['closePrice','turnoverValue'], max_window=21):
    # SUMIF(ABS(CLOSE/DELAY(CLOSE,1)-1)/AMOUNT,20,CLOSE<DELAY(CLOSE,1))/COUNT(CLOSE<DELAY(CLOSE,1),20)
    part1 = abs(data['closePrice'].pct_change(periods=1)) / data['turnoverValue']
    part1[data['closePrice'].diff(1)>=0] = 0.0
    part1 = part1.rolling(window=20, min_periods=20).sum()
    part2 = (data['closePrice'].diff(1)<0.0).rolling(window=20,min_periods=20).sum()
    return (part1 / part2).iloc[-1]

def alpha145(data, dependencies=['turnoverVol'], max_window=26):
    # (MEAN(VOLUME,9)-MEAN(VOLUME,26))/MEAN(VOLUME,12)*100
    alpha = (data['turnoverVol'].rolling(window=9,min_periods=9).mean() - data['turnoverVol'].rolling(window=26,min_periods=26).mean()) / data['turnoverVol'].rolling(window=12,min_periods=12).mean() * 100.0
    return alpha.iloc[-1]

def alpha146(data, dependencies=['closePrice'], max_window=121):
    # MEAN(RET-SMA(RET,61,2),20)*(RET-SMA(RET,61,2))/SMA(SMA(RET,61,2)^2,60)
    # \u5047\u8bbe\u6700\u540e\u4e00\u4e2aSMA(X,60,1)
    sma = (data['closePrice'].pct_change(1)).ewm(adjust=False, alpha=float(2)/61, min_periods=0, ignore_na=False).mean()
    ret_excess = data['closePrice'].pct_change(1) - sma
    part1 = ret_excess.rolling(window=20, min_periods=20).mean() * ret_excess
    part2 = (sma ** 2).ewm(adjust=False, alpha=float(1)/60, min_periods=0, ignore_na=False).mean()
    return (part1 / part2).iloc[-1]

def alpha147(data, dependencies=['closePrice'], max_window=24):
    # REGBETA(MEAN(CLOSE,12),SEQUENCE(12))
    ma_price = data['closePrice'].rolling(window=12, min_periods=12).mean()
    alpha = REGBETA(ma_price,list(range(1,13)),12)
    return alpha

def alpha148(data, dependencies=['openPrice', 'turnoverVol'], max_window=75):
    # (RANK(CORR(OPEN,SUM(MEAN(VOLUME,60),9),6))<RANK(OPEN-TSMIN(OPEN,14)))*-1
    part1 = (data['turnoverVol'].rolling(window=60,min_periods=60).mean()).rolling(window=9,min_periods=9).sum()
    part1 = part1.rolling(window=6,min_periods=6).corr(data['openPrice']).rank(axis=0,pct=True)
    part2 = (data['openPrice'] - data['openPrice'].rolling(window=14,min_periods=14).min()).rank(axis=0, pct=True)
    return (part2-part1).iloc[-1] * (-1)

def alpha149(data, dependencies=['closePrice'], max_window=253):
    # REGBETA(FILTER(RET,BANCHMARK_INDEX_CLOSE<DELAY(BANCHMARK_INDEX_CLOSE,1)),
    # FILTER(BANCHMARK_INDEX_CLOSE/DELAY(BANCHMARK_INDEX_CLOSE,1)-1,BANCHMARK_INDEX_CLOSE<DELAY(BANCHMARK_INDEX_CLOSE,1)),252)
    bm = (data['closePrice'].mean(axis=0).diff(1) < 0.0)
    part1 = data['closePrice'].pct_change(periods=1).iloc[-252:][bm]
    part2 = data['closePrice'].mean(axis=0).pct_change(periods=1).iloc[-252:][bm]
    alpha = pd.DataFrame([[stats.linregress(part1[col].values, part2.values)[0] for col in data['closePrice'].columns]], 
                 index=data['closePrice'].index[-1:], columns=data['closePrice'].columns)
    return alpha.iloc[-1]

def alpha150(data, dependencies=['closePrice', 'highestPrice', 'lowestPrice', 'turnoverVol'], max_window=1):
    # (CLOSE+HIGH+LOW)/3*VOLUME
    return ((data['closePrice'] + data['highestPrice'] + data['lowestPrice']) / 3.0 * data['turnoverVol']).iloc[-1]

def alpha151(data, dependencies=['closePrice'], max_window=41):
    # SMA(CLOSE-DELAY(CLOSE,20),20,1)
    return (data['closePrice'].diff(20)).ewm(adjust=False, alpha=float(1)/20, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha152(data, dependencies=['closePrice'], max_window=59):
    # A=DELAY(SMA(DELAY(CLOSE/DELAY(CLOSE,9),1),9,1),1)
    # SMA(MEAN(A,12)-MEAN(A,26),9,1)
    part1 = ((data['closePrice'] / data['closePrice'].shift(9)).shift(1)).ewm(adjust=False, alpha=float(1)/9, min_periods=0, ignore_na=False).mean().shift(1)
    alpha = (part1.rolling(window=12,min_periods=12).mean()-part1.rolling(window=26,min_periods=26).mean()).ewm(adjust=False, alpha=float(1)/9, min_periods=0, ignore_na=False).mean()
    return alpha.iloc[-1]

def alpha153(data, dependencies=['BBI'], max_window=24):
    # (MEAN(CLOSE,3)+MEAN(CLOSE,6)+MEAN(CLOSE,12)+MEAN(CLOSE,24))/4
    # \u5c31\u662fBBI
    part1=[3,6,12,24]
    part2=[data['closePrice'].rolling(window=x,min_periods=x).mean().iloc[-1] for x in part1]
    return sum(part2)/4

def alpha154(data, dependencies=['turnoverValue', 'turnoverVol'], max_window=198):
    # VWAP-MIN(VWAP,16)<CORR(VWAP,MEAN(VOLUME,180),18)
    # \u611f\u89c9\u662fTSMIN
    vwap = data['turnoverValue'] / data['turnoverVol']
    part1 = vwap - vwap.rolling(window=16, min_periods=16).min()
    part2 = (data['turnoverVol'].rolling(window=180, min_periods=180).mean()).rolling(window=18, min_periods=18).corr(vwap)
    return (part2-part1).iloc[-1]

def alpha155(data, dependencies=['turnoverVol'], max_window=37):
    # SMA(VOLUME,13,2)-SMA(VOLUME,27,2)-SMA(SMA(VOLUME,13,2)-SMA(VOLUME,27,2),10,2)
    sma13 = data['turnoverVol'].ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()
    sma27 = data['turnoverVol'].ewm(adjust=False, alpha=float(2)/27, min_periods=0, ignore_na=False).mean()
    ssma = (sma13-sma27).ewm(adjust=False, alpha=float(2)/10, min_periods=0, ignore_na=False).mean()
    return (sma13 - sma27 - ssma).iloc[-1]

def alpha156(data, dependencies=['turnoverValue', 'turnoverVol', 'openPrice', 'lowestPrice'], max_window=9):
    # MAX(RANK(DECAYLINEAR(DELTA(VWAP,5),3)),RANK(DECAYLINEAR((DELTA(OPEN*0.15+LOW*0.85,2)/(OPEN*0.15+LOW*0.85)) * -1,3))) * -1
    w3 = np.array(range(1, 4))
    den = data['openPrice']*0.15+data['lowestPrice']*0.85
    part1 = ((data['turnoverValue']/data['turnoverVol']).diff(5)).rolling(window=3,min_periods=3).apply(lambda x:np.dot(x,w3))
    part2 = (den.diff(2)/den*(-1)).rolling(window=3,min_periods=3).apply(lambda x:np.dot(x,w3))
    return np.maximum(part1, part2).iloc[-1] * (-1)

def alpha157(data, dependencies=['closePrice'], max_window=12):
    # MIN(PROD(RANK(LOG(SUM(TSMIN(RANK(-1*RANK(DELTA(CLOSE-1,5))),2),1))),1),5) +TSRANK(DELAY(-1*RET,6),5)
    part1 = np.log((((data['closePrice']-1.0).diff(5).rank(axis=0,pct=True) * (-1)).rank(axis=0, pct=True)).rolling(window=2, min_periods=2).min())
    part1 = (part1.rank(axis=0, pct=True)).rolling(window=5,min_periods=5).min().iloc[-1:]
    part2 = ((data['closePrice'].pct_change(periods=1) * (-1)).shift(6)).iloc[-5:].rank(axis=0, pct=True)
    return (part1 + part2) .iloc[-1]

def alpha158(data, dependencies=['lowestPrice', 'highestPrice', 'closePrice'], max_window=1):
    # (HIGH-LOW)/CLOSE
    return ((data['highestPrice'] - data['lowestPrice']) / data['closePrice']).iloc[-1]

def alpha159(data, dependencies=['closePrice', 'lowestPrice', 'highestPrice'], max_window=25):
    # ((CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),6))/SUM(MAX(HGIH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),6)*12*24
    # +(CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),12))/SUM(MAX(HGIH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),12)*6*24
    # +(CLOSE-SUM(MIN(LOW,DELAY(CLOSE,1)),24))/SUM(MAX(HGIH,DELAY(CLOSE,1))-MIN(LOW,DELAY(CLOSE,1)),24)*6*24)*100/(6*12+6*24+12*24)
    min_low_close = np.minimum(data['lowestPrice'], data['closePrice'].shift(1))
    max_high_close = np.maximum(data['highestPrice'], data['closePrice'].shift(1))
    part1 = (data['closePrice'] - min_low_close.rolling(window=6,min_periods=6).sum()) / (max_high_close-min_low_close).rolling(window=6,min_periods=6).sum() * 12 * 24
    part2 = (data['closePrice'] - min_low_close.rolling(window=12,min_periods=12).sum()) / (max_high_close-min_low_close).rolling(window=12,min_periods=12).sum() * 6 * 24
    part3 = (data['closePrice'] - min_low_close.rolling(window=24,min_periods=24).sum()) / (max_high_close-min_low_close).rolling(window=24,min_periods=24).sum() * 6 * 12
    return (part1+part2+part3).iloc[-1]*100.0/(12*6+6*24+12*24)
    
def alpha160(data, dependencies=['closePrice'], max_window=41):
    # SMA((CLOSE<=DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)
    part1 = data['closePrice'].rolling(window=20,min_periods=20).std()
    part1[data['closePrice'].diff(1)>0] = 0.0
    return part1.ewm(adjust=False, alpha=float(1)/20, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha161(data, dependencies=['closePrice', 'lowestPrice', 'highestPrice'], max_window=13):
    # MEAN(MAX(MAX(HIGH-LOW,ABS(DELAY(CLOSE,1)-HIGH)),ABS(DELAY(CLOSE,1)-LOW)),12)
    part1 = np.maximum(data['highestPrice']-data['lowestPrice'], abs(data['closePrice'].shift(1)-data['highestPrice']))
    part1 = np.maximum(part1, abs(data['closePrice'].shift(1)-data['lowestPrice']))
    return part1.rolling(window=12,min_periods=12).mean().iloc[-1]

def alpha162(data, dependencies=['closePrice'], max_window=25):
    # (SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100
    # -MIN(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12))
    # /(MAX(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12)
    # -MIN(SMA(MAX(CLOSE-DELAY(CLOSE,1),0),12,1)/SMA(ABS(CLOSE-DELAY(CLOSE,1)),12,1)*100,12))
    den = (np.maximum(data['closePrice'].diff(1), 0.0)).ewm(adjust=False, alpha=float(1)/12, min_periods=0, ignore_na=False).mean() /(abs(data['closePrice'].diff(1))).ewm(adjust=False, alpha=float(1)/12, min_periods=0, ignore_na=False).mean() * 100.0
    alpha = (den - den.rolling(window=12,min_periods=12).min()) / (den.rolling(window=12,min_periods=12).max() - den.rolling(window=12,min_periods=12).min())
    return alpha.iloc[-1]

def alpha163(data, dependencies=['turnoverValue', 'turnoverVol', 'closePrice', 'highestPrice'], max_window=20):
    # RANK((-1*RET)*MEAN(VOLUME,20)*VWAP*(HIGH-CLOSE))
    alpha = data['closePrice'].pct_change(periods=1) * (data['turnoverVol'].rolling(window=20, min_periods=20).mean()) * (data['turnoverValue'] / data['turnoverVol']) * (data['highestPrice'] - data['closePrice']) * (-1)
    return alpha.iloc[-1]

def alpha164(data, dependencies=['closePrice', 'highestPrice', 'lowestPrice'], max_window=26):
    # SMA(((CLOSE>DELAY(CLOSE,1)?1/(CLOSE-DELAY(CLOSE,1)):1)-MIN(CLOSE>DELAY(CLOSE,1)?1/(CLOSE-DELAY(CLOSE,1)):1,12))/(HIGH-LOW)*100,13,2)
    part1 = 1.0 / data['closePrice'].diff(1)
    part1[data['closePrice'].diff(1)<=0] = 1.0
    part2 = part1.rolling(window=12, min_periods=12).min()
    alpha = (part1-part2)/(data['highestPrice']-data['lowestPrice'])*100.0
    return alpha.ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha165(data, dependencies=['closePrice'], max_window=144):
    # MAX(SUMAC(CLOSE-MEAN(CLOSE,48)))-MIN(SUMAC(CLOSE-MEAN(CLOSE,48)))/STD(CLOSE,48)
    # SUMAC\u5c11\u4e86\u524dN\u9879\u548c,TSMAX/TSMIN
    part1 = ((data['closePrice']-data['closePrice'].rolling(window=48,min_periods=48).mean()).rolling(window=48,min_periods=48).sum()).rolling(window=48,min_periods=48).max()
    part2 = ((data['closePrice']-data['closePrice'].rolling(window=48,min_periods=48).mean()).rolling(window=48,min_periods=48).sum()).rolling(window=48,min_periods=48).min()
    part3 = data['closePrice'].rolling(window=48,min_periods=48).std()
    return (part1-part2/part3).iloc[-1]

def alpha166(data, dependencies=['closePrice'], max_window=41):
    # -20*(20-1)^1.5*SUM(CLOSE/DELAY(CLOSE,1)-1-MEAN(CLOSE/DELAY(CLOSE,1)-1,20),20)/((20-1)*(20-2)*(SUM((CLOSE/DELAY(CLOSE,1))^2,20))^1.5)
    part1 = data['closePrice'].pct_change(periods=1)-(data['closePrice'].pct_change(periods=1).rolling(window=20,min_periods=20).mean())
    part1 = part1.rolling(window=20,min_periods=20).sum() * ((-20) * 19 ** 1.5)
    part2 = (((data['closePrice']/data['closePrice'].shift(1)) ** 2).rolling(window=20,min_periods=20).sum() ** 1.5) * 19 * 18
    return (part1 / part2).iloc[-1]

def alpha167(data, dependencies=['closePrice'], max_window=13):
    # SUM(CLOSE-DELAY(CLOSE,1)>0?CLOSE-DELAY(CLOSE,1):0,12)
    return (np.maximum(data['closePrice'].diff(1), 0.0)).rolling(window=12, min_periods=12).sum().iloc[-1]

def alpha168(data, dependencies=['turnoverVol'], max_window=20):
    # -1*VOLUME/MEAN(VOLUME,20)
    return (data['turnoverVol']/(data['turnoverVol'].rolling(window=20,min_periods=20).mean())).iloc[-1] * (-1)

def alpha169(data, dependencies=['closePrice'], max_window=48):
    # SMA(MEAN(DELAY(SMA(CLOSE-DELAY(CLOSE,1),9,1),1),12)-MEAN(DELAY(SMA(CLOSE-DELAY(CLOSE,1),9,1),1),26),10,1)
    part1 = (data['closePrice'].diff(1).ewm(adjust=False, alpha=float(1)/9, min_periods=0, ignore_na=False).mean()).shift(1)
    part2 = (part1.rolling(window=12, min_periods=12).mean() - part1.rolling(window=26, min_periods=26).mean()).ewm(adjust=False, alpha=float(1)/10, min_periods=0, ignore_na=False).mean()
    return part2.iloc[-1]

def alpha170(data, dependencies=['closePrice','turnoverVol','highestPrice', 'turnoverValue'], max_window=20):
    # ((RANK(1/CLOSE)*VOLUME)/MEAN(VOLUME,20))*(HIGH*RANK(HIGH-CLOSE)/(SUM(HIGH,5)/5))-RANK(VWAP-DELAY(VWAP,5))
    vwap = data['turnoverValue']/data['turnoverVol']
    part1 = (1.0/data['closePrice']).rank(axis=0,pct=True) * data['turnoverVol'] / (data['turnoverVol'].rolling(window=20,min_periods=20).mean())
    part2 = ((data['highestPrice']-data['closePrice']).rank(axis=0,pct=True) * data['highestPrice']) / (data['highestPrice'].rolling(window=5,min_periods=5).sum()/5.0)
    part3 = (vwap.diff(5)).rank(axis=0,pct=True)
    return (part1*part2-part3).iloc[-1]
    
def alpha171(data, dependencies=['lowestPrice', 'closePrice', 'openPrice', 'highestPrice'], max_window=1):
    # (-1*(LOW-CLOSE)*(OPEN^5))/((CLOSE-HIGH)*(CLOSE^5))
    part1 = (data['lowestPrice']-data['closePrice']) * (data['openPrice'] ** 5) * (-1)
    part2 = (data['closePrice']-data['highestPrice']) * (data['closePrice'] ** 5)
    return (part1 / part2).iloc[-1]

def alpha172(data, dependencies=['ADX'], max_window=20):
    # 就是DMI-ADX
    # HD  HIGH-DELAY(HIGH,1)
    # LD  DELAY(LOW,1)-LOW
    # TR  MAX(MAX(HIGH-LOW,ABS(HIGH-DELAY(CLOSE,1))),ABS(LOW-DELAY(CLOSE,1)))

    # MEAN(ABS(
    #     SUM((LD>0&LD>HD)?LD:0,14)*100/SUM(TR,14)
    #     -SUM((HD>0&HD>LD)?HD:0,14)*100/SUM(TR,14))
    # /(SUM((LD>0&LD>HD)?LD:0,14)*100/SUM(TR,14)
    #     +SUM((HD>0&HD>LD)?HD:0,14)*100/SUM(TR,14))
    # *100,6)
    hd=data['highestPrice'].diff(1)
    ld=-data['lowestPrice'].diff(1)
    tr=np.maximum(np.maximum(data['highestPrice']-data['lowestPrice'],(data['highestPrice']-data['closePrice'].shift(1)).abs()),(data['lowestPrice']-data['closePrice'].shift(1)).abs())
    part1=(((ld>0)&(ld>hd))*ld).rolling(window=14, min_periods=14).sum()*100/tr.rolling(window=14, min_periods=14).sum()-(((hd>0)&(hd>ld))*hd).rolling(window=14, min_periods=14).sum()*100/tr.rolling(window=14, min_periods=14).sum()
    part2=(((ld>0)&(ld>hd))*ld).rolling(window=14, min_periods=14).sum()*100/tr.rolling(window=14, min_periods=14).sum()+(((hd>0)&(hd>ld))*hd).rolling(window=14, min_periods=14).sum()*100/tr.rolling(window=14, min_periods=14).sum()
    return (part1/part2).abs().mean()*100

def alpha173(data, dependencies=['closePrice'], max_window=39):
    # 3*SMA(CLOSE,13,2)-2*SMA(SMA(CLOSE,13,2),13,2)+SMA(SMA(SMA(LOG(CLOSE),13,2),13,2),13,2)
    den = data['closePrice'].ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()
    part1 = 3 * den
    part2 = 2 * (den.ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean())
    part3 = ((np.log(data['closePrice']).ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()) .ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()) .ewm(adjust=False, alpha=float(2)/13, min_periods=0, ignore_na=False).mean()
    return (part1 -part2 + part3).iloc[-1]

def alpha174(data, dependencies=['closePrice'], max_window=41):
    # SMA((CLOSE>DELAY(CLOSE,1)?STD(CLOSE,20):0),20,1)
    part1 = data['closePrice'].rolling(window=20,min_periods=20).std()
    part1[data['closePrice'].diff(1)<=0] = 0.0
    return part1.ewm(adjust=False, alpha=float(1)/20, min_periods=0, ignore_na=False).mean().iloc[-1]

def alpha175(data, dependencies=['lowestPrice','highestPrice','closePrice'], max_window=7):
    # MEAN(MAX(MAX(HIGH-LOW,ABS(DELAY(CLOSE,1)-HIGH)),ABS(DELAY(CLOSE,1)-LOW)),6)
    alpha = np.maximum(data['highestPrice']-data['lowestPrice'], abs(data['closePrice'].shift(1)-data['highestPrice']))
    alpha = np.maximum(alpha, abs(data['closePrice'].shift(1)-data['lowestPrice']))
    return alpha.rolling(window=6,min_periods=6).mean().iloc[-1]

def alpha176(data, dependencies=['closePrice','highestPrice','lowestPrice','turnoverVol'], max_window=18):
    # CORR(RANK((CLOSE-TSMIN(LOW,12))/(TSMAX(HIGH,12)-TSMIN(LOW,12))),RANK(VOLUME),6)
    part1 = ((data['closePrice'] - data['lowestPrice'].rolling(window=12,min_periods=12).min()) / (data['highestPrice'].rolling(window=12,min_periods=12).max()-data['lowestPrice'].rolling(window=12,min_periods=12).min())).rank(axis=0, pct=True)
    part2 = data['turnoverVol'].rank(axis=0, pct=True)
    return part1.rolling(window=6,min_periods=6).corr(part2).iloc[-1]

def alpha177(data, dependencies=['highestPrice'], max_window=20):
    # ((20-HIGHDAY(HIGH,20))/20)*100
    return (20 - data['highestPrice'].rolling(window=20, min_periods=20).apply(lambda x: 19-x.argmax(axis=0))).iloc[-1] * 5.0

def alpha178(data, dependencies=['closePrice', 'turnoverVol'], max_window=2):
    # (CLOSE-DELAY(CLOSE,1))/DELAY(CLOSE,1)*VOLUME
    return (data['closePrice'].pct_change(periods=1) * data['turnoverVol']).iloc[-1]

def alpha179(data, dependencies=['lowestPrice','turnoverValue','turnoverVol'], max_window=62):
    # RANK(CORR(VWAP,VOLUME,4))*RANK(CORR(RANK(LOW),RANK(MEAN(VOLUME,50)),12))
    part1 = ((data['turnoverValue']/data['turnoverVol']).rolling(window=4,min_periods=4).corr(data['turnoverVol'])).rank(axis=0,pct=True)
    part2 = (((data['turnoverVol'].rolling(window=50,min_periods=50).mean()).rank(axis=0,pct=True)).rolling(window=12,min_periods=12).corr(data['lowestPrice'].rank(axis=0,pct=True))).rank(axis=0,pct=True)
    return (part1 * part2).iloc[-1]

def alpha180(data, dependencies=['turnoverVol', 'closePrice'], max_window=68):
    # (MEAN(VOLUME,20)<VOLUME)?((-1*TSRANK(ABS(DELTA(CLOSE,7)),60))*SIGN(DELTA(CLOSE,7)):(-1*VOLUME))
    condition = data['turnoverVol'].rolling(window=20, min_periods=20).mean() < data['turnoverVol']
    alpha = abs(data['closePrice'].diff(7)).rolling(window=60, min_periods=60).apply(lambda x: stats.rankdata(x)[-1]/60.0) * np.sign(data['closePrice'].diff(7)) * (-1)
    alpha[~condition] = -1 * data['turnoverVol'][~condition]
    return alpha.iloc[-1]

def alpha181(data, dependencies=['closePrice'], max_window=40):
    # SUM(RET-MEAN(RET,20)-(BANCHMARK_INDEX_CLOSE-MEAN(BANCHMARK_INDEX_CLOSE,20))^2,20)/SUM((BANCHMARK_INDEX_CLOSE-MEAN(BANCHMARK_INDEX_CLOSE,20))^3)
    bm = data['closePrice'].mean()
    bm_mean = bm - bm.rolling(window=20, min_periods=20).mean()
    bm_mean = pd.DataFrame(data=np.repeat(bm_mean.values.reshape(len(bm_mean.values),1), len(data['closePrice'].columns), axis=1), index=data['closePrice'].index, columns=data['closePrice'].columns)
    ret = data['closePrice'].pct_change(periods=1)
    part1 = (ret-ret.rolling(window=20,min_periods=20).mean()-bm_mean**2).rolling(window=20,min_periods=20).sum()
    part2 = (bm_mean ** 3).rolling(window=20,min_periods=20).sum()
    return (part1 / part2).iloc[-1]

def alpha182(data, dependencies=['closePrice','openPrice'], max_window=20):
    # COUNT((CLOSE>OPEN & BANCHMARK_INDEX_CLOSE>BANCHMARK_INDEX_OPEN) OR (CLOSE<OPEN &BANCHMARK_INDEX_CLOSE<BANCHMARK_INDEX_OPEN),20)/20
    bm = data['closePrice'].mean(axis=1) > data['openPrice'].mean(axis=1)
    bm = pd.DataFrame(data=np.repeat(bm.values.reshape(len(bm.values),1), len(data['closePrice'].columns), axis=1), index=data['closePrice'].index, columns=data['closePrice'].columns)
    condition1 = np.logical_and(data['closePrice']>data['openPrice'], bm)
    condition2 = np.logical_and(data['closePrice']<data['openPrice'], ~bm)
    return np.logical_or(condition1, condition2).rolling(window=20, min_periods=20).mean().iloc[-1]
    
def alpha183(data, dependencies=['closePrice'], max_window=72):
    # MAX(SUMAC(CLOSE-MEAN(CLOSE,24)))-MIN(SUMAC(CLOSE-MEAN(CLOSE,24)))/STD(CLOSE,24)
    part1 = ((data['closePrice']-data['closePrice'].rolling(window=24,min_periods=24).mean()).rolling(window=24,min_periods=24).sum()).rolling(window=24,min_periods=24).max()
    part2 = ((data['closePrice']-data['closePrice'].rolling(window=24,min_periods=24).mean()).rolling(window=24,min_periods=24).sum()).rolling(window=24,min_periods=24).min()
    part3 = data['closePrice'].rolling(window=24,min_periods=24).std()
    return (part1-part2/part3).iloc[-1]

def alpha184(data, dependencies=['closePrice','openPrice'], max_window=201):
    # RANK(CORR(DELAY(OPEN-CLOSE,1),CLOSE,200))+RANK(OPEN-CLOSE)
    part1 = (((data['openPrice']-data['closePrice']).shift(1)).rolling(window=200,min_periods=200).corr(data['closePrice'])).rank(axis=0,pct=True)
    part2 = (data['openPrice']-data['closePrice']).rank(axis=0,pct=True)
    return (part1+part2).iloc[-1]

def alpha185(data, dependencies=['closePrice', 'openPrice'], max_window=1):
    # RANK(-1*(1-OPEN/CLOSE)^2)
    return ((1.0-data['openPrice']/data['closePrice']).iloc[-1] ** 2) * (-1)

def alpha186(data, dependencies=['ADXR'], max_window=1):
    # \u5c31\u662fADXR
#     (MEAN(ABS(SUM((LD>0  &  LD>HD)?LD:0,14)*100/SUM(TR,14)-SUM((HD>0  &
# HD>LD)?HD:0,14)*100/SUM(TR,14))/(SUM((LD>0  &  LD>HD)?LD:0,14)*100/SUM(TR,14)+SUM((HD>0  &
# HD>LD)?HD:0,14)*100/SUM(TR,14))*100,6)+DELAY(MEAN(ABS(SUM((LD>0  &
# LD>HD)?LD:0,14)*100/SUM(TR,14)-SUM((HD>0  &  HD>LD)?HD:0,14)*100/SUM(TR,14))/(SUM((LD>0  &
# LD>HD)?LD:0,14)*100/SUM(TR,14)+SUM((HD>0 & HD>LD)?HD:0,14)*100/SUM(TR,14))*100,6),6))/2
    return data['ADXR'].iloc[-1]

def alpha187(data, dependencies=['openPrice', 'highestPrice'], max_window=21):
    # SUM(OPEN<=DELAY(OPEN,1)?0:MAX(HIGH-OPEN,OPEN-DELAY(OPEN,1)),20)
    part1 = np.maximum(data['highestPrice']-data['openPrice'], data['openPrice'].diff(1))
    part1[data['openPrice'].diff(1)<=0] = 0.0
    return part1.rolling(window=20, min_periods=20).sum().iloc[-1]

def alpha188(data, dependencies=['lowestPrice', 'highestPrice'], max_window=11):
    # ((HIGH-LOW\u2013SMA(HIGH-LOW,11,2))/SMA(HIGH-LOW,11,2))*100
    sma = (data['highestPrice']-data['lowestPrice']).ewm(adjust=False, alpha=float(2)/11, min_periods=0, ignore_na=False).mean()
    return ((data['highestPrice']-data['lowestPrice']-sma)/sma).iloc[-1] * 100

def alpha189(data, dependencies=['closePrice'], max_window=12):
    # MEAN(ABS(CLOSE-MEAN(CLOSE,6)),6)
    return abs(data['closePrice']-data['closePrice'].rolling(window=6,min_periods=6).mean()).rolling(window=6,min_periods=6).mean().iloc[-1]

def alpha190(data, dependencies=['closePrice'], max_window=40):
    # LOG((COUNT(RET>((CLOSE/DELAY(CLOSE,19))^(1/20)-1),20)-1)
    # *SUMIF((RET-(CLOSE/DELAY(CLOSE,19))^(1/20)-1)^2,20,RET<(CLOSE/DELAY(CLOSE,19))^(1/20)-1)
    # /(COUNT(RET<(CLOSE/DELAY(CLOSE,19))^(1/20)-1,20)
    # *SUMIF((RET-((CLOSE/DELAY(CLOSE,19))^(1/20)-1))^2,20,RET>(CLOSE/DELAY(CLOSE,19))^(1/20)-1)))
    ret = data['closePrice'].pct_change(periods=1)
    ret_19 = (data['closePrice']/data['closePrice'].shift(19))**0.05-1.0
    part1 = (ret>ret_19).rolling(window=20, min_periods=20).sum()-1.0
    part2 = (np.minimum(ret-ret_19, 0.0) ** 2).rolling(window=20,min_periods=20).sum()
    part3 = (ret<ret_19).rolling(window=20, min_periods=20).sum()
    part4 = (np.maximum(ret-ret_19, 0.0) ** 2).rolling(window=20,min_periods=20).sum()
    return np.log(part1*part2/part3/part4).iloc[-1]

def alpha191(data, dependencies=['turnoverVol', 'lowestPrice', 'closePrice', 'highestPrice'], max_window=25):
    # CORR(MEAN(VOLUME,20),LOW,5)+(HIGH+LOW)/2-CLOSE
    part1 = (data['turnoverVol'].rolling(window=20,min_periods=20).mean()).rolling(window=5,min_periods=5).corr(data['lowestPrice'])
    return (part1 + data['highestPrice']*0.5+data['lowestPrice']*0.5-data['closePrice']).iloc[-1]

源码模块:xg_quant_backtrader_data.py

小果远程数据 / 回测 API 客户端

'''
作者:小果
微信:xg_quant
'''
import requests
import json
import pandas as pd
import numpy as np
from typing import Optional, Dict, Any, List, Union
from datetime import datetime
import urllib.parse
class xg_quant_backtrader_data:
    """
    小果量化回测系统数据api
    小果量化数据 - API对接框架
    """
    
    def __init__(
        self,
        url: str = "自定义",
        port: int = 8888,  # 修复:port应该是int类型
        user: str = '自定义',
        password: str = '自定义',
        auth_code: str = '自定义'
    ):
        """
        初始化小果量化数据客户端
        
        Args:
            url: 服务器地址
            port: 服务器端口
            user: 用户名称
            password: 用户密码
            auth_code: 授权码
        """
        self.url = url
        self.port = port
        self.user = user
        self.password = password
        self.auth_code = auth_code
        self.base_url = f"http://{url}:{port}"
        self.session = requests.Session()
        self.timeout = 120
        
        # 设置默认请求头
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'application/json',
            'Accept-Charset': 'utf-8'
        })
    
    def _get_params(self, **kwargs) -> Dict[str, Any]:
        """构建请求参数,自动添加用户认证信息"""
        params = {
            'user': self.user,
            'password': self.password,
            'auth_code': self.auth_code,
        }
        params.update(kwargs)
        return params
    
    def _request(
        self,
        endpoint: str,
        params: Dict[str, Any],
        method: str = 'GET',
        timeout: Optional[int] = None,
        verbose: bool = True
    ) -> Dict[str, Any]:
        """
        发送HTTP请求
        
        Args:
            endpoint: API端点路径
            params: 请求参数
            method: 请求方法
            timeout: 超时时间
            verbose: 是否打印详细信息
        
        Returns:
            响应数据字典
        """
        if timeout is None:
            timeout = self.timeout
        
        url = f"{self.base_url}{endpoint}"
        
        # 清理参数中的None值
        clean_params = {k: v for k, v in params.items() if v is not None}
        
        try:
            if method.upper() == 'GET':
                response = self.session.get(url, params=clean_params, timeout=timeout)
            else:
                response = self.session.post(url, params=clean_params, timeout=timeout)
            
            if verbose:
                print(f"📤 请求URL: {response.url[:100]}...")
                print(f"📤 状态码: {response.status_code}")
            
            response.raise_for_status()
            
            # 尝试解析JSON
            try:
                result = response.json()
                if verbose and result.get('status') == 'failed':
                    print(f"❌ 接口返回失败: {result.get('message', result.get('error', '未知错误'))}")
                    if 'info' in result:
                        print(f"📄 详细信息: {result.get('info')}")
                return result
            except json.JSONDecodeError as e:
                print(f"❌ JSON解析失败: {e}")
                print(f"📄 响应内容: {response.text[:500]}")
                return {"status": "failed", "error": "Invalid JSON response", "raw": response.text[:500]}
            
        except requests.exceptions.RequestException as e:
            print(f"❌ 请求失败: {e}")
            # 尝试获取更多错误信息
            if hasattr(e, 'response') and e.response is not None:
                try:
                    error_detail = e.response.json()
                    print(f"📄 错误详情: {error_detail}")
                    return {"status": "failed", "error": str(e), "detail": error_detail}
                except:
                    print(f"📄 响应内容: {e.response.text[:500]}")
                    return {"status": "failed", "error": str(e), "raw": e.response.text[:500]}
            return {"status": "failed", "error": str(e)}
    
    def _to_dataframe(self, data: Dict[str, Any]) -> pd.DataFrame:
        """
        将API返回的数据转换为DataFrame
        处理NaN和Infinity值
        """
        if data.get('status') == 'failed':
            print(f"⚠️ 数据获取失败: {data.get('message', data.get('error', '未知错误'))}")
            return pd.DataFrame()
        
        if 'data' in data and data['data']:
            df = pd.DataFrame(data['data'])
            # 清理数据:将NaN、Infinity替换为None
            df = df.replace([np.inf, -np.inf], np.nan)
            df = df.where(pd.notnull(df), None)
            return df
        
        return pd.DataFrame()
    
    def _to_dataframe_with_info(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """将API返回的数据转换为包含元信息的DataFrame"""
        if data.get('status') == 'failed':
            return {
                'status': 'failed', 
                'data': pd.DataFrame(), 
                'info': data.get('message', data.get('error', '未知错误'))
            }
        
        df = pd.DataFrame(data.get('data', []))
        # 清理数据
        df = df.replace([np.inf, -np.inf], np.nan)
        df = df.where(pd.notnull(df), None)
        
        result = {
            'status': data.get('status', 'success'),
            'data': df,
            'total': data.get('total', len(df)),
            'message': data.get('message', ''),
            'available_columns': data.get('available_columns', []),
            'selected_columns': data.get('selected_columns', []),
        }
        for key in ['stock', 'start_date', 'end_date', 'table', 'report_date']:
            if key in data:
                result[key] = data[key]
        return result

    # ============================================================
    # 一、回测接口(类方法名不带数字,但请求路径带 _1)
    # ============================================================
    
    def xg_dt_backtrader(
        self,
        start_date: str = '20260701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        dt_interval: int = 20,
        dt_type: str = '金额',
        dt_value: float = 1000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """定投回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, dt_interval=dt_interval,
            dt_type=dt_type, dt_value=dt_value, sell_zdf=sell_zdf,
            buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_dt_backtrader_1', params)
    
    def xg_mom_backtrader(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        mom_type: str = '百分比',
        mom_value: float = 1,
        mom_daily: int = 25,
        min_mom: float = 0,
        max_mom: float = 5,
        buy_rank: int = 1,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000
    ) -> Dict[str, Any]:
        """动量回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            mom_type=mom_type, mom_value=mom_value, mom_daily=mom_daily,
            min_mom=min_mom, max_mom=max_mom, buy_rank=buy_rank,
            sell_zdf=sell_zdf, sell_amount=sell_amount
        )
        return self._request('/xg_mom_backtrader_1', params)
    
    def xg_pz_backtrader(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.4,0.4,0.2',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, index_stock=index_stock,
            cash=cash, sell_zdf=sell_zdf, buy_zdf=buy_zdf,
            trade_value=trade_value, comm=comm
        )
        return self._request('/xg_pz_backtrader_1', params)
    
    def xg_zcph_backtrader(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.35,0.35,0.3',
        deviation_list: str = '0.1,0.1,0.05',
        interval: int = 20,
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置平衡策略回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, deviation_list=deviation_list,
            interval=interval, index_stock=index_stock, cash=cash,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_zcph_backtrader_1', params)
    
    def xg_gd_backtrader(
        self,
        start_date: str = '20250701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        gd_interval: int = 1,
        gd_bc_type_list: str = '百分比,百分比',
        gd_buy_bc_list: str = '0.03,0.02',
        gd_sell_bc_list: str = '-0.02,-0.015',
        gd_atr_ratio_list: str = '2.0,2.0',
        gd_atr_period_list: str = '14,14',
        gd_type_list: str = '金额,金额',
        gd_value_list: str = '1000,1500',
        init_position_ratio_list: str = '0.1,0.15',
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001,
        max_workers: int = 4
    ) -> Dict[str, Any]:
        """网格策略回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, gd_interval=gd_interval,
            gd_bc_type_list=gd_bc_type_list, gd_buy_bc_list=gd_buy_bc_list,
            gd_sell_bc_list=gd_sell_bc_list, gd_atr_ratio_list=gd_atr_ratio_list,
            gd_atr_period_list=gd_atr_period_list, gd_type_list=gd_type_list,
            gd_value_list=gd_value_list, init_position_ratio_list=init_position_ratio_list,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value,
            comm=comm, max_workers=max_workers
        )
        return self._request('/xg_gd_backtrader_1', params)
    
    def xg_hg_backtrader(
        self,
        start_date: str = '20240101',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        entry_period: int = 20,
        exit_period: int = 10,
        n_period: int = 20,
        risk_per_trade: float = 0.01,
        risk_per_unit: float = 0.02,
        max_units: int = 4,
        add_unit_threshold: float = 0.5,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000
    ) -> Dict[str, Any]:
        """海龟策略回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, entry_period=entry_period,
            exit_period=exit_period, n_period=n_period,
            risk_per_trade=risk_per_trade, risk_per_unit=risk_per_unit,
            max_units=max_units, add_unit_threshold=add_unit_threshold,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value
        )
        return self._request('/xg_hg_backtrader_1', params)
    
    def xg_more_mom_backtrader(
        self,
        start_date: str = '20250101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        enable_index_timing: bool = False,
        index_mean_line: int = 20,
        index_not_trader: str = '513100.SH,518880.SH',
        index_condition_type: str = '大于均线',
        index_offset: float = 0.0,
        mom_type: str = '百分比',
        mom_value: float = 0.1,
        mom_models: str = '动量1',
        mom_daily: int = 25,
        period: int = 20,
        short_ma: int = 3,
        long_ma: int = 20,
        enable_mom_filter: bool = False,
        max_value: float = 5,
        mini_value: float = 0,
        max_rank: int = 1,
        min_rank: int = 2,
        enable_buy_condition: bool = False,
        enable_sell_condition: bool = False,
        buy_condition_type: str = '涨幅',
        buy_period: int = 20,
        buy_period_ratio: float = 0.1,
        buy_offset: float = 0.0,
        sell_condition_type: str = '跌幅',
        sell_period: int = 20,
        sell_period_ratio: float = -0.1,
        sell_offset: float = 0.0,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000,
        interval: int = 1
    ) -> Dict[str, Any]:
        """综合动量回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, enable_index_timing=enable_index_timing,
            index_mean_line=index_mean_line, index_not_trader=index_not_trader,
            index_condition_type=index_condition_type, index_offset=index_offset,
            mom_type=mom_type, mom_value=mom_value, mom_models=mom_models,
            mom_daily=mom_daily, period=period, short_ma=short_ma,
            long_ma=long_ma, enable_mom_filter=enable_mom_filter,
            max_value=max_value, mini_value=mini_value,
            max_rank=max_rank, min_rank=min_rank,
            enable_buy_condition=enable_buy_condition,
            enable_sell_condition=enable_sell_condition,
            buy_condition_type=buy_condition_type, buy_period=buy_period,
            buy_period_ratio=buy_period_ratio, buy_offset=buy_offset,
            sell_condition_type=sell_condition_type, sell_period=sell_period,
            sell_period_ratio=sell_period_ratio, sell_offset=sell_offset,
            sell_zdf=sell_zdf, sell_amount=sell_amount, interval=interval
        )
        return self._request('/xg_more_mom_backtrader_1', params)
    
    def xg_condi_factor_backtrader(
        self,
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),True,False)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        buy_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "and", "选择方向": "等于", "值": true},
            "连续上涨天数": {"选择类型": "and", "选择方向": "大于", "值": 2}
        }''',
        rank_factor: str = '''{
            "均线评分": "降序"
        }''',
        sell_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "or", "选择方向": "等于", "值": false},
            "连续下跌天数": {"选择类型": "or", "选择方向": "大于", "值": 2}
        }''',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """条件因子回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            sell_condi_factor=sell_condi_factor,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_condi_factor_backtrader_1', params)
    
    def xg_rank_factor_backtrader(
        self,
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),0,1)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        is_open_buy_condi: bool = True,
        buy_condi_factor: str = '''{
            "25日回归动量": {"选择类型": "and", "选择方向": "大于", "值": 0},
            "25日回归动量": {"选择类型": "and", "选择方向": "小于", "值": 5}
        }''',
        rank_factor: str = '''{
            "25日回归动量": {"相关性": "正相关", "权重": 1}
        }''',
        total_factor_rank: str = '降序',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """排序多因子回测接口"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            is_open_buy_condi=is_open_buy_condi,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            total_factor_rank=total_factor_rank,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_rank_factor_backtrader_1', params)

    # ============================================================
    # 二、策略模拟交易接口(moni,不带 _1)
    # ============================================================
    
    def xg_dt_backtrader_moni(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        dt_interval: int = 20,
        dt_type: str = '金额',
        dt_value: float = 1000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """定投策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, dt_interval=dt_interval,
            dt_type=dt_type, dt_value=dt_value, sell_zdf=sell_zdf,
            buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_dt_backtrader_moni', params)
    
    def xg_mom_backtrader_moni(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        mom_type: str = '百分比',
        mom_value: float = 1,
        mom_daily: int = 25,
        min_mom: float = 0,
        max_mom: float = 5,
        buy_rank: int = 1,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000
    ) -> Dict[str, Any]:
        """动量策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            mom_type=mom_type, mom_value=mom_value, mom_daily=mom_daily,
            min_mom=min_mom, max_mom=max_mom, buy_rank=buy_rank,
            sell_zdf=sell_zdf, sell_amount=sell_amount
        )
        return self._request('/xg_mom_backtrader_moni', params)
    
    def xg_pz_backtrader_moni(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.4,0.4,0.2',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, index_stock=index_stock,
            cash=cash, sell_zdf=sell_zdf, buy_zdf=buy_zdf,
            trade_value=trade_value, comm=comm
        )
        return self._request('/xg_pz_backtrader_moni', params)
    
    def xg_zcph_backtrader_moni(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.35,0.35,0.3',
        deviation_list: str = '0.1,0.1,0.05',
        interval: int = 20,
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置平衡策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, deviation_list=deviation_list,
            interval=interval, index_stock=index_stock, cash=cash,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_zcph_backtrader_moni', params)
    
    def xg_gd_backtrader_moni(
        self,
        st_name: str = '小果网格测试策略',
        open_show: str = '是',
        start_date: str = '20250701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        gd_interval: int = 1,
        gd_bc_type_list: str = '百分比,百分比',
        gd_buy_bc_list: str = '0.03,0.02',
        gd_sell_bc_list: str = '-0.02,-0.015',
        gd_atr_ratio_list: str = '2.0,2.0',
        gd_atr_period_list: str = '14,14',
        gd_type_list: str = '金额,金额',
        gd_value_list: str = '1000,1500',
        init_position_ratio_list: str = '0.1,0.15',
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001,
        max_workers: int = 4
    ) -> Dict[str, Any]:
        """网格策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, gd_interval=gd_interval,
            gd_bc_type_list=gd_bc_type_list, gd_buy_bc_list=gd_buy_bc_list,
            gd_sell_bc_list=gd_sell_bc_list, gd_atr_ratio_list=gd_atr_ratio_list,
            gd_atr_period_list=gd_atr_period_list, gd_type_list=gd_type_list,
            gd_value_list=gd_value_list,
            init_position_ratio_list=init_position_ratio_list,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value,
            comm=comm, max_workers=max_workers
        )
        return self._request('/xg_gd_backtrader_moni', params)
    
    def xg_hg_backtrader_moni(
        self,
        st_name: str = '小果海龟测试策略',
        open_show: str = '是',
        start_date: str = '20240101',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        entry_period: int = 20,
        exit_period: int = 10,
        n_period: int = 20,
        risk_per_trade: float = 0.01,
        risk_per_unit: float = 0.02,
        max_units: int = 4,
        add_unit_threshold: float = 0.5,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000
    ) -> Dict[str, Any]:
        """海龟策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, entry_period=entry_period,
            exit_period=exit_period, n_period=n_period,
            risk_per_trade=risk_per_trade, risk_per_unit=risk_per_unit,
            max_units=max_units, add_unit_threshold=add_unit_threshold,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value
        )
        return self._request('/xg_hg_backtrader_moni', params)
    
    def xg_more_mom_backtrader_moni(
        self,
        st_name: str = '小果综合动量测试策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        enable_index_timing: bool = False,
        index_mean_line: int = 20,
        index_not_trader: str = '513100.SH,518880.SH',
        index_condition_type: str = '大于均线',
        index_offset: float = 0.0,
        mom_type: str = '百分比',
        mom_value: float = 0.1,
        mom_models: str = '动量1',
        mom_daily: int = 25,
        period: int = 20,
        short_ma: int = 3,
        long_ma: int = 20,
        enable_mom_filter: bool = False,
        max_value: float = 5,
        mini_value: float = 0,
        max_rank: int = 1,
        min_rank: int = 2,
        enable_buy_condition: bool = False,
        enable_sell_condition: bool = False,
        buy_condition_type: str = '涨幅',
        buy_period: int = 20,
        buy_period_ratio: float = 0.1,
        buy_offset: float = 0.0,
        sell_condition_type: str = '跌幅',
        sell_period: int = 20,
        sell_period_ratio: float = -0.1,
        sell_offset: float = 0.0,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000,
        interval: int = 1
    ) -> Dict[str, Any]:
        """综合动量策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, enable_index_timing=enable_index_timing,
            index_mean_line=index_mean_line, index_not_trader=index_not_trader,
            index_condition_type=index_condition_type, index_offset=index_offset,
            mom_type=mom_type, mom_value=mom_value, mom_models=mom_models,
            mom_daily=mom_daily, period=period, short_ma=short_ma,
            long_ma=long_ma, enable_mom_filter=enable_mom_filter,
            max_value=max_value, mini_value=mini_value,
            max_rank=max_rank, min_rank=min_rank,
            enable_buy_condition=enable_buy_condition,
            enable_sell_condition=enable_sell_condition,
            buy_condition_type=buy_condition_type, buy_period=buy_period,
            buy_period_ratio=buy_period_ratio, buy_offset=buy_offset,
            sell_condition_type=sell_condition_type, sell_period=sell_period,
            sell_period_ratio=sell_period_ratio, sell_offset=sell_offset,
            sell_zdf=sell_zdf, sell_amount=sell_amount, interval=interval
        )
        return self._request('/xg_more_mom_backtrader_moni', params)
    
    def xg_condi_factor_backtrader_moni(
        self,
        st_name: str = '小果条件因子测试策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),True,False)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        buy_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "and", "选择方向": "等于", "值": true},
            "连续上涨天数": {"选择类型": "and", "选择方向": "大于", "值": 2}
        }''',
        rank_factor: str = '''{
            "均线评分": "降序"
        }''',
        sell_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "or", "选择方向": "等于", "值": false},
            "连续下跌天数": {"选择类型": "or", "选择方向": "大于", "值": 2}
        }''',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """条件多因子策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            sell_condi_factor=sell_condi_factor,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_condi_factor_backtrader_moni', params)
    
    def xg_rank_factor_backtrader_moni(
        self,
        st_name: str = '小果排序多因子模拟策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),0,1)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        is_open_buy_condi: bool = True,
        buy_condi_factor: str = '''{
            "25日回归动量": {"选择类型": "and", "选择方向": "大于", "值": 0},
            "25日回归动量": {"选择类型": "and", "选择方向": "小于", "值": 5}
        }''',
        rank_factor: str = '''{
            "25日回归动量": {"相关性": "正相关", "权重": 1}
        }''',
        total_factor_rank: str = '降序',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """排序多因子策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            is_open_buy_condi=is_open_buy_condi,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            total_factor_rank=total_factor_rank,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_rank_factor_backtrader_moni', params)

    # ============================================================
    # 三、社区策略接口(moni_sq,不带 _1)
    # ============================================================
    
    def xg_dt_backtrader_moni_sq(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        dt_interval: int = 20,
        dt_type: str = '金额',
        dt_value: float = 1000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """定投策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, dt_interval=dt_interval,
            dt_type=dt_type, dt_value=dt_value, sell_zdf=sell_zdf,
            buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_dt_backtrader_moni_sq', params)
    
    def xg_mom_backtrader_moni_sq(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        mom_type: str = '百分比',
        mom_value: float = 1,
        mom_daily: int = 25,
        min_mom: float = 0,
        max_mom: float = 5,
        buy_rank: int = 1,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000
    ) -> Dict[str, Any]:
        """动量策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            mom_type=mom_type, mom_value=mom_value, mom_daily=mom_daily,
            min_mom=min_mom, max_mom=max_mom, buy_rank=buy_rank,
            sell_zdf=sell_zdf, sell_amount=sell_amount
        )
        return self._request('/xg_mom_backtrader_moni_sq', params)
    
    def xg_pz_backtrader_moni_sq(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.4,0.4,0.2',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, index_stock=index_stock,
            cash=cash, sell_zdf=sell_zdf, buy_zdf=buy_zdf,
            trade_value=trade_value, comm=comm
        )
        return self._request('/xg_pz_backtrader_moni_sq', params)
    
    def xg_zcph_backtrader_moni_sq(
        self,
        st_name: str = '小果测试',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        dt_type: str = '百分比',
        weight_list: str = '0.35,0.35,0.3',
        deviation_list: str = '0.1,0.1,0.05',
        interval: int = 20,
        index_stock: str = '000300.SH',
        cash: float = 100000,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001
    ) -> Dict[str, Any]:
        """资产配置平衡策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            dt_type=dt_type, weight_list=weight_list, deviation_list=deviation_list,
            interval=interval, index_stock=index_stock, cash=cash,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value, comm=comm
        )
        return self._request('/xg_zcph_backtrader_moni_sq', params)
    
    def xg_gd_backtrader_moni_sq(
        self,
        st_name: str = '小果网格测试策略',
        open_show: str = '是',
        start_date: str = '20250701',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        gd_interval: int = 1,
        gd_bc_type_list: str = '百分比,百分比',
        gd_buy_bc_list: str = '0.03,0.02',
        gd_sell_bc_list: str = '-0.02,-0.015',
        gd_atr_ratio_list: str = '2.0,2.0',
        gd_atr_period_list: str = '14,14',
        gd_type_list: str = '金额,金额',
        gd_value_list: str = '1000,1500',
        init_position_ratio_list: str = '0.1,0.15',
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000,
        comm: float = 0.0001,
        max_workers: int = 4
    ) -> Dict[str, Any]:
        """网格策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, gd_interval=gd_interval,
            gd_bc_type_list=gd_bc_type_list, gd_buy_bc_list=gd_buy_bc_list,
            gd_sell_bc_list=gd_sell_bc_list, gd_atr_ratio_list=gd_atr_ratio_list,
            gd_atr_period_list=gd_atr_period_list, gd_type_list=gd_type_list,
            gd_value_list=gd_value_list,
            init_position_ratio_list=init_position_ratio_list,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value,
            comm=comm, max_workers=max_workers
        )
        return self._request('/xg_gd_backtrader_moni_sq', params)
    
    def xg_hg_backtrader_moni_sq(
        self,
        st_name: str = '小果海龟测试策略',
        open_show: str = '是',
        start_date: str = '20240101',
        end_date: str = '20500101',
        stock_list: str = '513100.SH,513500.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        entry_period: int = 20,
        exit_period: int = 10,
        n_period: int = 20,
        risk_per_trade: float = 0.01,
        risk_per_unit: float = 0.02,
        max_units: int = 4,
        add_unit_threshold: float = 0.5,
        sell_zdf: float = 0.03,
        buy_zdf: float = -0.03,
        trade_value: float = 1000
    ) -> Dict[str, Any]:
        """海龟策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, entry_period=entry_period,
            exit_period=exit_period, n_period=n_period,
            risk_per_trade=risk_per_trade, risk_per_unit=risk_per_unit,
            max_units=max_units, add_unit_threshold=add_unit_threshold,
            sell_zdf=sell_zdf, buy_zdf=buy_zdf, trade_value=trade_value
        )
        return self._request('/xg_hg_backtrader_moni_sq', params)
    
    def xg_more_mom_backtrader_moni_sq(
        self,
        st_name: str = '小果综合动量测试策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        enable_index_timing: bool = False,
        index_mean_line: int = 20,
        index_not_trader: str = '513100.SH,518880.SH',
        index_condition_type: str = '大于均线',
        index_offset: float = 0.0,
        mom_type: str = '百分比',
        mom_value: float = 0.1,
        mom_models: str = '动量1',
        mom_daily: int = 25,
        period: int = 20,
        short_ma: int = 3,
        long_ma: int = 20,
        enable_mom_filter: bool = False,
        max_value: float = 5,
        mini_value: float = 0,
        max_rank: int = 1,
        min_rank: int = 2,
        enable_buy_condition: bool = False,
        enable_sell_condition: bool = False,
        buy_condition_type: str = '涨幅',
        buy_period: int = 20,
        buy_period_ratio: float = 0.1,
        buy_offset: float = 0.0,
        sell_condition_type: str = '跌幅',
        sell_period: int = 20,
        sell_period_ratio: float = -0.1,
        sell_offset: float = 0.0,
        sell_zdf: float = 0.03,
        sell_amount: float = 1000,
        interval: int = 1
    ) -> Dict[str, Any]:
        """综合动量策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, enable_index_timing=enable_index_timing,
            index_mean_line=index_mean_line, index_not_trader=index_not_trader,
            index_condition_type=index_condition_type, index_offset=index_offset,
            mom_type=mom_type, mom_value=mom_value, mom_models=mom_models,
            mom_daily=mom_daily, period=period, short_ma=short_ma,
            long_ma=long_ma, enable_mom_filter=enable_mom_filter,
            max_value=max_value, mini_value=mini_value,
            max_rank=max_rank, min_rank=min_rank,
            enable_buy_condition=enable_buy_condition,
            enable_sell_condition=enable_sell_condition,
            buy_condition_type=buy_condition_type, buy_period=buy_period,
            buy_period_ratio=buy_period_ratio, buy_offset=buy_offset,
            sell_condition_type=sell_condition_type, sell_period=sell_period,
            sell_period_ratio=sell_period_ratio, sell_offset=sell_offset,
            sell_zdf=sell_zdf, sell_amount=sell_amount, interval=interval
        )
        return self._request('/xg_more_mom_backtrader_moni_sq', params)
    
    def xg_condi_factor_backtrader_moni_sq(
        self,
        st_name: str = '小果条件因子测试策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),True,False)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        buy_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "and", "选择方向": "等于", "值": true},
            "连续上涨天数": {"选择类型": "and", "选择方向": "大于", "值": 2}
        }''',
        rank_factor: str = '''{
            "均线评分": "降序"
        }''',
        sell_condi_factor: str = '''{
            "收盘价大于5日均线": {"选择类型": "or", "选择方向": "等于", "值": false},
            "连续下跌天数": {"选择类型": "or", "选择方向": "大于", "值": 2}
        }''',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """条件多因子策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            sell_condi_factor=sell_condi_factor,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_condi_factor_backtrader_moni_sq', params)
    
    def xg_rank_factor_backtrader_moni_sq(
        self,
        st_name: str = '小果排序多因子社区策略',
        open_show: str = '是',
        start_date: str = '20250101',
        end_date: str = '20261201',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        min_commission: float = 0,
        trader_type: str = '百分比',
        trader_value: float = 0.5,
        hold_stock_limit: int = 2,
        is_open_user_factor: bool = True,
        user_factor_list: str = 'close,high,low,open,amount,volume,zdf',
        user_factor_cacal: str = '''{
            "收盘价大于5日均线": "IF(df['close']>MA(df['close'],5),0,1)",
            "均线评分": "IF(MA(df['close'],3)>MA(df['close'],5),25,0)+IF(MA(df['close'],5)>MA(df['close'],10),25,0)+IF(MA(df['close'],10)>MA(df['close'],20),25,0)+IF(MA(df['close'],20)>MA(df['close'],30),25,0)"
        }''',
        is_open_buy_condi: bool = True,
        buy_condi_factor: str = '''{
            "25日回归动量": {"选择类型": "and", "选择方向": "大于", "值": 0},
            "25日回归动量": {"选择类型": "and", "选择方向": "小于", "值": 5}
        }''',
        rank_factor: str = '''{
            "25日回归动量": {"相关性": "正相关", "权重": 1}
        }''',
        total_factor_rank: str = '降序',
        sell_type: str = '金额',
        sell_zdf: float = 0.03,
        sell_value: float = 1000,
        max_workers: int = 4,
        interval: int = 1,
        min_hold_days: int = 1,
        risk_free_rate: float = 0.02,
        slippage: float = 0,
        enable_limit_up_down_filter: bool = True,
        max_single_position_ratio: float = 1.0
    ) -> Dict[str, Any]:
        """排序多因子策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            min_commission=min_commission, trader_type=trader_type,
            trader_value=trader_value, hold_stock_limit=hold_stock_limit,
            is_open_user_factor=is_open_user_factor,
            user_factor_list=user_factor_list,
            user_factor_cacal=user_factor_cacal,
            is_open_buy_condi=is_open_buy_condi,
            buy_condi_factor=buy_condi_factor,
            rank_factor=rank_factor,
            total_factor_rank=total_factor_rank,
            sell_type=sell_type, sell_zdf=sell_zdf, sell_value=sell_value,
            max_workers=max_workers, interval=interval,
            min_hold_days=min_hold_days, risk_free_rate=risk_free_rate,
            slippage=slippage,
            enable_limit_up_down_filter=enable_limit_up_down_filter,
            max_single_position_ratio=max_single_position_ratio
        )
        return self._request('/xg_rank_factor_backtrader_moni_sq', params)

    # ============================================================
    # 四、数据读取接口
    # ============================================================
    
    def get_moni_trader_data(
        self,
        user: str = '自定义',
        st_type: str = '动量策略',
        st_name: str = '小果动量模拟策略'
    ) -> Dict[str, Any]:
        """读取模拟交易的统计数据"""
        params = self._get_params(user=user,st_type=st_type, st_name=st_name)
        return self._request('/get_moni_trader_data', params)
    
    def get_moni_trader_data_sq(
        self,
        user: str = '自定义',
        st_type: str = '动量策略',
        st_name: str = '小果动量模拟策略'
    ) -> Dict[str, Any]:
        """读取社区交易的统计数据"""
        params = self._get_params(user=user,st_type=st_type, st_name=st_name)
        return self._request('/get_moni_trader_data_sq', params)
    
    
    
    def get_stock_hist_data(
        self,
        stock: str = '513100.SH',
        start_date: str = '20200101',
        end_date: str = '20261231'
    ) -> Dict[str, Any]:
        """读取标的历史行情数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date
        )
        return self._request('/get_stock_hist_data', params)
    
    def get_stock_factor_data(
        self,
        stock: str = '513100.SH',
        start_date: str = '20200101',
        end_date: str = '20261231',
        columns: str = 'date,close,open,high,low,volume,amount'
    ) -> Dict[str, Any]:
        """读取标的因子数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            columns=columns
        )
        return self._request('/get_stock_factor_data', params)
    
    def get_stock_finance_data(
        self,
        table: str = '资产负债表',
        date: str = '2026-06-30',
        columns: str = 'secu_code,end_date,total_assets'
    ) -> Dict[str, Any]:
        """读取股票财务数据"""
        params = self._get_params(
            table=table,
            date=date,
            columns=columns
        )
        return self._request('/get_stock_finance_data', params)
        # ============================================================
    # 四、策略删除接口(单个)
    # ============================================================
    
    def del_moni_trader_data(
        self,
        user: str = '自定义',
        st_type: str = '定投策略',
        st_name: str = '小果定投模拟策略公开',
        open_show: str = '是'
    ) -> Dict[str, Any]:
        """删除模拟策略数据"""
        params = self._get_params(
            user=user,
            st_type=st_type,
            st_name=st_name,
            open_show=open_show
        )
        return self._request('/del_moni_trader_data', params)
    
    def del_moni_trader_data_sq(
        self,
        user: str = '自定义',
        st_type: str = '定投策略',
        st_name: str = '小果定投模拟策略公开',
        open_show: str = '是'
    ) -> Dict[str, Any]:
        """删除社区策略数据"""
        params = self._get_params(
            user=user,
            st_type=st_type,
            st_name=st_name,
            open_show=open_show
        )
        return self._request('/del_moni_trader_data_sq', params)

    # ============================================================
    # 五、批量策略管理接口
    # ============================================================
    
    def del_all_moni_trader_data(
        self,
        user: str = '自定义',
        confirm: str = '是'
    ) -> Dict[str, Any]:
        """删除全部模拟策略数据"""
        params = self._get_params(
            user=user,
            confirm=confirm
        )
        return self._request('/del_all_moni_trader_data', params)
    
    def del_all_moni_trader_data_sq(
        self,
        user: str = '自定义',
        confirm: str = '是'
    ) -> Dict[str, Any]:
        """删除全部社区策略数据"""
        params = self._get_params(
            user=user,
            confirm=confirm
        )
        return self._request('/del_all_moni_trader_data_sq', params)
    
    def get_all_moni_trader_data(
        self,
        user: str = '自定义'
    ) -> Dict[str, Any]:
        """读取个人模拟全部策略"""
        params = self._get_params(user=user)
        return self._request('/get_all_moni_trader_data', params)
    
    def get_all_moni_trader_data_sq(
        self,
        user: str = '自定义'
    ) -> Dict[str, Any]:
        """读取个人社区全部策略"""
        params = self._get_params(user=user)
        return self._request('/get_all_moni_trader_data_sq', params)

    # ============================================================
    # 六、策略执行接口
    # ============================================================
    
    def xg_condi_factor_backtrader_run(
        self,
        st_name: str = '小果条件因子测试策略',
        force_rerun: bool = False,
        save_data: bool = True
    ) -> Dict[str, Any]:
        """条件多因子策略回测执行接口"""
        params = self._get_params(
            st_name=st_name,
            force_rerun=force_rerun,
            save_data=save_data
        )
        return self._request('/xg_condi_factor_backtrader_run', params)
    ############################新添加模型**************************
    # ============================================================
    # 七、均值方差策略接口
    # ============================================================
    
    def xg_mean_var_backtrader(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        lookback_days: int = 60,
        max_weight: float = 0.6,
        min_weight: float = 0.05,
        lambda_risk: float = 2.0,
        interval: int = 5
    ) -> Dict[str, Any]:
        """均值方差最优资产组合权重再平衡策略回测"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, lookback_days=lookback_days,
            max_weight=max_weight, min_weight=min_weight,
            lambda_risk=lambda_risk, interval=interval
        )
        return self._request('/xg_mean_var_backtrader_1', params)
    
    def xg_mean_var_backtrader_moni(
        self,
        st_name: str = '小果均值方差策略',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        lookback_days: int = 60,
        max_weight: float = 0.6,
        min_weight: float = 0.05,
        lambda_risk: float = 2.0,
        interval: int = 5
    ) -> Dict[str, Any]:
        """均值方差最优资产组合策略模拟交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, lookback_days=lookback_days,
            max_weight=max_weight, min_weight=min_weight,
            lambda_risk=lambda_risk, interval=interval
        )
        return self._request('/xg_mean_var_backtrader_moni', params)
    
    def xg_mean_var_backtrader_moni_sq(
        self,
        st_name: str = '小果均值方差社区策略',
        open_show: str = '是',
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        index_stock: str = '000300.SH',
        cash: float = 100000,
        comm: float = 0.0001,
        max_workers: int = 4,
        lookback_days: int = 60,
        max_weight: float = 0.6,
        min_weight: float = 0.05,
        lambda_risk: float = 2.0,
        interval: int = 5
    ) -> Dict[str, Any]:
        """均值方差最优资产组合策略社区交易接口"""
        params = self._get_params(
            st_name=st_name, open_show=open_show,
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            index_stock=index_stock, cash=cash, comm=comm,
            max_workers=max_workers, lookback_days=lookback_days,
            max_weight=max_weight, min_weight=min_weight,
            lambda_risk=lambda_risk, interval=interval
        )
        return self._request('/xg_mean_var_backtrader_moni_sq', params)

    # ============================================================
    # 八、多标的量化分析接口
    # ============================================================
    
    def xg_stock_cov_correlation(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        max_workers: int = 4,
        method: str = 'pearson',
        risk_free_rate: float = 0.03
    ) -> Dict[str, Any]:
        """多标的收益率相关性矩阵"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            max_workers=max_workers, method=method,
            risk_free_rate=risk_free_rate
        )
        return self._request('/xg_stock_cov_correlation', params)
    
    def xg_stock_cov_covariance(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        max_workers: int = 4,
        method: str = 'pearson',
        risk_free_rate: float = 0.03,
        annualized: bool = True
    ) -> Dict[str, Any]:
        """多标的收益率协方差矩阵"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            max_workers=max_workers, method=method,
            risk_free_rate=risk_free_rate, annualized=annualized
        )
        return self._request('/xg_stock_cov_covariance', params)
    
    def xg_stock_cov_portfolio(
        self,
        start_date: str = '20260101',
        end_date: str = '20500101',
        stock_list: str = '159915.SZ,513100.SH,518880.SH',
        max_workers: int = 4,
        method: str = 'pearson',
        risk_free_rate: float = 0.03,
        target_return: Optional[float] = None
    ) -> Dict[str, Any]:
        """多标的投资组合优化"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            max_workers=max_workers, method=method,
            risk_free_rate=risk_free_rate, target_return=target_return
        )
        return self._request('/xg_stock_cov_portfolio', params)

    # ============================================================
    # 九、股票组合分析接口
    # ============================================================
    
    def xg_stock_analysis(
        self,
        start_date: str = '20240101',
        end_date: str = '20261231',
        stock_list: str = '159915.SZ,518880.SH,510300.SH',
        stock_weight: str = '0.4,0.3,0.3',
        index_stock: str = '000300.SH',
        max_workers: int = 4,
        risk_free_rate: float = 0.03
    ) -> Dict[str, Any]:
        """小果股票分析系统 - 组合收益分析"""
        params = self._get_params(
            start_date=start_date, end_date=end_date, stock_list=stock_list,
            stock_weight=stock_weight, index_stock=index_stock,
            max_workers=max_workers, risk_free_rate=risk_free_rate
        )
        return self._request('/xg_stock_analysis', params)

    # ============================================================
    # 十、用户认证接口
    # ============================================================
    
    def get_user_info(
        self,
        user: str = '自定义'
    ) -> Dict[str, Any]:
        """获取用户信息"""
        params = self._get_params(user=user)
        return self._request('/get_user_info', params)
    
    def check_password_is_av_user(
        self,
        user: str = '自定义'
    ) -> Dict[str, Any]:
        """检查授权码有效性"""
        params = self._get_params(user=user)
        return self._request('/check_password_is_av_user', params)

    # ============================================================
    # 十一、数据查询接口(AKShare/数据库API)
    # ============================================================
    
    def get_wencai_data(
        self,
        query: str = '今日涨停'
    ) -> Dict[str, Any]:
        """获取问财数据"""
        params = self._get_params(query=query)
        return self._request('/get_wencai_data', params)
    
    def get_user_def_data(
        self,
        name: str = 'df',
        func: str = '''
import akshare as ak
df = ak.stock_info_a_code_name()
print(df)
'''
    ) -> Dict[str, Any]:
        """获取自定义数据"""
        params = self._get_params(name=name, func=func)
        return self._request('/get_user_def_data', params)
    
    def get_user_base_data(
        self,
        file_path: str = '/xg_data/全市场股票/',
        file_name: str = '全市场股票'
    ) -> Dict[str, Any]:
        """获取数据库的数据"""
        params = self._get_params(file_path=file_path, file_name=file_name)
        return self._request('/get_user_base_data', params)

    # ============================================================
    # 十二、Tick/分钟数据接口
    # ============================================================
    
    
    
    def get_mini_data_5(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = '5',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """读取5分钟数据(mini)"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/get_mini_data_5', params)
    
    def get_mini_data_15(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = '15',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """读取15分钟数据(mini)"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/get_mini_data_15', params)
    
    def get_mini_data_30(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = '30',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """读取30分钟数据(mini)"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/get_mini_data_30', params)
    
    def get_mini_data_60(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = '60',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """读取60分钟数据(mini)"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/get_mini_data_60', params)

    # ============================================================
    # 十三、K线数据接口
    # ============================================================
    
    def query_history_k_data_plus_d(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'd',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """日线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/query_history_k_data_plus_d', params)
    
    def query_history_k_data_plus_w(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'w',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """周线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/query_history_k_data_plus_w', params)
    
    def query_history_k_data_plus_m(
        self,
        stock: str = 'sh.600031',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'm',
        adjustflag: str = '2'
    ) -> Dict[str, Any]:
        """月线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency,
            adjustflag=adjustflag
        )
        return self._request('/query_history_k_data_plus_m', params)

    # ============================================================
    # 十四、指数K线数据接口
    # ============================================================
    
    def query_history_k_data_plus_index_d(
        self,
        stock: str = 'sh.000001',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'd'
    ) -> Dict[str, Any]:
        """指数日线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency
        )
        return self._request('/query_history_k_data_plus_index_d', params)
    
    def query_history_k_data_plus_index_w(
        self,
        stock: str = 'sh.000001',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'w'
    ) -> Dict[str, Any]:
        """指数周线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency
        )
        return self._request('/query_history_k_data_plus_index_w', params)
    
    def query_history_k_data_plus_index_m(
        self,
        stock: str = 'sh.000001',
        start_date: str = '2026-04-01',
        end_date: str = '2050-12-31',
        frequency: str = 'm'
    ) -> Dict[str, Any]:
        """指数月线数据"""
        params = self._get_params(
            stock=stock,
            start_date=start_date,
            end_date=end_date,
            frequency=frequency
        )
        return self._request('/query_history_k_data_plus_index_m', params)

    # ============================================================
    # 十五、财务数据接口
    # ============================================================
    
    def query_profit_data(
        self,
        code: str = 'sh.600031',
        year: str = '2025',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """盈利能力"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_profit_data', params)
    
    def query_operation_data(
        self,
        code: str = 'sh.600031',
        year: str = '2025',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """营运能力"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_operation_data', params)
    
    def query_growth_data(
        self,
        code: str = 'sh.600031',
        year: str = '2026',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """季频成长能力"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_growth_data', params)
    
    def query_balance_data(
        self,
        code: str = 'sh.600031',
        year: str = '2026',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """季频偿债能力"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_balance_data', params)
    
    def query_cash_flow_data(
        self,
        code: str = 'sh.600031',
        year: str = '2026',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """季频现金流量"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_cash_flow_data', params)
    
    def query_dupont_data(
        self,
        code: str = 'sh.600031',
        year: str = '2026',
        quarter: str = '1'
    ) -> Dict[str, Any]:
        """季频杜邦指数"""
        params = self._get_params(
            code=code,
            year=year,
            quarter=quarter
        )
        return self._request('/query_dupont_data', params)

    # ============================================================
    # 五、系统接口
    # ============================================================
    
    def root(self) -> Dict[str, Any]:
        """根路径"""
        return self._request('/', {})
    
    def health(self) -> Dict[str, Any]:
        """健康检查"""
        return self._request('/health', {})


# ============================================================
# 测试代码
# ============================================================
if __name__ == "__main__":
    print("=" * 60)
    print("🚀 小果量化数据API测试")
    print("=" * 60)
    
    # 初始化客户端(使用您提供的服务器地址)
    client = xg_quant_backtrader_data(
        url="自定义",
        port=8888,
        user='自定义',
        password='自定义',
        auth_code='自定义'
    )
    
    print("\n" + "=" * 60)
    print("📋 一、系统接口测试")
    print("=" * 60)
    #因子数据
    df=client.get_stock_factor_data(columns='date,证券代码,5日涨跌幅')
    df=client._to_dataframe(df)
    print(df)
    #股票数据
    df=client.get_stock_hist_data()
    df=client._to_dataframe(df)
    print(df)
    #财务数据
    df=client.get_stock_finance_data()
    df=client._to_dataframe(df)
    print(df)

源码模块:因子计算测试.py

官方示例脚本

import pandas as pd
import numpy as np
import os
from datetime import datetime, timedelta
import json
import warnings
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import os
from xg_factor import xg_factor
from tqdm import tqdm
class xg_factor_trader:
    def __init__(self,
            index_stock='000300.SH',
            start_date='20260101',
            end_date='20500101'):
        self.path = os.path.dirname(os.path.abspath(__file__))
        self.index_stock=index_stock
        self.start_date=start_date
        self.end_date=end_date
        self.adj_type = 'none'
    def adjust_price(self, df):
        '''
        根据复权方式调整价格
        '''
        if self.adj_type == 'none':
            return df
        
        if 'preClose' in df.columns:
            try:
                df['adj_factor'] = 1.0
                for i in range(1, len(df)):
                    if df.loc[i, 'preClose'] > 0:
                        actual_return = df.loc[i, 'close'] / df.loc[i, 'preClose']
                        df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor'] * actual_return
                    else:
                        df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor']
                
                if self.adj_type in ['front', 'front_ratio']:
                    last_factor = df['adj_factor'].iloc[-1]
                    df['adj_factor'] = df['adj_factor'] / last_factor
                
                price_cols = ['open', 'high', 'low', 'close']
                for col in price_cols:
                    if col in df.columns:
                        df[col] = df[col] * df['adj_factor']
                
                df = df.drop(columns=['adj_factor'])
            except Exception as e:
                print(f"  复权计算出错: {e}")
                return df
        else:
            print(f"  警告: 没有preClose列,使用原始价格")
        
        return df
    def _convert_to_serializable(self, obj):
        '''
        递归转换不可序列化的对象为JSON可序列化格式
        '''
        if isinstance(obj, dict):
            return {k: self._convert_to_serializable(v) for k, v in obj.items()}
        elif isinstance(obj, list):
            return [self._convert_to_serializable(item) for item in obj]
        elif isinstance(obj, pd.Timestamp):
            return obj.strftime('%Y-%m-%d')
        elif isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, (np.integer, np.int64)):
            return int(obj)
        elif isinstance(obj, (np.floating, np.float64)):
            return float(obj) if not np.isnan(obj) else None
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        elif isinstance(obj, pd.DataFrame):
            return obj.to_dict('records')
        elif isinstance(obj, pd.Series):
            return obj.tolist()
        elif isinstance(obj, (np.bool_, bool)):
            return bool(obj)
        elif pd.isna(obj):
            return None
        else:
            return obj
    
    def get_stock_data(self, stock_code):
        '''读取单个股票历史数据'''
        try:
            df = pd.read_parquet(r'{}/data/历史数据/{}.parquet'.format(self.path, stock_code),
                engine='pyarrow',use_threads=True)
            
            df['date'] = pd.to_datetime(df['date'].astype(str), format='%Y%m%d')
            df = df[(df['date'] >= pd.to_datetime(self.start_date)) & 
                    (df['date'] <= pd.to_datetime(self.end_date))]
            df = df.sort_values('date').reset_index(drop=True)
            
            # 删除无效数据行
            df = df[df['close'] > 0]
            df = df[df['open'] > 0]
            
            # 应用复权
            df = self.adjust_price(df)
            
            # 计算涨跌幅
            df['zdf'] = df['close'].pct_change()
            
            return df
        except Exception as e:
            print(f"加载股票数据出错 {stock_code}: {e}")
            return pd.DataFrame()
    
    def _load_single_stock(self, stock):
        '''单个股票加载函数(用于多线程)'''
        try:
            df = self.get_stock_data(stock)
            if not df.empty:
                return (stock, df, True, f"数据加载成功: {len(df)} 行")
            else:
                return (stock, None, False, "数据加载失败")
        except Exception as e:
            return (stock, None, False, f"加载异常: {e}")
    
    def adjust_price(self, df):
        '''
        根据复权方式调整价格
        '''
        if self.adj_type == 'none':
            return df
        
        if 'preClose' in df.columns:
            try:
                df['adj_factor'] = 1.0
                for i in range(1, len(df)):
                    if df.loc[i, 'preClose'] > 0:
                        actual_return = df.loc[i, 'close'] / df.loc[i, 'preClose']
                        df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor'] * actual_return
                    else:
                        df.loc[i, 'adj_factor'] = df.loc[i-1, 'adj_factor']
                
                if self.adj_type in ['front', 'front_ratio']:
                    last_factor = df['adj_factor'].iloc[-1]
                    df['adj_factor'] = df['adj_factor'] / last_factor
                
                price_cols = ['open', 'high', 'low', 'close']
                for col in price_cols:
                    if col in df.columns:
                        df[col] = df[col] * df['adj_factor']
                
                df = df.drop(columns=['adj_factor'])
            except Exception as e:
                print(f"  复权计算出错: {e}")
                return df
        else:
            print(f"  警告: 没有preClose列,使用原始价格")
        
        return df
    def get_index_data(self):
        '''读取指数历史数据'''
        try:
        
            file_path = r'{}/data/指数数据/{}.parquet'.format(self.path, self.index_stock)
            if not os.path.exists(file_path):
                print(f"指数文件不存在: {file_path}")
                return pd.DataFrame()
            
            df = pd.read_parquet(file_path,engine='pyarrow',use_threads=True)
            df['date'] = pd.to_datetime(df['date'].astype(str), format='%Y%m%d')
            df = df[(df['date'] >= pd.to_datetime(self.start_date)) & 
                    (df['date'] <= pd.to_datetime(self.end_date))]
            df = df.sort_values('date').reset_index(drop=True)
            df = df[df['close'] > 0]
            df = df[df['open'] > 0]
            
            print(f"指数数据加载成功: {len(df)} 行")
            return df
        except Exception as e:
            print(f"加载指数数据出错: {e}")
            return pd.DataFrame()
if __name__=='__main__':
    stock='513100.SH'
    api=xg_factor_trader()
    df=api.get_stock_data(stock)
    index_df=api.get_index_data()
    models=xg_factor(df=df,index_df=index_df)
    result=models.MACD_金叉()
    df['因子']=result
    df=df[['date','证券代码','证券名称','因子']]
    print(df)

配置文件:因子表.json

608 条『因子名 → 调用字符串』配置清单(批量引擎 self.text)

{
    "5日涨跌幅": "cacal_zdf(n=5)",
    "10日涨跌幅": "cacal_zdf(n=10)",
    "20日涨跌幅": "cacal_zdf(n=20)",
    "30日涨跌幅": "cacal_zdf(n=30)",
    "60日涨跌幅": "cacal_zdf(n=60)",
    "120日涨跌幅": "cacal_zdf(n=120)",
    "六脉神剑":"six_pulse_excalibur_hist()",
    "小波段交易":"small_fruit_band_trading_1()",
    "大波段交易":"small_fruit_band_trading_2()",
    "波段超级买卖":"band_supe_buy_sell()",
    "价格距离5日均线涨跌幅":"cacal_price_line_zdf(n=5)",
    "价格距离10日均线涨跌幅":"cacal_price_line_zdf(n=10)",
    "价格距离20日均线涨跌幅":"cacal_price_line_zdf(n=20)",
    "价格距离30日均线涨跌幅":"cacal_price_line_zdf(n=30)",
    "价格距离60日均线涨跌幅":"cacal_price_line_zdf(n=60)",
    "价格距离120日均线涨跌幅":"cacal_price_line_zdf(n=120)",
    "5日均线距离10日均线涨跌幅":"cacal_line_line_zdf(n1=5,n2=10)",
    "10日均线距离20日均线涨跌幅":"cacal_line_line_zdf(n1=10,n2=20)",
    "20日均线距离30日均线涨跌幅":"cacal_line_line_zdf(n1=20,n2=30)",
    "30日均线距离60日均线涨跌幅":"cacal_line_line_zdf(n1=30,n2=60)",
    "60日均线距离120日均线涨跌幅":"cacal_line_line_zdf(n1=60,n2=120)",
    "5日偏度":"cacal_skew(n=5)",
    "10日偏度":"cacal_skew(n=10)",
    "20日偏度":"cacal_skew(n=20)",
    "30日偏度":"cacal_skew(n=30)",
    "60日偏度":"cacal_skew(n=60)",
    "120日偏度":"cacal_skew(n=120)",
    "5日峰度":"cacal_kurt(n=5)",
    "10日峰度":"cacal_kurt(n=10)",
    "20日峰度":"cacal_kurt(n=20)",
    "30日峰度":"cacal_kurt(n=30)",
    "60日峰度":"cacal_kurt(n=60)",
    "120日峰度":"cacal_kurt(n=120)",
    "KDJ_KD金叉": "KDJ_KD金叉()",
    "KDJ_KD死叉": "KDJ_KD死叉()",
    "RSI_金叉": "RSI_金叉()",
    "RSI_死叉": "RSI_死叉()",
    "WR_金叉": "WR_金叉()",
    "MACD_金叉": "MACD_金叉()",
    "MACD_死叉": "MACD_死叉()",
    "PSY_金叉": "PSY_金叉()",
    "PSY_死叉": "PSY_死叉()",
    "5日均线": "SMA(period=5)",
    "10日均线": "SMA(period=10)",
    "20日均线": "SMA(period=20)",
    "30日均线": "SMA(period=30)",
    "60日均线": "SMA(period=60)",
    "120日均线": "SMA(period=120)",
    "5日10日金叉": "CROSS_UP(n1=5,n2=10)",
    "10日20日金叉": "CROSS_UP(n1=10,n2=20)",
    "20日30日金叉": "CROSS_UP(n1=20,n2=30)",
    "30日60日金叉": "CROSS_UP(n1=30,n2=60)",
    "60日120日金叉": "CROSS_UP(n1=60,n2=120)",
    "5日10日死叉": "CROSS_DOWN(n1=10,n2=5)",
    "10日20日死叉": "CROSS_DOWN(n1=20,n2=10)",
    "20日30日死叉": "CROSS_DOWN(n1=30,n2=20)",
    "30日60日死叉": "CROSS_DOWN(n1=60,n2=30)",
    "60日120日死叉": "CROSS_DOWN(n1=120,n2=60)",
    "连续上涨天数": "BARSLASTCOUNT_UP()",
    "连续下跌天数": "BARSLASTCOUNT_DOWN()",
    "价格在5均线上": "PRICE_MA_LINE_ANAL(n=5)",
    "价格在10均线上": "PRICE_MA_LINE_ANAL(n=10)",
    "价格在20均线上": "PRICE_MA_LINE_ANAL(n=20)",
    "价格在30均线上": "PRICE_MA_LINE_ANAL(n=30)",
    "价格在60均线上": "PRICE_MA_LINE_ANAL(n=60)",
    "价格在120均线上": "PRICE_MA_LINE_ANAL(n=120)",
    "5均线在10均线上": "MA_LINE_ANAL(n1=5,n2=10)",
    "10均线在20均线上": "MA_LINE_ANAL(n1=10,n2=20)",
    "20均线在30均线上": "MA_LINE_ANAL(n1=20,n2=30)",
    "30均线在60均线上": "MA_LINE_ANAL(n1=30,n2=60)",
    "60均线在120均线上": "MA_LINE_ANAL(n1=60,n2=120)",
    "5日Alpha": "roll_alpha(n=5)",
    "10日Alpha": "roll_alpha(n=10)",
    "20日Alpha": "roll_alpha(n=20)",
    "30日Alpha": "roll_alpha(n=30)",
    "60日Alpha": "roll_alpha(n=60)",
    "120日Alpha": "roll_alpha(n=120)",
    "5日Beta": "roll_beta(n=5)",
    "10日Beta": "roll_beta(n=10)",
    "20日Beta": "roll_beta(n=20)",
    "30日Beta": "roll_beta(n=30)",
    "60日Beta": "roll_beta(n=60)",
    "120日Beta": "roll_beta(n=120)",
    "5日夏普比率": "roll_sharpe_ratio(n=5)",
    "10日夏普比率": "roll_sharpe_ratio(n=10)",
    "20日夏普比率": "roll_sharpe_ratio(n=20)",
    "30日夏普比率": "roll_sharpe_ratio(n=30)",
    "60日夏普比率": "roll_sharpe_ratio(n=60)",
    "120日夏普比率": "roll_sharpe_ratio(n=120)",
    "5日年化波动率": "roll_annual_volatility(n=5)",
    "10日年化波动率": "roll_annual_volatility(n=10)",
    "20日年化波动率": "roll_annual_volatility(n=20)",
    "30日年化波动率": "roll_annual_volatility(n=30)",
    "60日年化波动率": "roll_annual_volatility(n=60)",
    "120日年化波动率": "roll_annual_volatility(n=120)",
    "5日最大回撤": "roll_max_drawdown(n=5)",
    "10日最大回撤": "roll_max_drawdown(n=10)",
    "20日最大回撤": "roll_max_drawdown(n=20)",
    "30日最大回撤": "roll_max_drawdown(n=30)",
    "60日最大回撤": "roll_max_drawdown(n=60)",
    "120日最大回撤": "roll_max_drawdown(n=120)",
    "5日上涨捕获率": "roll_up_capture(n=5)",
    "10日上涨捕获率": "roll_up_capture(n=10)",
    "20日上涨捕获率": "roll_up_capture(n=20)",
    "30日上涨捕获率": "roll_up_capture(n=30)",
    "60日上涨捕获率": "roll_up_capture(n=60)",
    "120日上涨捕获率": "roll_up_capture(n=120)",
    "5日下跌捕获率": "roll_down_capture(n=5)",
    "10日下跌捕获率": "roll_down_capture(n=10)",
    "20日下跌捕获率": "roll_down_capture(n=20)",
    "30日下跌捕获率": "roll_down_capture(n=30)",
    "60日下跌捕获率": "roll_down_capture(n=60)",
    "120日下跌捕获率": "roll_down_capture(n=120)",
    "3日回归动量": "calculate_momentum_score(n=3)",
    "5日回归动量": "calculate_momentum_score(n=5)",
    "7日回归动量": "calculate_momentum_score(n=7)",
    "9日回归动量": "calculate_momentum_score(n=9)",
    "12日回归动量": "calculate_momentum_score(n=12)",
    "15日回归动量": "calculate_momentum_score(n=15)",
    "18日回归动量": "calculate_momentum_score(n=18)",
    "20日回归动量": "calculate_momentum_score(n=20)",
    "23日回归动量": "calculate_momentum_score(n=23)",
    "25日回归动量": "calculate_momentum_score(n=25)",
    "28日回归动量": "calculate_momentum_score(n=28)",
    "30日回归动量": "calculate_momentum_score(n=30)",
    "35日回归动量": "calculate_momentum_score(n=35)",
    "40日回归动量": "calculate_momentum_score(n=40)",
    "45日回归动量": "calculate_momentum_score(n=45)",
    "50日回归动量": "calculate_momentum_score(n=50)",
    "60日回归动量": "calculate_momentum_score(n=60)",
    "5日最高值到当前周期": "HHVBARS(n=5)",
    "10日最高值到当前周期": "HHVBARS(n=10)",
    "20日最高值到当前周期": "HHVBARS(n=20)",
    "30日最高值到当前周期": "HHVBARS(n=30)",
    "60日最高值到当前周期": "HHVBARS(n=60)",
    "120日最高值到当前周期": "HHVBARS(n=120)",
    "5日最低值到当前周期": "LLVBARS(n=5)",
    "10日最低值到当前周期": "LLVBARS(n=10)",
    "20日最低值到当前周期": "LLVBARS(n=20)",
    "30日最低值到当前周期": "LLVBARS(n=30)",
    "60日最低值到当前周期": "LLVBARS(n=60)",
    "120日最低值到当前周期": "LLVBARS(n=120)",
    "5日回归斜率": "SLOPE(n=5)",
    "10日回归斜率": "SLOPE(n=10)",
    "20日回归斜率": "SLOPE(n=20)",
    "30日回归斜率": "SLOPE(n=30)",
    "60日回归斜率": "SLOPE(n=60)",
    "120日回归斜率": "SLOPE(n=120)",
    "5日标准差": "STD(n=5)",
    "10日标准差": "STD(n=10)",
    "20日标准差": "STD(n=20)",
    "30日标准差": "STD(n=30)",
    "60日标准差": "STD(n=60)",
    "120日标准差": "STD(n=120)",
    "CCI商品路径指标": "CCI()",
    "MFI最近流量指标": "MFI()",
    "MTM动量线_MTM值": "MTM_MTM()",
    "MTM动量线_MTMMA值": "MTM_MTMMA()",
    "RSI相对强弱_RSI1": "RSI1()",
    "RSI相对强弱_RSI2": "RSI2()",
    "RSI相对强弱_RSI3": "RSI3()",
    "KDJ指标_K值": "KDJ_K()",
    "KDJ指标_D值": "KDJ_D()",
    "KDJ指标_J值": "KDJ_J()",
    "SKDJ慢速随机_K值": "SKDJ_K()",
    "SKDJ慢速随机_D值": "SKDJ_D()",
    "UDL引力线_UDL值": "UDL_UDL()",
    "UDL引力线_MAUDL值": "UDL_MAUDL()",
    "WR威廉指标_WR1": "WR1()",
    "WR威廉指标_WR2": "WR2()",
    "LWR指标_LWR1": "LWR1()",
    "LWR指标_LWR2": "LWR2()",
    "MARSI相对强弱平均线_RSI1": "MARSI1()",
    "MARSI相对强弱平均线_RSI2": "MARSI2()",
    "BIAS乖离率_BIAS1": "BIAS1()",
    "BIAS乖离率_BIAS2": "BIAS2()",
    "BIAS乖离率_BIAS3": "BIAS3()",
    "BIAS_QL乖离率传统版_BIAS值": "BIAS_QL_BIAS()",
    "BIAS_QL乖离率传统版_BIASMA值": "BIAS_QL_BIASMA()",
    "BIAS36三六乖离_BIAS36": "BIAS36_BIAS36()",
    "BIAS36三六乖离_BIAS612": "BIAS36_BIAS612()",
    "BIAS36三六乖离_MABIAS": "BIAS36_MABIAS()",
    "ACCER幅度涨速": "ACCER()",
    "ASI振动升降指标_ASI": "ASI_ASI()",
    "ASI振动升降指标_ASIT": "ASI_ASIT()",
    "CHO佳庆指标_CHO": "CHO_CHO()",
    "CHO佳庆指标_MACHO": "CHO_MACHO()",
    "DMA_XT平均差_DIF": "DMA_XT_DIF()",
    "DMA_XT平均差_DIFMA": "DMA_XT_DIFMA()",
    "DMI趋向指标_PDI": "DMI_PDI()",
    "DMI趋向指标_MDI": "DMI_MDI()",
    "DMI趋向指标_ADX": "DMI_ADX()",
    "DMI趋向指标_ADXR": "DMI_ADXR()",
    "DPO区间震荡线_DPO": "DPO_DPO()",
    "DPO区间震荡线_MADPO": "DPO_MADPO()",
    "EMV简易波动指标_EMV": "EMV_EMV()",
    "EMV简易波动指标_MAEMV": "EMV_MAEMV()",
    "MACD平滑异同平均线_DIF": "MACD_DIF()",
    "MACD平滑异同平均线_DEA": "MACD_DEA()",
    "MACD平滑异同平均线_MACD": "MACD_MACD()",
    "VMACD量平滑异同平均线_DIF": "VMACD_DIF()",
    "VMACD量平滑异同平均线_DEA": "VMACD_DEA()",
    "VMACD量平滑异同平均线_MACD": "VMACD_MACD()",
    "SMACD单线平滑异同平均线_DEA": "SMACD_DEA()",
    "SMACD单线平滑异同平均线_MACD": "SMACD_MACD()",
    "QACD快速异同平均线_DIF": "QACD_DIF()",
    "QACD快速异同平均线_MACD": "QACD_MACD()",
    "QACD快速异同平均线_DDIF": "QACD_DDIF()",
    "TRIX三重指数平均线_TRIX": "TRIX_TRIX()",
    "TRIX三重指数平均线_MATRIX": "TRIX_MATRIX()",
    "UOS终极指标_UOS": "UOS_UOS()",
    "UOS终极指标_MAUOS": "UOS_MAUOS()",
    "VTP量价曲线_VPT": "VTP_VPT()",
    "VTP量价曲线_MAVP": "VTP_MAVP()",
    "WVAD威廉变异离散量_WVAD": "WVAD_WVAD()",
    "WVAD威廉变异离散量_MAWVAD": "WVAD_MAWVAD()",
    "JS加数线_JS": "JS_JS()",
    "JS加数线_MAJS1": "JS_MAJS1()",
    "JS加数线_MAJS2": "JS_MAJS2()",
    "JS加数线_MAJS3": "JS_MAJS3()",
    "CYE市场趋势_CYEL": "CYE_CYEL()",
    "CYE市场趋势_CYES": "CYE_CYES()",
    "GDX轨道线_轨道": "GDX_轨道()",
    "GDX轨道线_压力线": "GDX_压力线()",
    "GDX轨道线_支撑线": "GDX_支撑线()",
    "JLHB绝路航标_B": "JLHB_B()",
    "JLHB绝路航标_VAR2": "JLHB_VAR2()",
    "JLHB绝路航标_绝路航标": "JLHB_绝路航标()",
    "BRAR情绪指标_BR": "BRAR_BR()",
    "BRAR情绪指标_AR": "BRAR_AR()",
    "CR带状能量线_CR": "CR_CR()",
    "CR带状能量线_MA1": "CR_MA1()",
    "CR带状能量线_MA2": "CR_MA2()",
    "CR带状能量线_MA3": "CR_MA3()",
    "CR带状能量线_MA4": "CR_MA4()",
    "MASS梅斯线_MASS": "MASS_MASS()",
    "MASS梅斯线_MAMASS": "MASS_MAMASS()",
    "PSY心理线_PSY": "PSY_PSY()",
    "PSY心理线_PSYMA": "PSY_PSYMA()",
    "VR成交量变异率_VR": "VR_VR()",
    "VR成交量变异率_MAVR": "VR_MAVR()",
    "WAD威廉多空力度线_WAD": "WAD_WAD()",
    "WAD威廉多空力度线_MAWAD": "WAD_MAWAD()",
    "PCNT幅度比_PCNT": "PCNT_PCNT()",
    "PCNT幅度比_MAPCNT": "PCNT_MAPCNT()",
    "CYR市场强弱_CYR": "CYR_CYR()",
    "CYR市场强弱_MACYR": "CYR_MACYR()",
    "AMO成交金额_AMOW": "AMO_AMOW()",
    "AMO成交金额_AMO1": "AMO_AMO1()",
    "AMO成交金额_AMO2": "AMO_AMO2()",
    "OBV累积能量线_OBV": "OBV_OBV()",
    "OBV累积能量线_MAOBV": "OBV_MAOBV()",
    "VOL成交量_MAVOL1": "VOL_XT_MAVOL1()",
    "VOL成交量_MAVOL2": "VOL_XT_MAVOL2()",
    "VRSI相对强弱量_RSI1": "VRSI1()",
    "VRSI相对强弱量_RSI2": "VRSI2()",
    "VRSI相对强弱量_RSI3": "VRSI3()",
    "HSL换手线_HSL": "HSL_HSL()",
    "HSL换手线_MAHSL": "HSL_MAHSL()",
    "MA均线_MA1": "MA_XT_MA1()",
    "MA均线_MA2": "MA_XT_MA2()",
    "MA均线_MA3": "MA_XT_MA3()",
    "MA均线_MA4": "MA_XT_MA4()",
    "ACD升降线_ACD": "ACD_ACD()",
    "ACD升降线_MAACD": "ACD_MAACD()",
    "BBI多空均线": "BBI()",
    "EXPMA指数平均线_EXP1": "EXPMA_EXP1()",
    "EXPMA指数平均线_EXP2": "EXPMA_EXP2()",
    "HMA高价平均线_HMA1": "HMA_HMA1()",
    "HMA高价平均线_HMA2": "HMA_HMA2()",
    "HMA高价平均线_HMA3": "HMA_HMA3()",
    "HMA高价平均线_HMA4": "HMA_HMA4()",
    "HMA高价平均线_HMA5": "HMA_HMA5()",
    "LMA低价平均线_LMA1": "LMA_LMA1()",
    "LMA低价平均线_LMA2": "LMA_LMA2()",
    "LMA低价平均线_LMA3": "LMA_LMA3()",
    "LMA低价平均线_LMA4": "LMA_LMA4()",
    "LMA低价平均线_LMA5": "LMA_LMA5()",
    "VMA变异平均线_VMA1": "VMA_VMA1()",
    "VMA变异平均线_VMA2": "VMA_VMA2()",
    "VMA变异平均线_VMA3": "VMA_VMA3()",
    "VMA变异平均线_VMA4": "VMA_VMA4()",
    "VMA变异平均线_VMA5": "VMA_VMA5()",
    "AMV成本均线_AMV1": "AMV_AMV1()",
    "AMV成本均线_AMV2": "AMV_AMV2()",
    "AMV成本均线_AMV3": "AMV_AMV3()",
    "AMV成本均线_AMV4": "AMV_AMV4()",
    "BBIBOLL多空布林线_BBIBOLL": "BBIBOLL_BBIBOLL()",
    "BBIBOLL多空布林线_UPR": "BBIBOLL_UPR()",
    "BBIBOLL多空布林线_DWN": "BBIBOLL_DWN()",
    "ALLIGAT鳄鱼线_上唇": "ALLIGAT_上唇()",
    "ALLIGAT鳄鱼线_牙齿": "ALLIGAT_牙齿()",
    "ALLIGAT鳄鱼线_下颚": "ALLIGAT_下颚()",
    "GMMA顾比均线_MA3": "GMMA_MA3()",
    "GMMA顾比均线_MA5": "GMMA_MA5()",
    "GMMA顾比均线_MA8": "GMMA_MA8()",
    "GMMA顾比均线_MA10": "GMMA_MA10()",
    "GMMA顾比均线_MA12": "GMMA_MA12()",
    "GMMA顾比均线_MA15": "GMMA_MA15()",
    "GMMA顾比均线_MA30": "GMMA_MA30()",
    "GMMA顾比均线_MA35": "GMMA_MA35()",
    "GMMA顾比均线_MA40": "GMMA_MA40()",
    "GMMA顾比均线_MA45": "GMMA_MA45()",
    "GMMA顾比均线_MA50": "GMMA_MA50()",
    "GMMA顾比均线_MA60": "GMMA_MA60()",
    "BOLL布林线_BOLL": "BOLL_BOLL()",
    "BOLL布林线_UB": "BOLL_UB()",
    "BOLL布林线_LB": "BOLL_LB()",
    "PBX瀑布线_PBX1": "PBX_PBX1()",
    "PBX瀑布线_PBX2": "PBX_PBX2()",
    "PBX瀑布线_PBX3": "PBX_PBX3()",
    "PBX瀑布线_PBX4": "PBX_PBX4()",
    "PBX瀑布线_PBX5": "PBX_PBX5()",
    "PBX瀑布线_PBX6": "PBX_PBX6()",
    "ENE轨道线_UPPER": "ENE_UPPER()",
    "ENE轨道线_LOWER": "ENE_LOWER()",
    "ENE轨道线_ENE": "ENE_ENE()",
    "MIKE麦克支撑压力_STOR": "MIKE_STOR()",
    "MIKE麦克支撑压力_MIDR": "MIKE_MIDR()",
    "MIKE麦克支撑压力_WEKR": "MIKE_WEKR()",
    "MIKE麦克支撑压力_WEKS": "MIKE_WEKS()",
    "MIKE麦克支撑压力_MIDS": "MIKE_MIDS()",
    "MIKE麦克支撑压力_STOS": "MIKE_STOS()",
    "XS薛斯通道_SUP": "XS_SUP()",
    "XS薛斯通道_SDN": "XS_SDN()",
    "XS薛斯通道_LUP": "XS_LUP()",
    "XS薛斯通道_LDN": "XS_LDN()",
    "TQN唐奇安通道_周期高点": "TQN_周期高点()",
    "TQN唐奇安通道_周期低点": "TQN_周期低点()",
    "TQN唐奇安通道_平空开多": "TQN_平空开多()",
    "TQN唐奇安通道_平多开空": "TQN_平多开空()",
    "SAR抛物线指标": "SAR()",
    "MA交易_MA1": "MA_交易_MA1()",
    "MA交易_MA2": "MA_交易_MA2()",
    "MA交易_平空开多": "MA_交易_平空开多()",
    "MA交易_平多开空": "MA_交易_平多开空()",
    "MACD交易_DIFF": "MACD_交易_DIFF()",
    "MACD交易_DEA": "MACD_交易_DEA()",
    "MACD交易_MACD": "MACD_交易_MACD()",
    "MACD交易_平空开多": "MACD_交易_平空开多()",
    "MACD交易_平多开空": "MACD_交易_平多开空()",
    "KDJ交易_K": "KDJ_交易_K()",
    "KDJ交易_D": "KDJ_交易_D()",
    "KDJ交易_J": "KDJ_交易_J()",
    "KDJ交易_平空开多": "KDJ_交易_平空开多()",
    "KDJ交易_平多开空": "KDJ_交易_平多开空()",
    "SG_XDT心电图_QR": "SG_XDT_QR()",
    "SG_XDT心电图_MQR1": "SG_XDT_MQR1()",
    "SG_XDT心电图_MQR2": "SG_XDT_MQR2()",
    "SG_NDB脑电波_DK": "SG_NDB_DK()",
    "SG_NDB脑电波_MDK1": "SG_NDB_MDK1()",
    "SG_NDB脑电波_MDK2": "SG_NDB_MDK2()",
    "SG_SMX生命线_ZY1": "SG_SMX_ZY1()",
    "SG_SMX生命线_ZY2": "SG_SMX_ZY2()",
    "SG_SMX生命线_ZY3": "SG_SMX_ZY3()",
    "SG_LB量比_量比": "SG_LB_量比()",
    "SG_LB量比_MA5": "SG_LB_MA5()",
    "SG_LB量比_MA10": "SG_LB_MA10()",
    "SG_PF强势股评分": "SG_PF()",
    "RAD威力雷达_RADER1": "RAD_RADER1()",
    "RAD威力雷达_RADERMA": "RAD_RADERMA()",
    "LON龙系长线_LON": "LON_LON()",
    "LON龙系长线_LONMA": "LON_LONMA()",
    "LON龙系长线_LONT": "LON_LONT()",
    "SHT龙系短线_SHT": "SHT_SHT()",
    "SHT龙系短线_SHTMA": "SHT_SHTMA()",
    "ZLJC主力进出_JCS": "ZLJC_JCS()",
    "ZLJC主力进出_JCM": "ZLJC_JCM()",
    "ZLJC主力进出_JCL": "ZLJC_JCL()",
    "ZLMM主力买卖_MMS": "ZLMM_MMS()",
    "ZLMM主力买卖_MMM": "ZLMM_MMM()",
    "ZLMM主力买卖_MML": "ZLMM_MML()",
    "SLZT神龙在天_白龙": "SLZT_白龙()",
    "SLZT神龙在天_黄龙": "SLZT_黄龙()",
    "SLZT神龙在天_紫龙": "SLZT_紫龙()",
    "SLZT神龙在天_青龙": "SLZT_青龙()",
    "SLZT神龙在天_红龙": "SLZT_红龙()",
    "SLZT神龙在天_蓝龙": "SLZT_蓝龙()",
    "ADVOL龙系离散量_ADVOL": "ADVOL_ADVOL()",
    "ADVOL龙系离散量_MA1": "ADVOL_MA1()",
    "ADVOL龙系离散量_MA2": "ADVOL_MA2()",
    "CYS市场盈亏": "CYS()",
    "CYW主力控盘": "CYW()",
    "JAX济安线_J": "JAX_J()",
    "JAX济安线_A": "JAX_A()",
    "JAX济安线_X": "JAX_X()",
    "XJDX超级短线_J": "XJDX_J()",
    "XJDX超级短线_D": "XJDX_D()",
    "XJDX超级短线_K": "XJDX_K()",
    "ZJTJ庄家抬轿_无庄控盘": "ZJTJ_无庄控盘()",
    "ZJTJ庄家抬轿_开始控盘": "ZJTJ_开始控盘()",
    "ZJTJ庄家抬轿_有庄控盘": "ZJTJ_有庄控盘()",
    "ZJTJ庄家抬轿_主力出货": "ZJTJ_主力出货()",
    "BDZX波段之星_AK": "BDZX_AK()",
    "BDZX波段之星_AD1": "BDZX_AD1()",
    "BDZX波段之星_AJ": "BDZX_AJ()",
    "BDZX波段之星_买进": "BDZX_买进()",
    "BDZX波段之星_卖出": "BDZX_卖出()",
    "LHXJ猎狐先觉_主力弃盘": "LHXJ_主力弃盘()",
    "LHXJ猎狐先觉_主力控盘": "LHXJ_主力控盘()",
    "LYJH猎鹰歼狐_机构做空能量线": "LYJH_机构做空能量线()",
    "LYJH猎鹰歼狐_机构做多能量线": "LYJH_机构做多能量线()",
    "JFZX飓风智能中线_多头力量": "JFZX_多头力量()",
    "JFZX飓风智能中线_空头力量": "JFZX_空头力量()",
    "CYHT财运亨通_SK": "CYHT_SK()",
    "CYHT财运亨通_SD": "CYHT_SD()",
    "CYHT财运亨通_卖出": "CYHT_卖出()",
    "CYHT财运亨通_买进": "CYHT_买进()",
    "BSQJ买卖区间_B买": "BSQJ_B买()",
    "BSQJ买卖区间_持仓": "BSQJ_持仓()",
    "BSQJ买卖区间_S卖": "BSQJ_S卖()",
    "BSQJ买卖区间_空仓": "BSQJ_空仓()",
    "CDP_STD逆势操作_CDP": "CDP_STD_CDP()",
    "CDP_STD逆势操作_AH": "CDP_STD_AH()",
    "CDP_STD逆势操作_NH": "CDP_STD_NH()",
    "CDP_STD逆势操作_NL": "CDP_STD_NL()",
    "CDP_STD逆势操作_AL": "CDP_STD_AL()",
    "Alpha001": "alpha001()",
    "Alpha002": "alpha002()",
    "Alpha003": "alpha003()",
    "Alpha004": "alpha004()",
    "Alpha005": "alpha005()",
    "Alpha006": "alpha006()",
    "Alpha007": "alpha007()",
    "Alpha008": "alpha008()",
    "Alpha009": "alpha009()",
    "Alpha010": "alpha010()",
    "Alpha011": "alpha011()",
    "Alpha012": "alpha012()",
    "Alpha013": "alpha013()",
    "Alpha014": "alpha014()",
    "Alpha015": "alpha015()",
    "Alpha016": "alpha016()",
    "Alpha017": "alpha017()",
    "Alpha018": "alpha018()",
    "Alpha019": "alpha019()",
    "Alpha020": "alpha020()",
    "Alpha021": "alpha021()",
    "Alpha022": "alpha022()",
    "Alpha023": "alpha023()",
    "Alpha024": "alpha024()",
    "Alpha025": "alpha025()",
    "Alpha026": "alpha026()",
    "Alpha027": "alpha027()",
    "Alpha028": "alpha028()",
    "Alpha029": "alpha029()",
    "Alpha030": "alpha030()",
    "Alpha031": "alpha031()",
    "Alpha032": "alpha032()",
    "Alpha033": "alpha033()",
    "Alpha034": "alpha034()",
    "Alpha035": "alpha035()",
    "Alpha036": "alpha036()",
    "Alpha037": "alpha037()",
    "Alpha038": "alpha038()",
    "Alpha039": "alpha039()",
    "Alpha040": "alpha040()",
    "Alpha041": "alpha041()",
    "Alpha042": "alpha042()",
    "Alpha043": "alpha043()",
    "Alpha044": "alpha044()",
    "Alpha045": "alpha045()",
    "Alpha046": "alpha046()",
    "Alpha047": "alpha047()",
    "Alpha048": "alpha048()",
    "Alpha049": "alpha049()",
    "Alpha050": "alpha050()",
    "Alpha051": "alpha051()",
    "Alpha052": "alpha052()",
    "Alpha053": "alpha053()",
    "Alpha054": "alpha054()",
    "Alpha055": "alpha055()",
    "Alpha056": "alpha056()",
    "Alpha057": "alpha057()",
    "Alpha058": "alpha058()",
    "Alpha059": "alpha059()",
    "Alpha060": "alpha060()",
    "Alpha061": "alpha061()",
    "Alpha062": "alpha062()",
    "Alpha063": "alpha063()",
    "Alpha064": "alpha064()",
    "Alpha065": "alpha065()",
    "Alpha066": "alpha066()",
    "Alpha067": "alpha067()",
    "Alpha068": "alpha068()",
    "Alpha069": "alpha069()",
    "Alpha070": "alpha070()",
    "Alpha071": "alpha071()",
    "Alpha072": "alpha072()",
    "Alpha073": "alpha073()",
    "Alpha074": "alpha074()",
    "Alpha075": "alpha075()",
    "Alpha076": "alpha076()",
    "Alpha077": "alpha077()",
    "Alpha078": "alpha078()",
    "Alpha079": "alpha079()",
    "Alpha080": "alpha080()",
    "Alpha081": "alpha081()",
    "Alpha082": "alpha082()",
    "Alpha083": "alpha083()",
    "Alpha084": "alpha084()",
    "Alpha085": "alpha085()",
    "Alpha086": "alpha086()",
    "Alpha087": "alpha087()",
    "Alpha088": "alpha088()",
    "Alpha089": "alpha089()",
    "Alpha090": "alpha090()",
    "Alpha091": "alpha091()",
    "Alpha092": "alpha092()",
    "Alpha093": "alpha093()",
    "Alpha094": "alpha094()",
    "Alpha095": "alpha095()",
    "Alpha096": "alpha096()",
    "Alpha097": "alpha097()",
    "Alpha098": "alpha098()",
    "Alpha099": "alpha099()",
    "Alpha100": "alpha100()",
    "Alpha101": "alpha101()",
    "Alpha102": "alpha102()",
    "Alpha103": "alpha103()",
    "Alpha104": "alpha104()",
    "Alpha105": "alpha105()",
    "Alpha106": "alpha106()",
    "Alpha107": "alpha107()",
    "Alpha108": "alpha108()",
    "Alpha109": "alpha109()",
    "Alpha110": "alpha110()",
    "Alpha111": "alpha111()",
    "Alpha112": "alpha112()",
    "Alpha113": "alpha113()",
    "Alpha114": "alpha114()",
    "Alpha115": "alpha115()",
    "Alpha116": "alpha116()",
    "Alpha117": "alpha117()",
    "Alpha118": "alpha118()",
    "Alpha119": "alpha119()",
    "Alpha120": "alpha120()",
    "Alpha121": "alpha121()",
    "Alpha122": "alpha122()",
    "Alpha123": "alpha123()",
    "Alpha124": "alpha124()",
    "Alpha125": "alpha125()",
    "Alpha126": "alpha126()",
    "Alpha127": "alpha127()",
    "Alpha128": "alpha128()",
    "Alpha129": "alpha129()",
    "Alpha130": "alpha130()",
    "Alpha131": "alpha131()",
    "Alpha132": "alpha132()",
    "Alpha133": "alpha133()",
    "Alpha134": "alpha134()",
    "Alpha135": "alpha135()",
    "Alpha136": "alpha136()",
    "Alpha137": "alpha137()",
    "Alpha138": "alpha138()",
    "Alpha139": "alpha139()",
    "Alpha140": "alpha140()",
    "Alpha141": "alpha141()",
    "Alpha142": "alpha142()",
    "Alpha143": "alpha143()",
    "Alpha144": "alpha144()",
    "Alpha145": "alpha145()",
    "Alpha146": "alpha146()",
    "Alpha147": "alpha147()",
    "Alpha148": "alpha148()",
    "Alpha149": "alpha149()",
    "Alpha150": "alpha150()",
    "Alpha151": "alpha151()",
    "Alpha152": "alpha152()",
    "Alpha153": "alpha153()",
    "Alpha154": "alpha154()",
    "Alpha155": "alpha155()",
    "Alpha156": "alpha156()",
    "Alpha157": "alpha157()",
    "Alpha158": "alpha158()",
    "Alpha159": "alpha159()",
    "Alpha160": "alpha160()",
    "Alpha161": "alpha161()",
    "Alpha162": "alpha162()",
    "Alpha163": "alpha163()",
    "Alpha164": "alpha164()",
    "Alpha165": "alpha165()",
    "Alpha166": "alpha166()",
    "Alpha167": "alpha167()",
    "Alpha168": "alpha168()",
    "Alpha169": "alpha169()",
    "Alpha170": "alpha170()",
    "Alpha171": "alpha171()",
    "Alpha172": "alpha172()",
    "Alpha173": "alpha173()",
    "Alpha174": "alpha174()",
    "Alpha175": "alpha175()",
    "Alpha176": "alpha176()",
    "Alpha177": "alpha177()",
    "Alpha178": "alpha178()",
    "Alpha179": "alpha179()",
    "Alpha180": "alpha180()",
    "Alpha181": "alpha181()",
    "Alpha182": "alpha182()",
    "Alpha183": "alpha183()",
    "Alpha184": "alpha184()",
    "Alpha185": "alpha185()",
    "Alpha186": "alpha186()",
    "Alpha187": "alpha187()",
    "Alpha188": "alpha188()",
    "Alpha189": "alpha189()",
    "Alpha190": "alpha190()",
    "Alpha191": "alpha191()"
}