通达信zig方法的java实现

package util;

import com.alibaba.fastjson.JSONObject;
import main.original.YGFutureTechIndexKline;
import main.talib.YGFutureTechIndexTaLibSMA;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class YGFutureMaiToJava {
   /*
        首先从您第一根K线算起,看每根K线的最高价,和第一根K线的最高价相比是不是涨幅超过10%
    (这里假设第一根K线的最高价位置比较低,位置高的画线原理是一样的),把第一次涨幅超过10%
    的这个点成为上拐点,然后K线继续往后走,出现了一个最高点,然后开始下跌了,这个最高点我们记为A,
    然后K线往后走的跌幅是否超过10%,把第一次跌幅超过10%的K线记为下拐点,如果这个下拐点成立了,
    那么之前的A的这个位置就发生一次转向,就是我们看到的折线,如下图,最低点位置开始,上面一条横线就是上拐点位置,
    然后出现了最高点,再往下走,出现了下拐点,那么证明最高点处应该转折,之后都是按照这个原理画的。
    zig函数产生的连线是连接的最大值和最小值
    */
    //参数1周期长度,参数2百分比
    public static List<Double> getZigZag(List<Double> numbers, Double percentage){
        //     循环前的变量初始化
        //     端点 候选点 扫描点 端点列表 拐点线列表 趋势状态
        int ZIG_STATE_START = 0;
        int ZIG_STATE_RISE = 1;
        int ZIG_STATE_FALL = 2;
        int peer_i = 0;
        Integer candidate_i = 0;
        int scan_i = 0;
        List<Integer> peers = new ArrayList<>();
        List<Double> ziglst = new ArrayList<>();
        int state = ZIG_STATE_START;
        percentage = percentage/100;
        
        if(numbers.size()<2){
            return null;
        }
        while (true) {
            scan_i += 1;
            if (scan_i == numbers.size() - 1) {
                // 扫描到尾部
                if (candidate_i == null) {
                    peer_i = scan_i;
                    peers.add(peer_i);
                } else {
                    if (state == ZIG_STATE_RISE) {
                        if (numbers.get(scan_i) >= numbers.get(candidate_i)) {
                            peer_i = scan_i;
                            peers.add(peer_i);
                        } else {
                            peer_i = candidate_i;
                            peers.add(peer_i);
                            peer_i = scan_i;
                            peers.add(peer_i);
                        }
                    } else if (state == ZIG_STATE_FALL) {
                        if (numbers.get(scan_i) <= numbers.get(candidate_i)) {
                            peer_i = scan_i;
                            peers.add(peer_i);
                        } else {
                            peer_i = candidate_i;
                            peers.add(peer_i);
                            peer_i = scan_i;
                            peers.add(peer_i);
                        }
                    }
                }
                break;
            }

            ///
            if (state == ZIG_STATE_START) {
                if (numbers.get(scan_i) >= numbers.get(peer_i) * (1 + percentage)) {
                    candidate_i = scan_i;
                    state = ZIG_STATE_RISE;
                } else if (numbers.get(scan_i) <= numbers.get(peer_i) * (1 - percentage)) {
                    candidate_i = scan_i;
                    state = ZIG_STATE_FALL;
                }
                peers.add(peer_i);
            } else if (state == ZIG_STATE_RISE) {
                if (numbers.get(scan_i) >= numbers.get(candidate_i)) {
                    candidate_i = scan_i;
                } else if (numbers.get(scan_i) <= numbers.get(candidate_i) * (1 - percentage)) {
                    peer_i = candidate_i;
                    peers.add(peer_i);
                    state = ZIG_STATE_FALL;
                    candidate_i = scan_i;
                }
            } else if (state == ZIG_STATE_FALL) {
                if (numbers.get(scan_i) <= numbers.get(candidate_i)) {
                    candidate_i = scan_i;
                } else if (numbers.get(scan_i) >= numbers.get(candidate_i) * (1 + percentage)) {
                    peer_i = candidate_i;
                    peers.add(peer_i);
                    state = ZIG_STATE_RISE;
                    candidate_i = scan_i;
                }
            }
        }

        //线性插值, 计算出zig的值
        for(int i=1;i<peers.size();i++){

            int  peer_start_i = peers.get(i-1);
            int peer_end_i = peers.get(i);
            Double start_value = numbers.get(peer_start_i);
            Double end_value = numbers.get(peer_end_i);
            Double a = (end_value - start_value)/(peer_end_i - peer_start_i);// 斜率

            if(peer_start_i == 0){
                for(int j=0;j<(peer_end_i - peer_start_i +1);j++){
                    ziglst.add(start_value + a*j);
                }
            }else {
                for(int j=1;j<(peer_end_i - peer_start_i +1);j++){
                    ziglst.add(start_value + a*j);
                }
            }
        }
        return ziglst;
    }

    //本方法中troughPositionlst存储所有波谷的位置,peakPositionlst存储所有波峰的位置
    public static  List<Integer> getTROUGHBARS(List<Double> numbers, Double percentage) {
        int ZIG_STATE_START = 0;
        int ZIG_STATE_RISE = 1;
        int ZIG_STATE_FALL = 2;
        int state = ZIG_STATE_START;
        List<Double> troughBarslst = getZigZag(numbers, percentage);
        List<Integer> troughPositionlst = new ArrayList<>();
        List<Integer> peakPositionlst = new ArrayList<>();

        if (troughBarslst != null && troughBarslst.size() > 0) {
            for (int i = 1; i < troughBarslst.size(); i++) {
                if (i == troughBarslst.size() - 1) {
                    // 扫描到尾部
                    if (state == ZIG_STATE_RISE) {
                        if (troughBarslst.get(i) <= troughBarslst.get(i - 1)) {
                            troughPositionlst.add(i);
                            peakPositionlst.add(i - 1);
                        }
                    }
                     else if (state == ZIG_STATE_FALL) {
                            if (troughBarslst.get(i) >= troughBarslst.get(i - 1)) {
                                troughPositionlst.add(i - 1);
                                peakPositionlst.add(i);
                            }
                     }


                    break;
                }
   ///
                    if (state == ZIG_STATE_START) {
                        if (troughBarslst.get(i) >= troughBarslst.get(i - 1)) {
                            state = ZIG_STATE_RISE;
                            troughPositionlst.add(i - 1);
                        } else if (troughBarslst.get(i) <= troughBarslst.get(i - 1)) {
                            state = ZIG_STATE_FALL;
                            peakPositionlst.add(i - 1);
                        }
                    } else if (state == ZIG_STATE_RISE) {
                        if (troughBarslst.get(i) <= troughBarslst.get(i - 1)) {
                            state = ZIG_STATE_FALL;
                            peakPositionlst.add(i - 1);
                        }
                    } else if (state == ZIG_STATE_FALL) {
                        if (troughBarslst.get(i) >= troughBarslst.get(i - 1)) {
                            state = ZIG_STATE_RISE;
                            troughPositionlst.add(i - 1);
                        }
                    }
                }
            }
        else {
                return null;
        }
        return troughPositionlst;

    }
}
<think>好的,我现在需要帮助用户解决如何用Python实现通达信ZIG函数的问题。首先,我需要回忆一下ZIG函数的定义。ZIG函数通常用于技术分析,用来识别价格走势中的转折点,比如高点和低点的形成。用户提供的引用中提到,他们通过自定义函数和matplotlib来绘制高低点图表,但示例可能不够精确。 接下来,我需要确认用户的需求。用户希望看到示例代码,并且可能希望了解具体的实现步骤。根据引用中的信息,示例代码使用了高低点数据列表,并通过plot方法绘制图表。但用户可能需要更详细的实现方法,包括如何计算这些转折点。 首先,ZIG函数的实现通常基于价格的波动率或百分比变化。例如,当价格从最低点上涨超过设定的阈值时,标记为低点;反之,当从最高点下跌超过阈值时,标记为高点。我需要将这个逻辑转化为Python代码。 然后,我需要考虑数据结构。假设用户使用Pandas DataFrame来处理股票数据,需要遍历数据点,跟踪当前的高点和低点,并根据阈值判断是否形成转折点。这涉及到循环遍历每个数据点,并比较当前价格与之前的高点或低点的变化是否超过阈值。 接下来,代码结构可能包括初始化高点和低点的变量,遍历每个数据点,检查是否符合转折条件,并记录这些转折点的位置和值。此外,可能需要处理数据中的NaN值,特别是在初始阶段没有足够数据进行比较时。 然后,根据引用中的示例,用户可能需要绘制这些转折点。因此,在代码中需要将转折点的索引和价格提取出来,并使用matplotlib进行可视化。这包括在折线图上用不同颜色或标记突出显示高点和低点。 在编写代码时,需要注意算法的效率和准确性。例如,处理大量数据时,循环可能较慢,但考虑到ZIG函数通常用于分析,可能可以接受。另外,阈值的设置会影响转折点的数量,用户可能需要调整这个参数以达到理想的效果。 此外,需要验证代码的正确性。例如,使用示例数据运行代码,检查转折点是否被正确识别,并确保绘制的图表符合预期。如果用户提供的引用中有相关的数据获取方法(如使用ts.get_h_data),可能需要确保数据格式正确,比如索引是否为日期时间类型,以便正确绘图。 最后,用户可能希望了解如何优化这个实现,比如提高计算速度或处理更复杂的情况。同时,可能需要指出当前实现的局限性,比如只考虑单向波动或阈值固定,而实际中可能需要动态调整阈值或处理更多条件。 总结步骤:定义阈值,遍历数据,跟踪高低点,记录转折点,绘制结果。同时,根据引用中的信息,提醒用户如果需要更精确的功能,可能需要参考通达信软件或更复杂的算法。</think>### Python实现通达信ZIG函数的方法 #### 1. ZIG函数的核心逻辑 ZIG函数的核心是识别价格序列中的**转折点**,其判断依据是价格相对于前一个极值点的波动幅度超过设定阈值(例如5%)。例如: - 当价格从低点反弹超过阈值时,标记该低点为转折点; - 当价格从高点回撤超过阈值时,标记该高点为转折点[^1]。 #### 2. 实现代码示例 ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt def calculate_zig(data, threshold=0.05): highs, lows = [], [] zig_points = {'highs': [], 'lows': []} current_high = None current_low = None for i in range(len(data)): price = data['close'].iloc[i] # 初始化第一个极值点 if i == 0: current_high = price current_low = price continue # 检测高点回撤是否超过阈值 if current_high is not None: if (current_high - price) / current_high >= threshold: zig_points['highs'].append((i-1, current_high)) current_low = price # 切换为寻找低点 current_high = None # 检测低点反弹是否超过阈值 elif current_low is not None: if (price - current_low) / current_low >= threshold: zig_points['lows'].append((i-1, current_low)) current_high = price # 切换为寻找高点 current_low = None # 更新当前极值 if current_high is None and current_low is not None: current_low = min(current_low, price) elif current_low is None and current_high is not None: current_high = max(current_high, price) return zig_points # 示例数据(需替换为实际数据) dates = pd.date_range(start='2023-01-01', periods=100, freq='D') prices = np.random.normal(100, 5, 100).cumsum() df = pd.DataFrame({'close': prices}, index=dates) # 计算转折点 zig_data = calculate_zig(df, threshold=0.03) # 绘制结果 plt.figure(figsize=(12,6)) plt.plot(df.index, df['close'], label='Price') plt.scatter( [df.index[i] for i, _ in zig_data['highs']], [price for _, price in zig_data['highs']], color='red', marker='v', label='Highs' ) plt.scatter( [df.index[i] for i, _ in zig_data['lows']], [price for _, price in zig_data['lows']], color='green', marker='^', label='Lows' ) plt.legend() plt.show() ``` #### 3. 关键参数说明 - `threshold=0.05`: 波动率阈值,可调节转折点灵敏度 - `data['close']`: 需要输入包含收盘价的DataFrame - `zig_points`: 返回值包含高点和低点的索引及价格 #### 4. 注意事项 - 实际应用需处理**数据清洗**(如缺失值) - 建议结合**均线系统**过滤噪声信号 - 不同周期参数(如周线/日线)需重新优化阈值[^2]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值