@Override
  protected String buildLine(
      int calculatorIndex,
      Map<EventKey, EventValue> edata,
      QuotationUnit qU,
      List<SortedMap<Date, double[]>> linearsExpects) {

    Date calculatorDate = qU.getDate();
    EventValue bearishEventValue =
        edata.get(new StandardEventKey(calculatorDate, getEventDefinition(), EventType.BEARISH));
    EventValue bullishEventValue =
        edata.get(new StandardEventKey(calculatorDate, getEventDefinition(), EventType.BULLISH));
    BigDecimal calculatorClose = qU.getClose();

    int chaikinIndex = getIndicatorIndexFromQuotationIndex(this.chaikinOscillator, calculatorIndex);

    String line =
        new SimpleDateFormat("yyyy-MM-dd").format(calculatorDate)
            + ","
            + calculatorClose
            + ","
            + this.chaikinOscillator.getChaikinOsc()[chaikinIndex];

    if (bearishEventValue != null) {
      line = line + "," + calculatorClose + ",0,";
    } else if (bullishEventValue != null) {
      line = line + ",0," + calculatorClose + ",";
    } else {
      line = line + ",0,0,";
    }

    line = addScoringLinesElement(line, calculatorDate, linearsExpects) + "\n";

    return line;
  }
 @Override
 protected String getLine(Integer indicator, QuotationUnit qU) {
   String line =
       new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss").format(qU.getDate())
           + ","
           + qU.getClose()
           + ","
           + slowK[indicator]
           + ","
           + slowD[indicator]
           + "\n";
   return line;
 }
  @Override
  protected FormulatRes eventFormulaCalculation(QuotationUnit qU, Integer quotationIdx)
      throws InvalidAlgorithmParameterException {

    FormulatRes res = new FormulatRes(getEventDefinition());
    res.setCurrentDate(qU.getDate());

    int chaikinIdx = getIndicatorIndexFromQuotationIndex(this.chaikinOscillator, quotationIdx);
    double[] chaikinLookBackP =
        Arrays.copyOfRange(
            this.chaikinOscillator.getChaikinOsc(), chaikinIdx - getDaysSpan(), chaikinIdx);
    double[] quotationLookBackP =
        Arrays.copyOfRange(
            quotationsCopy.getCloseValues(), quotationIdx - getDaysSpan(), quotationIdx);

    int smaIndex = getIndicatorIndexFromQuotationIndex(this.sma, quotationIdx);
    double[] quotationLookBackPThresh =
        Arrays.copyOfRange(this.sma.getSma(), smaIndex - getDaysSpan(), smaIndex);

    double[] chaikinThreshCurve = new double[chaikinLookBackP.length];

    {
      Boolean isPriceDown = lowerLow(quotationLookBackP, quotationLookBackPThresh);
      Boolean isChaikinUp = higherLow(chaikinLookBackP, chaikinThreshCurve);
      res.setBullishCrossOver(isPriceDown && isChaikinUp);

      if (res.getBullishCrossOver()) return res;
    }
    {
      Boolean isPriceUp = higherHigh(quotationLookBackP, quotationLookBackPThresh);
      Boolean isChaikinDown = lowerHigh(chaikinLookBackP, chaikinThreshCurve);
      res.setBearishCrossBellow(isPriceUp && isChaikinDown);

      return res;
    }
  }