小果量化因子库 专家
教程 https://gitcode.com/qq_50882340/xg_factor_trader
一、系统概述
小果量化因子库把「数百个技术指标 / 191 个 WorldQuant Alpha / 交易信号」封装成一套方法 + 一份因子表 + 一个批量引擎的统一形态。它做三件事:
- 算因子:给行情 → 得到数十~数百列因子;
- 批量管理:按
因子表.json清单,对单只或全市场并行计算并落盘 parquet; - 供下游:产出可直接喂给排序多因子 / 条件多因子 / 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() |
十、自定义因子 / 接入引擎
- 临时组合:
models.C做 pandas 计算,len==len(df)即可; - 通达信信号:
CROSS(MA(models.C,5), MA(models.C,20)); - 进批量:在
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()"
}
微信扫一扫