Administrator
7 days ago ff340aba27d8990386fa788a182c2ace0a4c2ad8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
package com.xcong.excoin.modules.okxNewPrice.indicator;
 
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 交易策略实现
 * 展示如何为ETH合约交易(开仓/平仓)组合所有指标
 */
@Slf4j
public class TradingStrategy extends IndicatorBase {
 
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyConfig {
        private int maShortPeriod = 5;      // 短期移动平均周期
        private int maLongPeriod = 20;      // 长期移动平均周期
        private int rsiPeriod = 14;         // RSI指标周期
        private int kdjPeriod = 9;          // KDJ指标周期
        private int bollPeriod = 20;        // 布林带周期
        private double bollK = 2.0;         // 布林带标准差倍数
        private int atrPeriod = 14;         // ATR计算周期
        private boolean enableDynamicParams = true; // 是否启用动态参数优化
        private boolean enableMultiTimeframeConfirm = true; // 是否启用多周期确认
        private int volumeMaPeriod = 20;    // 成交量移动平均周期
        private boolean enableVolumeConfirm = true; // 是否启用成交量验证
        
        // 风险控制参数
        private BigDecimal baseLeverage = new BigDecimal(3); // 基础杠杆倍数
        private int volatilityThresholdPeriod = 30; // 波动率阈值计算周期(用于动态杠杆)
        private boolean enableDynamicLeverage = true; // 是否启用动态杠杆
        private boolean enableThreeStepProfitTaking = true; // 是否启用三段式止盈
        private boolean enableBlackSwanFilter = true; // 是否启用黑天鹅事件过滤
    }
 
    public enum Direction {
        LONG,      // 做多方向信号
        SHORT,     // 做空方向信号
        RANGING    // 震荡市场
    }
 
    public enum SignalType {
        NONE,      // 无信号
        BUY,       // 开多信号
        SELL,      // 开空信号
        CLOSE_BUY, // 平多信号
        CLOSE_SELL // 平空信号
    }
 
    private final StrategyConfig config;
    private final MA ma;
    private final AdvancedMA advancedMA;
    private final BOLL boll;
    private final KDJ kdj;
    private final MACD macd;
    private final RSI rsi;
 
    public TradingStrategy() {
        this(new StrategyConfig());
    }
 
    public TradingStrategy(StrategyConfig config) {
        this.config = config;
        this.ma = new MA();
        this.advancedMA = new AdvancedMA();
        this.boll = new BOLL(config.getBollPeriod(), config.getBollK());
        this.kdj = new KDJ(config.getKdjPeriod());
        this.macd = new MACD();
        this.rsi = new RSI(config.getRsiPeriod());
    }
 
    /**
     * 计算所有指标并生成交易信号
     * @param prices 价格数据
     * @param high 最高价列表
     * @param low 最低价列表
     * @param close 收盘价列表
     * @param volume 成交量列表
     * @param currentPrice 当前价格
     * @param hasLongPosition 是否当前持有做多仓位
     * @param hasShortPosition 是否当前持有做空仓位
     * @param fiveMinPrices 5分钟价格数据(多周期确认)
     * @param oneHourPrices 1小时价格数据(多周期确认)
     * @param fourHourPrices 4小时价格数据(多周期确认)
     * @param fundingRate 当前资金费率(用于黑天鹅过滤)
     * @param hasLargeTransfer 是否有大额转账(用于黑天鹅过滤)
     * @param hasUpcomingEvent 是否有即将到来的重大事件(用于黑天鹅过滤)
     * @return 交易信号
     */
    public SignalType generateSignal(List<BigDecimal> prices, List<BigDecimal> high,
                                    List<BigDecimal> low, List<BigDecimal> close,
                                    List<BigDecimal> volume, BigDecimal currentPrice,
                                    boolean hasLongPosition, boolean hasShortPosition,
                                    List<BigDecimal> fiveMinPrices,
                                    List<BigDecimal> oneHourPrices,
                                    List<BigDecimal> fourHourPrices,
                                    BigDecimal fundingRate,
                                    boolean hasLargeTransfer,
                                    boolean hasUpcomingEvent) {
        // 计算所有指标
        calculateIndicators(prices, high, low, close);
 
        // 检查是否为震荡市场,如果是,则执行区间交易策略
        if (isRangeMarket(prices)) {
            log.info("当前市场为震荡行情,执行区间交易策略");
            return generateRangeTradingSignal(currentPrice, volume, hasLongPosition, hasShortPosition);
        }
 
        // 黑天鹅事件过滤
        if (blackSwanFilter(fundingRate, hasLargeTransfer, hasUpcomingEvent)) {
            log.info("黑天鹅事件过滤触发,不产生信号");
            return SignalType.NONE;
        }
 
        // 开多信号
        if (shouldOpenLong(currentPrice, prices, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
            log.info("生成买入信号");
            return SignalType.BUY;
        }
 
        // 开空信号
        if (shouldOpenShort(currentPrice, prices, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
            log.info("生成卖出信号");
            return SignalType.SELL;
        }
 
        // 平多信号
        if (shouldCloseLong(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasLongPosition) {
            log.info("生成平多信号");
            return SignalType.CLOSE_BUY;
        }
 
        // 平空信号
        if (shouldCloseShort(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasShortPosition) {
            log.info("生成平空信号");
            return SignalType.CLOSE_SELL;
        }
 
        log.info("未生成信号");
        return SignalType.NONE;
    }
 
    /**
     * 多周期确认辅助方法(看涨)
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否有足够的多周期确认
     */
    private boolean multiTimeframeConfirm(List<BigDecimal> fiveMinPrices,
                                         List<BigDecimal> oneHourPrices,
                                         List<BigDecimal> fourHourPrices) {
        if (!config.isEnableMultiTimeframeConfirm()) {
            return true; // 如果未启用多周期确认,则默认返回true
        }
 
        int confirmCount = 0;
 
        // 检查5分钟周期
        if (hasBullishTrend(fiveMinPrices)) {
            confirmCount++;
        }
 
        // 检查1小时周期
        if (hasBullishTrend(oneHourPrices)) {
            confirmCount++;
        }
 
        // 检查4小时周期
        if (hasBullishTrend(fourHourPrices)) {
            confirmCount++;
        }
 
        // 至少需要2个周期确认
        return confirmCount >= 2;
    }
    
    /**
     * 多周期确认辅助方法(看跌)
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否有足够的多周期确认
     */
    private boolean multiTimeframeBearishConfirm(List<BigDecimal> fiveMinPrices,
                                         List<BigDecimal> oneHourPrices,
                                         List<BigDecimal> fourHourPrices) {
        if (!config.isEnableMultiTimeframeConfirm()) {
            return true; // 如果未启用多周期确认,则默认返回true
        }
 
        int confirmCount = 0;
 
        // 检查5分钟周期
        if (hasBearishTrend(fiveMinPrices)) {
            confirmCount++;
        }
 
        // 检查1小时周期
        if (hasBearishTrend(oneHourPrices)) {
            confirmCount++;
        }
 
        // 检查4小时周期
        if (hasBearishTrend(fourHourPrices)) {
            confirmCount++;
        }
 
        // 至少需要2个周期确认
        return confirmCount >= 2;
    }
 
    /**
     * 检查指定周期是否有看涨趋势
     * @param prices 价格数据
     * @return 是否有看涨趋势
     */
    private boolean hasBullishTrend(List<BigDecimal> prices) {
        if (prices == null || prices.size() < 20) {
            return false; // 数据不足
        }
 
        // 创建临时MA指标用于判断趋势
        MA tempMA = new MA();
        MACD tempMACD = new MACD();
        
        // 计算指标
        tempMA.calculate(prices);
        tempMACD.calculate(prices);
 
        // 优化后的多头趋势判断:
        // 1. MA多头排列:短期MA > 中期MA > 长期MA
        // 2. 所有均线向上发散
        // 3. MACD趋势:DIFF线在DEA线之上
        boolean isMaBullish = tempMA.getEma5().compareTo(tempMA.getEma10()) > 0 && 
                             tempMA.getEma10().compareTo(tempMA.getEma20()) > 0;
        
        // 判断均线向上发散(简单方法:近期均线斜率为正)
        boolean isMaDivergingUp = calculateMaSlope(prices, 5) > 0 && 
                                 calculateMaSlope(prices, 10) > 0 && 
                                 calculateMaSlope(prices, 20) > 0;
                                 
        // MACD趋势判断
        boolean isMacdBullish = tempMACD.getDif().compareTo(tempMACD.getDea()) > 0;
 
        return isMaBullish && isMaDivergingUp && isMacdBullish;
    }
 
    /**
     * 检查指定周期是否有看跌趋势
     * @param prices 价格数据
     * @return 是否有看跌趋势
     */
    private boolean hasBearishTrend(List<BigDecimal> prices) {
        if (prices == null || prices.size() < 20) {
            return false; // 数据不足
        }
 
        // 创建临时MA指标用于判断趋势
        MA tempMA = new MA();
        MACD tempMACD = new MACD();
        
        // 计算指标
        tempMA.calculate(prices);
        tempMACD.calculate(prices);
 
        // 优化后的空头趋势判断:
        // 1. MA空头排列:短期MA < 中期MA < 长期MA
        // 2. 所有均线向下发散
        // 3. MACD趋势:DIFF线在DEA线之下
        boolean isMaBearish = tempMA.getEma5().compareTo(tempMA.getEma10()) < 0 && 
                             tempMA.getEma10().compareTo(tempMA.getEma20()) < 0;
        
        // 判断均线向下发散(简单方法:近期均线斜率为负)
        boolean isMaDivergingDown = calculateMaSlope(prices, 5) < 0 && 
                                   calculateMaSlope(prices, 10) < 0 && 
                                   calculateMaSlope(prices, 20) < 0;
                                   
        // MACD趋势判断
        boolean isMacdBearish = tempMACD.getDif().compareTo(tempMACD.getDea()) < 0;
 
        return isMaBearish && isMaDivergingDown && isMacdBearish;
    }
 
    /**
     * 计算均线斜率
     * @param prices 价格数据
     * @param period 均线周期
     * @return 均线斜率(正数表示向上,负数表示向下)
     */
    private double calculateMaSlope(List<BigDecimal> prices, int period) {
        if (prices == null || prices.size() < period * 2) {
            return 0; // 数据不足
        }
        
        // 获取最近两个周期的均线值
        int endIndex = prices.size() - 1;
        int startIndex = endIndex - period + 1;
        
        // 计算当前周期的均线
        BigDecimal currentMa = calculateMA(prices.subList(startIndex, endIndex + 1), period);
        
        // 计算前一个周期的均线
        int prevStartIndex = startIndex - period;
        BigDecimal prevMa = calculateMA(prices.subList(prevStartIndex, startIndex), period);
        
        // 计算斜率(简单差值法)
        return currentMa.subtract(prevMa).doubleValue();
    }
    
    /**
     * 成交量验证辅助方法
     * 增强版:当前成交量需大于20周期均量的1.2倍,以过滤无量反弹/回调的假信号
     * @param volume 成交量列表
     * @return 是否通过成交量验证
     */
    private boolean volumeConfirm(List<BigDecimal> volume) {
        if (!config.isEnableVolumeConfirm() || volume == null || volume.size() < config.getVolumeMaPeriod()) {
            return true; // 如果未启用成交量验证或数据不足,则默认返回true
        }
 
        // 计算成交量移动平均
        BigDecimal volumeMA = calculateMA(volume, config.getVolumeMaPeriod());
        BigDecimal currentVolume = volume.get(volume.size() - 1);
 
        // 增强验证:成交量需要大于1.2倍均线
        return currentVolume.compareTo(volumeMA.multiply(new BigDecimal("1.2"))) > 0;
    }
 
    /**
     * 量价背离检测
     * 检测价格上涨/下跌但成交量萎缩的情况,或价格和成交量趋势不一致
     * @param prices 价格列表
     * @param volume 成交量列表
     * @return 是否存在量价背离
     */
    private boolean hasPriceVolumeDivergence(List<BigDecimal> prices, List<BigDecimal> volume) {
        if (!config.isEnableVolumeConfirm() || prices == null || volume == null || prices.size() < 3 || volume.size() < 3) {
            return false; // 如果未启用成交量验证或数据不足,则默认返回false
        }
 
        // 获取最近3个周期的价格和成交量
        BigDecimal currentPrice = prices.get(prices.size() - 1);
        BigDecimal prevPrice1 = prices.get(prices.size() - 2);
        BigDecimal prevPrice2 = prices.get(prices.size() - 3);
        
        BigDecimal currentVolume = volume.get(volume.size() - 1);
        BigDecimal prevVolume1 = volume.get(volume.size() - 2);
        BigDecimal prevVolume2 = volume.get(volume.size() - 3);
 
        // 计算价格趋势
        boolean priceTrendUp = currentPrice.compareTo(prevPrice1) > 0 && prevPrice1.compareTo(prevPrice2) > 0;
        boolean priceTrendDown = currentPrice.compareTo(prevPrice1) < 0 && prevPrice1.compareTo(prevPrice2) < 0;
        
        // 计算成交量趋势
        boolean volumeTrendUp = currentVolume.compareTo(prevVolume1) > 0 && prevVolume1.compareTo(prevVolume2) > 0;
        boolean volumeTrendDown = currentVolume.compareTo(prevVolume1) < 0 && prevVolume1.compareTo(prevVolume2) < 0;
 
        // 检测量价背离
        // 价格上涨但成交量萎缩
        boolean bullishDivergence = priceTrendUp && volumeTrendDown;
        // 价格下跌但成交量萎缩(通常是强势信号,不视为背离)
        // 价格下跌但成交量放大(可能是恐慌性抛售,视为背离)
        boolean bearishDivergence = priceTrendDown && volumeTrendUp;
 
        return bullishDivergence || bearishDivergence;
    }
 
    /**
     * 计算所有指标
     * @param prices 价格数据
     * @param high 最高价列表
     * @param low 最低价列表
     * @param close 收盘价列表
     */
    private void calculateIndicators(List<BigDecimal> prices, List<BigDecimal> high,
                                    List<BigDecimal> low, List<BigDecimal> close) {
        // 计算ATR和波动率
        BigDecimal atr = calculateATR(high, low, close, config.getAtrPeriod());
        BigDecimal volatility = normalizeVolatility(close, atr);
 
        // 使用动态参数计算指标
        if (config.isEnableDynamicParams()) {
            log.info("使用动态参数计算指标,波动率: {}", volatility);
            ma.calculate(prices, volatility);
            macd.calculate(prices, volatility);
        } else {
            ma.calculate(prices);
            macd.calculate(prices);
        }
 
        // 其他指标计算
        advancedMA.calculateTripleEMA(prices);
        boll.calculate(prices);
        kdj.calculate(prices);
        rsi.calculate(prices);
    }
 
    /**
     * 检查是否为震荡市场
     * @param prices 价格数据列表
     * @return 是否为震荡市场
     */
    private boolean isRangeMarket(List<BigDecimal> prices) {
        // 优化的震荡市场判断条件,放宽标准以减少RANGING信号频率
        
        // 1. 高级MA三线收敛(小于3%,放宽条件)
        boolean isMaConverged = advancedMA.calculatePercent().compareTo(new BigDecimal(3)) < 0;
        
        // 2. RSI中性区间(35-65,放宽条件)
        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(35)) > 0 &&
                              rsi.getRsi().compareTo(new BigDecimal(65)) < 0;
        
        // 3. BOLL带宽收窄(小于0.06,放宽条件)
        boolean isBollNarrow = boll.calculateBandWidth().compareTo(new BigDecimal(0.06)) < 0;
        
        // 4. MACD柱状图趋近于0(多空力量平衡,放宽条件)
        boolean isMacdBalanced = macd.getMacdBar().abs().compareTo(new BigDecimal(0.02)) < 0;
        
        // 5. KDJ在中间区域波动(25-75,放宽条件)
        boolean isKdjNeutral = kdj.getK().compareTo(new BigDecimal(25)) > 0 && 
                             kdj.getK().compareTo(new BigDecimal(75)) < 0 &&
                             kdj.getD().compareTo(new BigDecimal(25)) > 0 && 
                             kdj.getD().compareTo(new BigDecimal(75)) < 0 &&
                             kdj.getJ().compareTo(new BigDecimal(20)) > 0 && 
                             kdj.getJ().compareTo(new BigDecimal(80)) < 0;
        
        // 6. 价格波动范围较小(最近20根K线最高价与最低价的比值小于1.06,放宽条件)
        boolean isPriceVolatilityLow = calculatePriceVolatility(prices).compareTo(new BigDecimal(1.06)) < 0;
        
        // 综合判断:只需要满足部分条件即可,增加趋势信号的机会
        int rangeConditionsMet = 0;
        if (isMaConverged) {
            rangeConditionsMet++;
        }
        if (isRsiNeutral) {
            rangeConditionsMet++;
        }
        if (isBollNarrow) {
            rangeConditionsMet++;
        }
        if (isMacdBalanced) {
            rangeConditionsMet++;
        }
        if (isKdjNeutral) {
            rangeConditionsMet++;
        }
        if (isPriceVolatilityLow) {
            rangeConditionsMet++;
        }
        
        // 只有满足4个或以上条件才判定为震荡市场
        return rangeConditionsMet >= 4;
    }
    
    /**
     * 计算价格波动率(最近20根K线最高价与最低价的比值)
     * @param prices 价格数据列表
     * @return 价格波动率
     */
    private BigDecimal calculatePriceVolatility(List<BigDecimal> prices) {
        if (prices == null || prices.isEmpty()) {
            return BigDecimal.ONE;
        }
        
        List<BigDecimal> recentPrices = prices.subList(Math.max(0, prices.size() - 20), prices.size());
        if (recentPrices.isEmpty()) {
            return BigDecimal.ONE;
        }
        
        BigDecimal highest = recentPrices.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ONE);
        BigDecimal lowest = recentPrices.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ONE);
        
        return highest.divide(lowest, 10, RoundingMode.HALF_UP);
    }
 
 
 
    /**
     * 根据15分钟时间框架指标确定市场方向(做多/做空/震荡)
     * @param prices 价格数据列表
     * @param high 最高价列表
     * @param low 最低价列表
     * @param close 收盘价列表
     * @param currentPrice 当前价格
     * @return 市场方向
     */
    public Direction getDirection(List<BigDecimal> prices, List<BigDecimal> high, 
                                List<BigDecimal> low, List<BigDecimal> close,
                                BigDecimal currentPrice) {
        // 计算所有指标
        calculateIndicators(prices, high, low, close);
 
        // 检查是否为震荡市场
        if (isRangeMarket(prices)) {
            return Direction.RANGING;
        }
 
        // 优化后的多头趋势条件:
        // 1. MA多头排列(短期MA > 中期MA > 长期MA)
        // 2. MACD趋势(DIFF在DEA之上,代表多头趋势)
        // 3. 价格在BOLL中轨上方
        // 4. RSI(50-65) 为健康多头区间
        boolean isMaBullish = ma.getEma5().compareTo(ma.getEma10()) > 0 &&
                              ma.getEma10().compareTo(ma.getEma20()) > 0;
        boolean isMacdBullish = macd.getDif().compareTo(macd.getDea()) > 0;
        boolean isPriceAboveBollMid = currentPrice.compareTo(boll.getMid()) > 0;
        boolean isRsiBullish = rsi.getRsi().compareTo(new BigDecimal(50)) > 0 &&
                              rsi.getRsi().compareTo(new BigDecimal(65)) < 0;
        
        // 检查多头信号(MA多头 + MACD金叉 + 价格在BOLL中轨上方 + RSI(50-65))
        if (isMaBullish && isMacdBullish && isPriceAboveBollMid && isRsiBullish) {
            return Direction.LONG;
        }
 
        // 优化后的空头趋势条件:
        // 1. MA空头排列(短期MA < 中期MA < 长期MA)
        // 2. MACD趋势(DIFF在DEA之下,代表空头趋势)
        // 3. 价格在BOLL中轨下方
        // 4. RSI(35-50) 为健康空头区间
        boolean isMaBearish = ma.getEma5().compareTo(ma.getEma10()) < 0 &&
                              ma.getEma10().compareTo(ma.getEma20()) < 0;
        boolean isMacdBearish = macd.getDif().compareTo(macd.getDea()) < 0;
        boolean isPriceBelowBollMid = currentPrice.compareTo(boll.getMid()) < 0;
        boolean isRsiBearish = rsi.getRsi().compareTo(new BigDecimal(35)) > 0 &&
                              rsi.getRsi().compareTo(new BigDecimal(50)) < 0;
        
        // 检查空头信号(MA空头 + MACD死叉 + 价格在BOLL中轨下方 + RSI(35-50))
        if (isMaBearish && isMacdBearish && isPriceBelowBollMid && isRsiBearish) {
            return Direction.SHORT;
        }
 
        // 如果没有明确方向,默认为震荡
        return Direction.RANGING;
    }
 
    /**
     * 根据优化建议检查是否应该开多仓位
     * 使用主次结合法:
     * - 主信号(趋势):MA多头排列 + MACD金叉
     * - 辅信号(入场点):价格回调至BOLL中轨附近获得支撑,且出现KDJ金叉或RSI从低位回升至50以上
     * @param currentPrice 当前价格
     * @param prices 价格数据
     * @param volume 成交量列表
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否应该开多
     */
    private boolean shouldOpenLong(BigDecimal currentPrice, List<BigDecimal> prices, List<BigDecimal> volume,
                                  List<BigDecimal> fiveMinPrices,
                                  List<BigDecimal> oneHourPrices,
                                  List<BigDecimal> fourHourPrices) {
        // 主信号:趋势判断
        // MA多头排列(短期MA > 中期MA > 长期MA)
        boolean isMaBullish = ma.getEma5().compareTo(ma.getEma10()) > 0 && 
                             ma.getEma10().compareTo(ma.getEma20()) > 0;
        // MACD趋势(DIFF在DEA之上)
        boolean isMacdBullish = macd.getDif().compareTo(macd.getDea()) > 0;
        
        // 如果主信号不满足,直接返回false
        if (!(isMaBullish && isMacdBullish)) {
            return false;
        }
        
        // 辅信号:入场点判断
        // 价格在BOLL中轨上方,且未触及上轨(避免追高)
        boolean isPriceInSafeZone = currentPrice.compareTo(boll.getMid()) > 0 && 
                                   currentPrice.compareTo(boll.getUpper()) < 0;
        // 价格靠近BOLL中轨
        boolean isPriceNearBollMid = currentPrice.compareTo(boll.getMid().multiply(new BigDecimal(0.98))) > 0 &&
                                    currentPrice.compareTo(boll.getMid().multiply(new BigDecimal(1.02))) < 0;
        
        // RSI:健康区间30-70,刚从50中线向上
        boolean isRsiHealthy = rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && 
                              rsi.getRsi().compareTo(new BigDecimal(70)) < 0;
        boolean isRsiAboveMid = rsi.getRsi().compareTo(new BigDecimal(50)) > 0;
        
        // KDJ:金叉或超卖区域
        boolean isKdjGoldenCross = kdj.isGoldenCross();
        boolean isKdjOversold = kdj.getJ().compareTo(new BigDecimal(15)) < 0;
        
        // 入场点条件:价格在安全区域或靠近中轨,且动量健康
        boolean isEntryPointValid = (isPriceInSafeZone || isPriceNearBollMid) && 
                                   (isRsiHealthy && isRsiAboveMid) && 
                                   (isKdjGoldenCross || isKdjOversold);
        
        // 成交量验证
        boolean isVolumeConfirmed = volumeConfirm(volume);
        // 量价背离检测
        boolean isPriceVolumeDivergence = hasPriceVolumeDivergence(prices, volume);
        // 多周期确认
        boolean isMultiTimeframeConfirmed = multiTimeframeConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
 
        return isEntryPointValid && isVolumeConfirmed && !isPriceVolumeDivergence && isMultiTimeframeConfirmed;
    }
 
    /**
     * 根据优化建议检查是否应该开空仓位
     * 使用主次结合法:
     * - 主信号(趋势):MA空头排列 + MACD死叉
     * - 辅信号(入场点):价格反弹至BOLL中轨附近遇阻,且出现KDJ死叉或RSI从高位回落至50以下
     * @param currentPrice 当前价格
     * @param prices 价格数据
     * @param volume 成交量列表
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否应该开空
     */
    private boolean shouldOpenShort(BigDecimal currentPrice, List<BigDecimal> prices, List<BigDecimal> volume,
                                   List<BigDecimal> fiveMinPrices,
                                   List<BigDecimal> oneHourPrices,
                                   List<BigDecimal> fourHourPrices) {
        // 主信号:趋势判断
        // MA空头排列(短期MA < 中期MA < 长期MA)
        boolean isMaBearish = ma.getEma5().compareTo(ma.getEma10()) < 0 && 
                             ma.getEma10().compareTo(ma.getEma20()) < 0;
        // MACD趋势(DIFF在DEA之下)
        boolean isMacdBearish = macd.getDif().compareTo(macd.getDea()) < 0;
        
        // 如果主信号不满足,直接返回false
        if (!(isMaBearish && isMacdBearish)) {
            return false;
        }
        
        // 辅信号:入场点判断
        // 价格在BOLL中轨下方,且未触及下轨(避免追空)
        boolean isPriceInSafeZone = currentPrice.compareTo(boll.getMid()) < 0 && 
                                   currentPrice.compareTo(boll.getLower()) > 0;
        // 价格靠近BOLL中轨
        boolean isPriceNearBollMid = currentPrice.compareTo(boll.getMid().multiply(new BigDecimal(0.98))) > 0 &&
                                    currentPrice.compareTo(boll.getMid().multiply(new BigDecimal(1.02))) < 0;
        
        // RSI:健康区间30-70,刚从50中线向下
        boolean isRsiHealthy = rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && 
                              rsi.getRsi().compareTo(new BigDecimal(70)) < 0;
        boolean isRsiBelowMid = rsi.getRsi().compareTo(new BigDecimal(50)) < 0;
        
        // KDJ:死叉或超买区域
        boolean isKdjDeathCross = kdj.isDeathCross();
        boolean isKdjOverbought = kdj.getJ().compareTo(new BigDecimal(85)) > 0;
        
        // 入场点条件:价格在安全区域或靠近中轨,且动量健康
        boolean isEntryPointValid = (isPriceInSafeZone || isPriceNearBollMid) && 
                                   (isRsiHealthy && isRsiBelowMid) && 
                                   (isKdjDeathCross || isKdjOverbought);
        
        // 成交量验证
        boolean isVolumeConfirmed = volumeConfirm(volume);
        // 量价背离检测
        boolean isPriceVolumeDivergence = hasPriceVolumeDivergence(prices, volume);
        // 多周期确认(看跌)
        boolean isMultiTimeframeConfirmed = multiTimeframeBearishConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
 
        return isEntryPointValid && isVolumeConfirmed && !isPriceVolumeDivergence && isMultiTimeframeConfirmed;
    }
 
    /**
     * 根据优化建议检查是否应该平多仓位
     * 采用分层止盈止损策略:
     * - 保护止损:价格跌破BOLL中轨
     * - 跟踪止损:价格有效跌破移动平均线
     * - 最终平仓:趋势反转信号(MA空头排列 + MACD死叉)
     * @param currentPrice 当前价格
     * @param volume 成交量列表
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否应该平多
     */
    private boolean shouldCloseLong(BigDecimal currentPrice, List<BigDecimal> volume,
                                   List<BigDecimal> fiveMinPrices,
                                   List<BigDecimal> oneHourPrices,
                                   List<BigDecimal> fourHourPrices) {
        // 保护止损:价格跌破BOLL中轨(关键支撑位)
        boolean isStopLossTriggered = currentPrice.compareTo(boll.getMid()) < 0;
        
        // 跟踪止损:价格有效跌破短期均线(5EMA)
        boolean isTrailingStopTriggered = currentPrice.compareTo(ma.getEma5()) < 0;
        
        // 趋势反转信号:MA空头排列 + MACD死叉
        boolean isMaBearish = ma.getEma5().compareTo(ma.getEma10()) < 0 && 
                             ma.getEma10().compareTo(ma.getEma20()) < 0;
        boolean isMacdBearish = macd.getDif().compareTo(macd.getDea()) < 0;
        boolean isTrendReversed = isMaBearish && isMacdBearish;
        
        // 多周期确认(看跌)
        boolean isMultiTimeframeConfirmed = multiTimeframeBearishConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
        
        // 平多条件:保护止损触发 或 跟踪止损触发 或 (趋势反转且多周期确认)
        return isStopLossTriggered || isTrailingStopTriggered || (isTrendReversed && isMultiTimeframeConfirmed);
    }
 
    /**
     * 根据优化建议检查是否应该平空仓位
     * 采用分层止盈止损策略:
     * - 保护止损:价格突破BOLL中轨
     * - 跟踪止损:价格有效突破移动平均线
     * - 最终平仓:趋势反转信号(MA多头排列 + MACD金叉)
     * @param currentPrice 当前价格
     * @param volume 成交量列表
     * @param fiveMinPrices 5分钟价格数据
     * @param oneHourPrices 1小时价格数据
     * @param fourHourPrices 4小时价格数据
     * @return 是否应该平空
     */
    private boolean shouldCloseShort(BigDecimal currentPrice, List<BigDecimal> volume,
                                    List<BigDecimal> fiveMinPrices,
                                    List<BigDecimal> oneHourPrices,
                                    List<BigDecimal> fourHourPrices) {
        // 保护止损:价格突破BOLL中轨(关键阻力位)
        boolean isStopLossTriggered = currentPrice.compareTo(boll.getMid()) > 0;
        
        // 跟踪止损:价格有效突破短期均线(5EMA)
        boolean isTrailingStopTriggered = currentPrice.compareTo(ma.getEma5()) > 0;
        
        // 趋势反转信号:MA多头排列 + MACD金叉
        boolean isMaBullish = ma.getEma5().compareTo(ma.getEma10()) > 0 && 
                             ma.getEma10().compareTo(ma.getEma20()) > 0;
        boolean isMacdBullish = macd.getDif().compareTo(macd.getDea()) > 0;
        boolean isTrendReversed = isMaBullish && isMacdBullish;
        
        // 多周期确认(看涨)
        boolean isMultiTimeframeConfirmed = multiTimeframeConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
        
        // 平空条件:保护止损触发 或 跟踪止损触发 或 (趋势反转且多周期确认)
        return isStopLossTriggered || isTrailingStopTriggered || (isTrendReversed && isMultiTimeframeConfirmed);
    }
 
    /**
     * 获取所有指标的当前状态
     * @return 指标状态字符串
     */
    public String getIndicatorStatus() {
        return String.format("MA5: %s, MA20: %s, ", ma.getEma5(), ma.getEma20()) +
               String.format("MACD-DIF: %s, MACD-DEA: %s, MACD-BAR: %s, ", macd.getDif(), macd.getDea(), macd.getMacdBar()) +
               String.format("KDJ-K: %s, KDJ-D: %s, KDJ-J: %s, ", kdj.getK(), kdj.getD(), kdj.getJ()) +
               String.format("RSI: %s, ", rsi.getRsi()) +
               String.format("BOLL-MID: %s, BOLL-UP: %s, BOLL-DN: %s, ", boll.getMid(), boll.getUpper(), boll.getLower()) +
               String.format("AdvancedMA-Bullish: %s, Bearish: %s, Percent: %s",
               advancedMA.isBullish(), advancedMA.isBearish(), advancedMA.calculatePercent());
    }
    
    /**
     * 生成区间交易信号
     * 在震荡行情下,使用BOLL通道作为区间边界,结合KDJ指标生成交易信号
     * @param currentPrice 当前价格
     * @param volume 成交量列表
     * @param hasLongPosition 是否当前持有做多仓位
     * @param hasShortPosition 是否当前持有做空仓位
     * @return 交易信号
     */
    private SignalType generateRangeTradingSignal(BigDecimal currentPrice, List<BigDecimal> volume, 
                                                 boolean hasLongPosition, boolean hasShortPosition) {
        // 区间交易策略逻辑:
        // 1. 价格触及BOLL下轨且KDJ超卖 → 买入信号
        // 2. 价格触及BOLL上轨且KDJ超买 → 卖出信号
        // 3. 价格回归BOLL中轨 → 平仓信号
        
        // 检查KDJ极端超买超卖情况
        boolean isKdjJExtremeOverbought = kdj.getJ().compareTo(new BigDecimal("100")) > 0;
        boolean isKdjJExtremeOversold = kdj.getJ().compareTo(new BigDecimal("10")) < 0;
        
        // 价格触及BOLL下轨(基础条件)
        boolean isPriceNearBollLower = currentPrice.compareTo(boll.getLower()) >= 0 && 
                                      currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.01"))) <= 0;
        
        // 价格触及BOLL上轨(基础条件)
        boolean isPriceNearBollUpper = currentPrice.compareTo(boll.getUpper()) <= 0 && 
                                      currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.99"))) >= 0;
        
        // 当KDJ-J极度超买/超卖时,放宽BOLL边界要求
        if (isKdjJExtremeOverbought) {
            isPriceNearBollUpper = currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.985"))) >= 0;
        }
        if (isKdjJExtremeOversold) {
            isPriceNearBollLower = currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.015"))) <= 0;
        }
        
        // 价格回归BOLL中轨附近
        boolean isPriceNearBollMid = currentPrice.compareTo(boll.getMid().multiply(new BigDecimal("0.998"))) >= 0 && 
                                    currentPrice.compareTo(boll.getMid().multiply(new BigDecimal("1.002"))) <= 0;
        
        // KDJ超卖(使用调整后的阈值)
        boolean isKdjOversold = kdj.getJ().compareTo(new BigDecimal(15)) < 0;
        
        // KDJ超买(使用调整后的阈值)
        boolean isKdjOverbought = kdj.getJ().compareTo(new BigDecimal(85)) > 0;
        
        // RSI超卖(<30)
        boolean isRsiOversold = rsi.getRsi().compareTo(new BigDecimal(30)) < 0;
        
        // RSI超买(>70)
        boolean isRsiOverbought = rsi.getRsi().compareTo(new BigDecimal(70)) > 0;
        
        // 成交量验证(当前成交量大于20周期均值的1.1倍)
        boolean isVolumeValid = volumeConfirm(volume) && 
                               volume.get(volume.size() - 1).compareTo(calculateMA(volume, config.getVolumeMaPeriod()).multiply(new BigDecimal("1.1"))) > 0;
        
        // 开多逻辑:价格触及BOLL下轨且KDJ超卖且RSI超卖且有成交量支持
        if (isPriceNearBollLower && isKdjOversold && isRsiOversold && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL下轨({}), KDJ-J值({})超卖,RSI({})超卖,生成买入信号", boll.getLower(), kdj.getJ(), rsi.getRsi());
            return SignalType.BUY;
        }
        
        // 开空逻辑:价格触及BOLL上轨且KDJ超买且RSI超买且有成交量支持
        if (isPriceNearBollUpper && isKdjOverbought && isRsiOverbought && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL上轨({}), KDJ-J值({})超买,RSI({})超买,生成卖出信号", boll.getUpper(), kdj.getJ(), rsi.getRsi());
            return SignalType.SELL;
        }
        
        // 平多逻辑:价格回归BOLL中轨
        if (isPriceNearBollMid && hasLongPosition) {
            log.info("区间交易:价格回归BOLL中轨({}),生成平多信号", boll.getMid());
            return SignalType.CLOSE_BUY;
        }
        
        // 平空逻辑:价格回归BOLL中轨
        if (isPriceNearBollMid && hasShortPosition) {
            log.info("区间交易:价格回归BOLL中轨({}),生成平空信号", boll.getMid());
            return SignalType.CLOSE_SELL;
        }
        
        return SignalType.NONE;
    }
    
    /**
     * 计算动态杠杆倍数
     * 杠杆倍数 = 基础杠杆 * (波动率阈值/当前波动率)
     * @param high 最高价列表
     * @param low 最低价列表
     * @param close 收盘价列表
     * @return 动态杠杆倍数
     */
    public BigDecimal calculateDynamicLeverage(List<BigDecimal> high, List<BigDecimal> low, List<BigDecimal> close) {
        if (!config.isEnableDynamicLeverage()) {
            return config.getBaseLeverage();
        }
        
        // 计算当前ATR和波动率
        BigDecimal currentAtr = calculateATR(high, low, close, config.getAtrPeriod());
        BigDecimal currentVolatility = normalizeVolatility(close, currentAtr);
        
        // 计算30日ATR移动中位数作为波动率阈值
        BigDecimal volatilityThreshold = calculateVolatilityThreshold(high, low, close);
        
        // 动态计算杠杆倍数
        BigDecimal leverage = config.getBaseLeverage().multiply(volatilityThreshold).divide(currentVolatility, 2, BigDecimal.ROUND_HALF_UP);
        
        // 限制杠杆范围在1x-10x之间
        leverage = leverage.min(new BigDecimal(10)).max(BigDecimal.ONE);
        
        log.info("动态杠杆计算 - 基础杠杆: {}, 波动率阈值: {}, 当前波动率: {}, 计算杠杆: {}",
                config.getBaseLeverage(), volatilityThreshold, currentVolatility, leverage);
        
        return leverage;
    }
    
    /**
     * 计算波动率阈值(30日ATR移动中位数)
     * @param high 最高价列表
     * @param low 最低价列表
     * @param close 收盘价列表
     * @return 波动率阈值
     */
    private BigDecimal calculateVolatilityThreshold(List<BigDecimal> high, List<BigDecimal> low, List<BigDecimal> close) {
        if (high == null || low == null || close == null || close.size() < config.getVolatilityThresholdPeriod()) {
            return new BigDecimal(5); // 默认阈值
        }
        
        List<BigDecimal> volatilityList = new ArrayList<>();
        for (int i = close.size() - config.getVolatilityThresholdPeriod(); i < close.size(); i++) {
            List<BigDecimal> recentHigh = high.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
            List<BigDecimal> recentLow = low.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
            List<BigDecimal> recentClose = close.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
            
            BigDecimal atr = calculateATR(recentHigh, recentLow, recentClose, config.getAtrPeriod());
            BigDecimal volatility = normalizeVolatility(recentClose, atr);
            volatilityList.add(volatility);
        }
        
        // 计算中位数
        volatilityList.sort(BigDecimal::compareTo);
        int midIndex = volatilityList.size() / 2;
        return volatilityList.get(midIndex);
    }
    
    /**
     * 三段式止盈策略
     * 第一目标:BOLL上轨(30%仓位)
     * 第二目标:斐波那契161.8%(50%仓位)
     * 第三目标:趋势线破位(20%仓位)
     * @param entryPrice 入场价格
     * @param currentPrice 当前价格
     * @param direction 交易方向
     * @param positionSize 当前仓位大小
     * @return 止盈信号和应该平仓的仓位比例
     */
    public ProfitTakingResult calculateThreeStepProfitTaking(BigDecimal entryPrice, BigDecimal currentPrice, 
                                                            Direction direction, BigDecimal positionSize) {
        if (!config.isEnableThreeStepProfitTaking()) {
            return new ProfitTakingResult(SignalType.NONE, BigDecimal.ZERO);
        }
        
        // 计算三个止盈目标
        BigDecimal firstTarget = calculateFirstProfitTarget(entryPrice, currentPrice, direction);
        BigDecimal secondTarget = calculateSecondProfitTarget(entryPrice, direction);
        BigDecimal thirdTarget = calculateThirdProfitTarget(currentPrice, direction);
        
        // 判断当前价格是否达到目标
        if (direction == Direction.LONG) {
            if (currentPrice.compareTo(thirdTarget) >= 0) {
                // 达到第三目标,平全部仓位
                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize);
            } else if (currentPrice.compareTo(secondTarget) >= 0) {
                // 达到第二目标,平50%仓位
                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize.multiply(new BigDecimal("0.5")));
            } else if (currentPrice.compareTo(firstTarget) >= 0) {
                // 达到第一目标,平30%仓位
                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize.multiply(new BigDecimal("0.3")));
            }
        } else if (direction == Direction.SHORT) {
            if (currentPrice.compareTo(thirdTarget) <= 0) {
                // 达到第三目标,平全部仓位
                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize);
            } else if (currentPrice.compareTo(secondTarget) <= 0) {
                // 达到第二目标,平50%仓位
                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize.multiply(new BigDecimal("0.5")));
            } else if (currentPrice.compareTo(firstTarget) <= 0) {
                // 达到第一目标,平30%仓位
                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize.multiply(new BigDecimal("0.3")));
            }
        }
        
        return new ProfitTakingResult(SignalType.NONE, BigDecimal.ZERO);
    }
    
    /**
     * 计算第一止盈目标:BOLL上轨
     */
    private BigDecimal calculateFirstProfitTarget(BigDecimal entryPrice, BigDecimal currentPrice, Direction direction) {
        return direction == Direction.LONG ? boll.getUpper() : boll.getLower();
    }
    
    /**
     * 计算第二止盈目标:斐波那契161.8%
     */
    private BigDecimal calculateSecondProfitTarget(BigDecimal entryPrice, Direction direction) {
        BigDecimal fibonacciRatio = new BigDecimal("1.618");
        if (direction == Direction.LONG) {
            return entryPrice.multiply(BigDecimal.ONE.add(fibonacciRatio.divide(new BigDecimal(100))));
        } else {
            return entryPrice.multiply(BigDecimal.ONE.subtract(fibonacciRatio.divide(new BigDecimal(100))));
        }
    }
    
    /**
     * 计算第三止盈目标:简单趋势线破位(这里简化为MA5下穿MA20)
     */
    private BigDecimal calculateThirdProfitTarget(BigDecimal currentPrice, Direction direction) {
        // 这里使用简化的趋势线破位判断
        // 实际应用中可以使用更复杂的趋势线计算
        return direction == Direction.LONG ? ma.getEma20() : ma.getEma20();
    }
    
 
 
    /**
     * 黑天鹅事件过滤
     * 规避重大事件前后30分钟、链上大额转账、异常资金费率
     * @param fundingRate 当前资金费率
     * @param hasLargeTransfer 是否有大额转账
     * @param hasUpcomingEvent 是否有即将到来的重大事件
     * @return 是否应该规避交易
     */
    public boolean blackSwanFilter(BigDecimal fundingRate, boolean hasLargeTransfer, boolean hasUpcomingEvent) {
        if (!config.isEnableBlackSwanFilter()) {
            return false;
        }
        
        // 资金费率绝对值大于0.2%
        boolean isAbnormalFundingRate = fundingRate != null && 
                fundingRate.abs().compareTo(new BigDecimal("0.002")) > 0;
        
        // 大额转账监控(这里简化为外部传入)
        // 重大事件监控(这里简化为外部传入)
        
        boolean shouldAvoid = isAbnormalFundingRate || hasLargeTransfer || hasUpcomingEvent;
        
        if (shouldAvoid) {
            log.info("黑天鹅事件过滤触发 - 资金费率异常: {}, 大额转账: {}, 即将发生重大事件: {}",
                    isAbnormalFundingRate, hasLargeTransfer, hasUpcomingEvent);
        }
        
        return shouldAvoid;
    }
    
    /**
     * 止盈结果类
     */
    public static class ProfitTakingResult {
        private SignalType signal;
        private BigDecimal closePositionSize;
        
        public ProfitTakingResult(SignalType signal, BigDecimal closePositionSize) {
            this.signal = signal;
            this.closePositionSize = closePositionSize;
        }
        
        public SignalType getSignal() {
            return signal;
        }
        
        public BigDecimal getClosePositionSize() {
            return closePositionSize;
        }
    }
}