缠中说禅中枢指标:趋势峰谷线多空转折源码学习
利他科技分享技术
通达信指标安装技巧:
电脑端 打开通达信软件;点击“功能”-“公式系统”-“公式管理器”;选择“技术指标公式”-“新建”;测试通过的话,一定要记得去点击右上角的”确定“按钮,这样就完成了。
友情提示(指标只是辅助,不作建议)

图一:指标全局分析图
一、指标核心用法
指标名称:缠中说禅中枢指标
指标类型画线方法:主图叠加
主要用法简介:请注意本指标含有未来函数
LIJIND1 := 5; 参数值为5
LIJIND2 := ZIG(3, LIJIND1); ZIG函数:ZIG(K, N) 表示折线,在通达信中ZIG(3, N) 通常指基于收盘价的之字转向,N=5是转折幅度百分比。ZIG输出转向点之间的连线值。
LIJIND3 := TROUGH(3, LIJIND1, 1); TROUGH(K, N, M) 表示前M个波谷的值,M=1表示最近波谷。
LIJIND4 := PEAK(3, LIJIND1, 1); 前M个波峰值。
LIJIND5 := TROUGH(3, LIJIND1, 2); 前第2个波谷。
LIJIND6 := PEAK(3, LIJIND1, 2); 前第2个波峰。
LIJIND7 := LIJIND2 > REF(LIJIND2,1); 判断ZIG值上升。
LIJIND8 := LIJIND2 < REF(LIJIND2,1); 下降。
然后画K线柱体:上升时洋红色,下降时浅蓝色。用STICKLINE。
DRAWLINE: 从波谷到下一个波峰画红色线,从波峰到下一个波谷画绿色线。
LIJIND9 := MIN(LIJIND4, LIJIND6); 前两个波峰的最小值。
LIJIND10 := MAX(LIJIND3, LIJIND5); 前两个波谷的最大值。
LIJIND11 := LIJIND9 > LIJIND10; 条件:较小波峰大于较大波谷,表示目前价格在某个区间
LIJIND12: IF(LIJIND11, LIJIND9, DRAWNULL) 画灰色点线在波峰较低水平。
LIJIND13: IF(LIJIND11, LIJIND10, DRAWNULL) 画灰色点线在波谷较高水平。
继续画矩形区域:STICKLINE(LIJIND11&&(LIJIND7||LIJIND8), LIJIND9, LIJIND10, 0, -1), COLORGRAY; 画灰色区域。
再次定义LIJIND14和LIJIND15(重复前面的4和3)。
DRAWNUMBER在波峰处标数值,波谷处标数值。
整体来看,这是一个基于ZIG转向指标的趋势分析,识别峰谷,画出趋势线,标记高低点,并在特定条件下画出“箱体”区域(当较小波峰大于较大波谷时,画一个矩形和水平线)。
二、指标图谱展示


图二:指标指数示范图
三、指标Python代码
# -*- coding: utf-8 -*-"""通达信 ZIG 转向指标 Python 实现功能:1. ZIG 折线计算(基于收盘价的百分比转向)2. 波峰/波谷识别与值提取3. 绘制峰谷之间的趋势线(红涨绿跌)4. 箱体区域判定与可视化(灰色区域 + 水平虚线)5. K线颜色标记(涨洋红、跌淡蓝)6. 峰谷数值标注"""import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport matplotlib.dates as mdatesfrom mplfinance.original_flavor import candlestick_ohlcimport akshare as ak # 数据源,也可替换为 yfinance 等# ==================== 1. ZIG 转向算法 ====================def calc_zig(close, percent=5):"""计算 ZIG 折线(未来函数版本,一次性处理全部历史数据)参数:close: np.array, 收盘价序列percent: float, 转向百分比(默认5%)返回:zig: np.array, ZIG 折线值pivots: list of (index, price, type) 转折点列表,type='peak' 或 'trough'"""n = len(close)if n == 0:return np.array([]), []# 初始化direction = None # 'up' 或 'down'ext_price = close[0] # 当前极值价格ext_idx = 0 # 当前极值索引pivots = [] # 存储转折点 (index, price, type)for i in range(1, n):pct_change = (close[i] - ext_price) / ext_price * 100if direction is None:if pct_change >= percent:direction = 'up'ext_price = close[i]ext_idx = ielif pct_change <= -percent:direction = 'down'ext_price = close[i]ext_idx = i# 否则保持,不记录转折点elif direction == 'up':if close[i] >= ext_price:# 继续向上,更新极值ext_price = close[i]ext_idx = ielif pct_change <= -percent:# 转向向下,记录前一波峰pivots.append((ext_idx, ext_price, 'peak'))direction = 'down'ext_price = close[i]ext_idx = ielif direction == 'down':if close[i] <= ext_price:# 继续向下ext_price = close[i]ext_idx = ielif pct_change >= percent:# 转向向上,记录前一波谷pivots.append((ext_idx, ext_price, 'trough'))direction = 'up'ext_price = close[i]ext_idx = i# 添加最后一个极值点(若未成对)if direction == 'up':pivots.append((ext_idx, ext_price, 'peak'))elif direction == 'down':pivots.append((ext_idx, ext_price, 'trough'))# 去重(连续相同类型只保留一个)unique_pivots = []for idx, price, ptype in pivots:if not unique_pivots or unique_pivots[-1][2] != ptype:unique_pivots.append((idx, price, ptype))else:# 相同类型保留更极端的(峰值取大,谷值取小)last = unique_pivots[-1]if ptype == 'peak' and price > last[1]:unique_pivots[-1] = (idx, price, ptype)elif ptype == 'trough' and price < last[1]:unique_pivots[-1] = (idx, price, ptype)pivots = unique_pivots# 线性插值填充 zig 序列zig = np.full(n, np.nan)if len(pivots) == 0:zig[:] = close[0]return zig, pivots# 第一个转折点之前的区域用第一个点值填充first_idx = pivots[0][0]zig[:first_idx+1] = pivots[0][1]# 转折点之间线性插值for j in range(len(pivots)-1):idx1, price1, _ = pivots[j]idx2, price2, _ = pivots[j+1]if idx2 > idx1:x = np.arange(idx1, idx2+1)y = np.linspace(price1, price2, len(x))zig[idx1:idx2+1] = y# 最后一个转折点到末尾填充last_idx = pivots[-1][0]zig[last_idx:] = pivots[-1][1]return zig, pivots# ==================== 2. 提取波峰/波谷值 ====================def get_peaks_troughs(pivots):"""从转折点列表中分离波峰和波谷"""peaks = [(idx, price) for idx, price, ptype in pivots if ptype == 'peak']troughs = [(idx, price) for idx, price, ptype in pivots if ptype == 'trough']return peaks, troughsdef get_nth_peak(peaks, n):"""获取第 n 个波峰值(1为最近)"""if n <= len(peaks):return peaks[-n][1]return np.nandef get_nth_trough(troughs, n):"""获取第 n 个波谷值(1为最近)"""if n <= len(troughs):return troughs[-n][1]return np.nandef get_peak_bars(peaks, current_idx):"""当前K线到最近波峰的周期数(0表示当前就是波峰)"""if not peaks:return np.nanlast_peak_idx = peaks[-1][0]return current_idx - last_peak_idxdef get_trough_bars(troughs, current_idx):"""当前K线到最近波谷的周期数"""if not troughs:return np.nanlast_trough_idx = troughs[-1][0]return current_idx - last_trough_idx# ==================== 3. 主计算函数 ====================def compute_indicators(df, percent=5):"""计算全部指标并返回带标记的 DataFramedf: 包含 'date', 'open', 'high', 'low', 'close' 列"""close = df['close'].valuesn = len(df)# ZIG 与转折点zig, pivots = calc_zig(close, percent)peaks, troughs = get_peaks_troughs(pivots)# LIJIND7 / LIJIND8: ZIG 上升/下降zig_series = pd.Series(zig)df['zig'] = zigdf['zig_up'] = zig_series > zig_series.shift(1)df['zig_down'] = zig_series < zig_series.shift(1)# 波峰波谷值df['peak1'] = np.nandf['trough1'] = np.nandf['peak2'] = np.nandf['trough2'] = np.nanfor i in range(n):# 最近波峰/谷的值df.loc[i, 'peak1'] = get_nth_peak(peaks, 1)df.loc[i, 'trough1'] = get_nth_trough(troughs, 1)df.loc[i, 'peak2'] = get_nth_peak(peaks, 2)df.loc[i, 'trough2'] = get_nth_trough(troughs, 2)# LIJIND9 = MIN(峰值1, 峰值2)df['min_peak'] = df[['peak1', 'peak2']].min(axis=1)# LIJIND10 = MAX(谷值1, 谷值2)df['max_trough'] = df[['trough1', 'trough2']].max(axis=1)# LIJIND11: 较小的峰值 > 较大的谷值df['box_condition'] = df['min_peak'] > df['max_trough']# 波峰/波谷位置标记(用于绘图)df['is_peak'] = Falsedf['is_trough'] = Falsefor idx, _ in peaks:df.loc[idx, 'is_peak'] = Truefor idx, _ in troughs:df.loc[idx, 'is_trough'] = True# 波峰/波谷数量标记(用于DRAWNUMBER)return df, pivots, peaks, troughs# ==================== 4. 绘图(专业风格) ====================def plot_zig_indicator(df, pivots, peaks, troughs, title="ZIG 转向指标"):"""绘制 K线图 + ZIG折线 + 趋势线 + 箱体区域 + K线着色"""# 准备OHLC数据ohlc = []dates = df['date'].valuesfor i, row in df.iterrows():# mplfinance candlestick 需要数值化的日期ohlc.append([i, row['open'], row['high'], row['low'], row['close']])fig, ax = plt.subplots(figsize=(14, 8))fig.subplots_adjust(bottom=0.1)# 绘制K线candlestick_ohlc(ax, ohlc, width=0.6, colorup='red', colordown='green', alpha=0.8)# 根据 ZIG 上升/下降 重新覆盖K线颜色(原公式效果)for i, row in df.iterrows():if row['zig_up']:color = 'magenta' # 洋红elif row['zig_down']:color = 'lightskyblue' # 淡蓝else:continue# 画一个半透明矩形覆盖K线区间(从开盘到收盘,影线上使用相同颜色边框即可)ax.add_patch(plt.Rectangle((i-0.4, row['low']), 0.8, row['high']-row['low'],facecolor=color, edgecolor=color, alpha=0.3))# 绘制 ZIG 折线ax.plot(df.index, df['zig'], color='black', linewidth=1.5, label='ZIG(3,5)')# 绘制峰谷连线(红色:谷->峰;绿色:峰->谷)for j in range(len(pivots)-1):idx1, price1, ptype1 = pivots[j]idx2, price2, ptype2 = pivots[j+1]if ptype1 == 'trough' and ptype2 == 'peak':ax.plot([idx1, idx2], [price1, price2], color='red', linewidth=2, label='_nolegend_')elif ptype1 == 'peak' and ptype2 == 'trough':ax.plot([idx1, idx2], [price1, price2], color='green', linewidth=2, label='_nolegend_')# 标注波峰/波谷数字for idx, price in peaks:ax.text(idx, price*1.02, f'{price:.2f}', ha='center', va='bottom',fontsize=8, color='red', fontweight='bold')for idx, price in troughs:ax.text(idx, price*0.98, f'{price:.2f}', ha='center', va='top',fontsize=8, color='green', fontweight='bold')# 箱体区域绘制(灰色矩形 + 水平虚线)box_start = 0box_end = len(df)-1in_box = Falsefor i, row in df.iterrows():if row['box_condition'] and not in_box:in_box = Truebox_start = ielif not row['box_condition'] and in_box:# 结束当前箱体ax.axhspan(df.loc[box_start, 'max_trough'], df.loc[box_start, 'min_peak'],xmin=box_start/len(df), xmax=(i-1)/len(df),facecolor='gray', alpha=0.2)# 画水平虚线ax.hlines(df.loc[box_start, 'min_peak'], box_start, i-1,colors='gray', linestyles='--', linewidth=1)ax.hlines(df.loc[box_start, 'max_trough'], box_start, i-1,colors='gray', linestyles='--', linewidth=1)in_box = Falseif in_box:ax.axhspan(df.loc[box_start, 'max_trough'], df.loc[box_start, 'min_peak'],xmin=box_start/len(df), xmax=1,facecolor='gray', alpha=0.2)ax.hlines(df.loc[box_start, 'min_peak'], box_start, len(df)-1,colors='gray', linestyles='--', linewidth=1)ax.hlines(df.loc[box_start, 'max_trough'], box_start, len(df)-1,colors='gray', linestyles='--', linewidth=1)# 图表装饰ax.set_title(title, fontsize=16)ax.set_xlabel('交易日期')ax.set_ylabel('价格')ax.legend(loc='best')ax.grid(True, linestyle='--', alpha=0.5)# 设置x轴标尺为日期tick_step = max(1, len(df)//10)ax.set_xticks(range(0, len(df), tick_step))ax.set_xticklabels([dates[i].strftime('%Y-%m-%d') for i in range(0, len(df), tick_step)],rotation=45, ha='right')plt.tight_layout()plt.show()# ==================== 5. 主程序示例 ====================if __name__ == '__main__':# 获取股票数据(示例:贵州茅台,2023年数据)symbol = "600519" # 贵州茅台df = ak.stock_zh_a_hist(symbol, period="daily", start_date="20230101", end_date="20231231", adjust="qfq")df.rename(columns={'日期': 'date','开盘': 'open','收盘': 'close','最高': 'high','最低': 'low','成交量': 'volume'}, inplace=True)df['date'] = pd.to_datetime(df['date'])df.sort_values('date', inplace=True)df.reset_index(drop=True, inplace=True)# 计算指标df_result, pivots, peaks, troughs = compute_indicators(df, percent=5)# 绘图plot_zig_indicator(df_result, pivots, peaks, troughs, title=f"{symbol} ZIG(3,5) 指标")# 可选:打印最近两峰两谷数据print("最近两根波峰:", [p[1] for p in peaks[-2:]])print("最近两根波谷:", [t[1] for t in troughs[-2:]])print("箱体条件满足:", df_result['box_condition'].iloc[-1])

四、指标公式源代码
|
LIJIND1:=5; LIJIND2:=ZIG(3,LIJIND1); LIJIND3:=TROUGH(3,LIJIND1,1); LIJIND4:=PEAK(3,LIJIND1,1); LIJIND5:=TROUGH(3,LIJIND1,2); LIJIND6:=PEAK(3,LIJIND1,2); LIJIND7:=LIJIND2>REF(LIJIND2,1); LIJIND8:=LIJIND2<REF(LIJIND2,1); STICKLINE(LIJIND7,H,L,0,0),COLORMAGENTA; STICKLINE(LIJIND7,C,O,3,1),COLORMAGENTA; STICKLINE(LIJIND8,H,L,0,0),COLORLIBLUE; STICKLINE(LIJIND8,C,O,3,1),COLORLIBLUE; DRAWLINE(TROUGHBARS(3,LIJIND1,1)=0,L,PEAKBARS(3,LIJIND1,1)=0,H,0),COLORRED,LINETHICK2; DRAWLINE(PEAKBARS(3,LIJIND1,1)=0,H,TROUGHBARS(3,LIJIND1,1)=0,L,0),COLORGREEN,LINETHICK2; LIJIND9:=MIN(LIJIND4,LIJIND6); LIJIND10:=MAX(LIJIND3,LIJIND5); LIJIND11:=LIJIND9>LIJIND10; LIJIND12:IF(LIJIND11,LIJIND9,DRAWNULL),COLORGRAY,DOTLINE; LIJIND13:IF(LIJIND11,LIJIND10,DRAWNULL),COLORGRAY,DOTLINE; STICKLINE(LIJIND11&&(LIJIND7||LIJIND8),LIJIND9,LIJIND10,0,-1),COLORGRAY; LIJIND14:=PEAK(3,LIJIND1,1); LIJIND15:=TROUGH(3,LIJIND1,1); DRAWNUMBER(PEAKBARS(3,LIJIND1,1)=0,H*1.01,LIJIND14),COLORRED; DRAWNUMBER(TROUGHBARS(3,LIJIND1,1)=0,L*0.99,LIJIND15),COLORGREEN; |
分享知识:与人为善,分享快乐!爱人如己,我为人人!
自用指标




夜雨聆风

