calculateValue method

dynamic calculateValue()

Implementation

calculateValue() {
  if (datas == null) return;
  if (datas!.isEmpty) return;

  // 如果用户配置了要显示DMI,则先计算DMI
  // if (secondaryStates.contains(SecondaryState.DMI)) {
  //   _computeDMI(datas!); // period可自定义
  // }
  // 如果用户勾选了DMI, 就内部计算DMI
  // if (secondaryStates.contains(SecondaryState.DMI)) {
  //   _computeDMIAdvanced(
  //     datas!,
  //     period: 14,
  //     useAdxr: true, // 要不要计算ADXR
  //     adxrPeriod: 14,
  //     smoothMethod: 'ema', // 这里演示"双重平滑"
  //   );
  // }

  maxScrollX = getMinTranslateX().abs();
  setTranslateXFromScrollX(scrollX);
  mStartIndex = indexOfTranslateX(xToTranslateX(0));
  mStopIndex = indexOfTranslateX(xToTranslateX(mWidth));
  for (int i = mStartIndex; i <= mStopIndex; i++) {
    var item = datas![i];
    getMainMaxMinValue(item, i);
    getVolMaxMinValue(item);
    // getSecondaryMaxMinValue(item);
    // 3)更新每个 SecondaryState 的最大最小值
    for (final st in secondaryStates) {
      double oldMax = mSecondaryMaxMap[st] ?? double.minPositive;
      double oldMin = mSecondaryMinMap[st] ?? double.maxFinite;
      double newMax = oldMax;
      double newMin = oldMin;
      if (st == SecondaryState.VOLATILITY) {
        double? val = item.volIndicator;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.ENVELOPES) {
        // 3条线: envMid, envUp, envDn
        if (item.envMid != null && item.envMid!.isFinite) {
          if (item.envMid! > newMax) newMax = item.envMid!;
          if (item.envMid! < newMin) newMin = item.envMid!;
        }
        if (item.envUp != null && item.envUp!.isFinite) {
          if (item.envUp! > newMax) newMax = item.envUp!;
          if (item.envUp! < newMin) newMin = item.envUp!;
        }
        if (item.envDn != null && item.envDn!.isFinite) {
          if (item.envDn! > newMax) newMax = item.envDn!;
          if (item.envDn! < newMin) newMin = item.envDn!;
        }
      } else if (st == SecondaryState.MFI) {
        double? mfiVal = item.mfi;
        if (mfiVal != null && mfiVal.isFinite) {
          if (mfiVal > newMax) newMax = mfiVal;
          if (mfiVal < newMin) newMin = mfiVal;
        }
      } else if (st == SecondaryState.MOMENTUM) {
        double? val = item.momentum;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.DEMARKER) {
        double? demVal = item.dem;
        if (demVal != null && demVal.isFinite) {
          if (demVal > newMax) newMax = demVal;
          if (demVal < newMin) newMin = demVal;
        }
      } else if (st == SecondaryState.WPR) {
        double? wVal = item.wpr;
        if (wVal != null && wVal.isFinite) {
          // 常见 wVal在 -100..0
          // 但为了兼容,还是正常比较
          if (wVal > newMax) newMax = wVal;
          if (wVal < newMin) newMin = wVal;
        }
      } else if (st == SecondaryState.STOCHASTIC) {
        // stochK, stochD
        double? kVal = item.stochK;
        double? dVal = item.stochD;
        if (kVal != null && kVal.isFinite) {
          if (kVal > newMax) newMax = kVal;
          if (kVal < newMin) newMin = kVal;
        }
        if (dVal != null && dVal.isFinite) {
          if (dVal > newMax) newMax = dVal;
          if (dVal < newMin) newMin = dVal;
        }
      } else if (st == SecondaryState.STDDEV) {
        double? val = item.stdDev;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.ADX) {
        double? adxVal = item.adx;
        if (adxVal != null && adxVal.isFinite) {
          if (adxVal > newMax) newMax = adxVal;
          if (adxVal < newMin) newMin = adxVal;
        }
      } else if (st == SecondaryState.VIX) {
        double? v = item.vix;
        if (v != null && v.isFinite) {
          if (v > newMax) newMax = v;
          if (v < newMin) newMin = v;
        }
      } else if (st == SecondaryState.ADL) {
        double? v = item.adl;
        if (v != null && v.isFinite) {
          if (v > newMax) newMax = v;
          if (v < newMin) newMin = v;
        }
      } else if (st == SecondaryState.OBV) {
        // 这里可纳入obvEma(更平滑) or obv(原始) 作为坐标
        double? val = item.obvEma; // 优先看平滑
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.VWAP) {
        double? v = item.vwap;
        if (v != null && v.isFinite) {
          if (v > newMax) newMax = v;
          if (v < newMin) newMin = v;
        }
      } else if (st == SecondaryState.HV) {
        double? hvVal = item.hv;
        if (hvVal != null && hvVal.isFinite) {
          if (hvVal > newMax) newMax = hvVal;
          if (hvVal < newMin) newMin = hvVal;
        }
      } else if (st == SecondaryState.ATR) {
        double? a = item.atr;
        if (a != null && a.isFinite) {
          if (a > newMax) newMax = a;
          if (a < newMin) newMin = a;
        }
      } else if (st == SecondaryState.SUPER_TREND) {
        final List<double?> vals = [
          item.superTrend,
          item.superTrendUpper,
          item.superTrendLower,
        ];
        for (final v in vals) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.STC) {
        final double? val = item.stc;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.QQE) {
        final List<double?> vals = [item.qqe, item.qqeSignal];
        for (final v in vals) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.WAVE_TREND) {
        final List<double?> vals = [item.waveTrend1, item.waveTrend2];
        for (final v in vals) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.CMO) {
        final double? val = item.cmo;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.EOM) {
        final double? val = item.eom;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.PVI_NVI) {
        final List<double?> vals = [item.pvi, item.nvi];
        for (final v in vals) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.VORTEX) {
        // item.viPlus, item.viMinus
        double? viplus = item.viPlus;
        double? viminus = item.viMinus;
        if (viplus != null && viplus.isFinite) {
          if (viplus > newMax) newMax = viplus;
          if (viplus < newMin) newMin = viplus;
        }
        if (viminus != null && viminus.isFinite) {
          if (viminus > newMax) newMax = viminus;
          if (viminus < newMin) newMin = viminus;
        }
      } else if (st == SecondaryState.AROON) {
        // item.aroonUp, item.aroonDown, item.aroonOsc
        double? up = item.aroonUp;
        double? down = item.aroonDown;
        double? osc = item.aroonOsc; // 若calcOsc=true

        // 依次更新
        if (up != null && up.isFinite) {
          if (up > newMax) newMax = up;
          if (up < newMin) newMin = up;
        }
        if (down != null && down.isFinite) {
          if (down > newMax) newMax = down;
          if (down < newMin) newMin = down;
        }
        if (osc != null && osc.isFinite) {
          if (osc > newMax) newMax = osc;
          if (osc < newMin) newMin = osc;
        }
      } else if (st == SecondaryState.SAR) {
        // 只存一条 psar
        final psarVal = item.psar;
        if (psarVal != null && psarVal.isFinite) {
          if (psarVal > newMax) newMax = psarVal;
          if (psarVal < newMin) newMin = psarVal;
        }
      } else if (st == SecondaryState.ICHIMOKU) {
        // 5条线: Tenkan, Kijun, SpanA, SpanB, Chikou
        final lines = [
          item.ichimokuTenkan,
          item.ichimokuKijun,
          item.ichimokuSpanA,
          item.ichimokuSpanB,
          item.ichimokuChikou,
        ];
        for (var val in lines) {
          if (val != null && val.isFinite) {
            if (val > newMax) newMax = val;
            if (val < newMin) newMin = val;
          }
        }
      } else if (st == SecondaryState.TSI) {
        // TSI + 信号线
        if (item.tsi != null && item.tsiSignal != null) {
          if (item.tsi!.isFinite) {
            newMax = newMax > item.tsi! ? newMax : item.tsi!;
            newMin = newMin < item.tsi! ? newMin : item.tsi!;
          }
          if (item.tsiSignal!.isFinite) {
            newMax = newMax > item.tsiSignal! ? newMax : item.tsiSignal!;
            newMin = newMin < item.tsiSignal! ? newMin : item.tsiSignal!;
          }
        }
      } else if (st == SecondaryState.PPO) {
        // 这里给PPO主线 + PPO信号线 做max/min
        if (item.ppo != null && item.ppoSignal != null) {
          double ppoVal = item.ppo!;
          double ppoSig = item.ppoSignal!;
          if (ppoVal.isFinite) {
            newMax = newMax > ppoVal ? newMax : ppoVal;
            newMin = newMin < ppoVal ? newMin : ppoVal;
          }
          if (ppoSig.isFinite) {
            newMax = newMax > ppoSig ? newMax : ppoSig;
            newMin = newMin < ppoSig ? newMin : ppoSig;
          }
        }
      } else if (st == SecondaryState.TRIX) {
        // 和MACD/KDJ类似,获取TRIX和其Signal线的值
        if (item.trix != null && item.trixSignal != null) {
          // 这里只示例主线/信号线各一个
          // 如果你自己还想多画别的线,可以都加进reduce
          newMax = [oldMax, item.trix!, item.trixSignal!]
              .reduce((a, b) => a > b ? a : b);

          newMin = [oldMin, item.trix!, item.trixSignal!]
              .reduce((a, b) => a < b ? a : b);
        }
      } else if (st == SecondaryState.DMI) {
        // pdi, mdi, adx, adxr
        if (item.pdi != null && item.mdi != null && item.adx != null) {
          // 这里假设你还需要adxr,可以一起写,否则省略
          newMax = [
            oldMax,
            item.pdi!,
            item.mdi!,
            item.adx!,
            if (item.adxr != null) item.adxr!
          ].reduce((a, b) => a > b ? a : b);

          newMin = [
            oldMin,
            item.pdi!,
            item.mdi!,
            item.adx!,
            if (item.adxr != null) item.adxr!
          ].reduce((a, b) => a < b ? a : b);
        }
      } else if (st == SecondaryState.MACD) {
        // item.macd, item.dif, item.dea
        if (item.macd != null && item.dif != null && item.dea != null) {
          newMax = [oldMax, item.macd!, item.dif!, item.dea!, item.osma!]
              .reduce((a, b) => a > b ? a : b);
          newMin = [oldMin, item.macd!, item.dif!, item.dea!, item.osma!]
              .reduce((a, b) => a < b ? a : b);
        }
        // double? val = item.osma;
        // if (val != null && val.isFinite) {
        //   if (val > newMax) newMax = val;
        //   if (val < newMin) newMin = val;
        // }
      } else if (st == SecondaryState.KDJ) {
        // item.k, item.d, item.j
        if (item.k != null && item.d != null && item.j != null) {
          newMax = [oldMax, item.k!, item.d!, item.j!]
              .reduce((a, b) => a > b ? a : b);
          newMin = [oldMin, item.k!, item.d!, item.j!]
              .reduce((a, b) => a < b ? a : b);
        }
      } else if (st == SecondaryState.RSI) {
        // item.rsi
        if (item.rsi != null) {
          newMax = newMax > item.rsi! ? newMax : item.rsi!;
          newMin = newMin < item.rsi! ? newMin : item.rsi!;
        }
      } else if (st == SecondaryState.WR) {
        // WR 通常范围 [-100, 0], 也可自行判定
        newMax = newMax > 0 ? newMax : 0;
        newMin = newMin < -100 ? newMin : -100;
      } else if (st == SecondaryState.CCI) {
        if (item.cci != null) {
          newMax = math.max(newMax, item.cci!);
          newMin = math.min(newMin, item.cci!);
        }
      } else if (st == SecondaryState.CMF) {
        final val = item.cmf;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.CHAIKIN_OSC) {
        final val = item.chaikinOscillator;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.KLINGER) {
        final values = [item.kvo, item.kvoSignal];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.VPT) {
        final val = item.vpt;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.FORCE) {
        final val = item.forceIndex;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.ROC) {
        final values = [item.roc, item.rocSignal];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.ULTIMATE) {
        final val = item.ultimateOsc;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.CONNORS_RSI) {
        final val = item.connorsRsi;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.STOCH_RSI) {
        final values = [item.stochRsiK, item.stochRsiD];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.RVI) {
        final values = [item.rvi, item.rviSignal];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.DPO) {
        final val = item.dpo;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.KAMA) {
        final val = item.kama;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.HMA) {
        final val = item.hma;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.KELTNER) {
        final values = [
          item.keltnerUpper,
          item.keltnerMiddle,
          item.keltnerLower,
        ];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.DONCHIAN) {
        final values = [
          item.donchianUpper,
          item.donchianMiddle,
          item.donchianLower,
        ];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.BOLL_BANDWIDTH) {
        final val = item.bollBandwidth;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.CHAIKIN_VOLATILITY) {
        final val = item.chaikinVolatility;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.HV_PERCENTILE) {
        final val = item.hvPercentile;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.ATR_PERCENTILE) {
        final val = item.atrPercentile;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.ELDER_RAY) {
        final values = [item.elderBull, item.elderBear];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.ICHIMOKU_SPAN) {
        final val = item.ichimokuSpanDiff;
        if (val != null && val.isFinite) {
          if (val > newMax) newMax = val;
          if (val < newMin) newMin = val;
        }
      } else if (st == SecondaryState.PIVOT) {
        final values = [
          item.pivot,
          item.pivotR1,
          item.pivotR2,
          item.pivotR3,
          item.pivotS1,
          item.pivotS2,
          item.pivotS3,
        ];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      } else if (st == SecondaryState.GANN_FAN) {
        final values = [item.gann1x1, item.gann1x2, item.gann2x1];
        for (final v in values) {
          if (v != null && v.isFinite) {
            if (v > newMax) newMax = v;
            if (v < newMin) newMin = v;
          }
        }
      }
      // 回写到 Map
      mSecondaryMaxMap[st] = newMax;
      mSecondaryMinMap[st] = newMin;

      // print('[getSecondaryMaxMinValue] Max: $newMax, Min: $newMin');
    }
  }
}