/* Auto-generated JSON-RPC server for ta_codegen Java output.
 * Build: javac TaCodegenServe.java && java TaCodegenServe
 */
import java.io.*;
import java.util.*;

enum RetCode {
    Success, BadParam, OutOfRangeStartIndex, OutOfRangeEndIndex, AllocErr, InternalError;
    public int toInt() {
        switch(this) {
            case Success: return 0;
            case BadParam: return 2;
            case OutOfRangeStartIndex: return 12;
            case OutOfRangeEndIndex: return 13;
            case AllocErr: return 3;
            default: return 5000;
        }
    }
}

class MInteger { public int value; }

enum FuncUnstId {
    Adx, Adxr, Atr, Cmo, Dx, Ema,
    HtDcPeriod, HtDcPhase, HtPhasor, HtSine, HtTrendline, HtTrendMode,
    Imi, Kama, Mama, Mfi, MinusDI, MinusDM,
    Natr, PlusDI, PlusDM, Rsi, StochRsi, T3, None;
}

enum Compatibility {
    Default, Metastock;
}

enum MAType {
    Sma, Ema, Wma, Dema, Tema, Trima, Kama, Mama, T3;
}

enum RangeType {
    RealBody, HighLow, Shadows;
}

class CandleSetting {
    RangeType rangeType;
    int avgPeriod;
    double factor;
    CandleSetting(RangeType rt, int ap, double f) { rangeType = rt; avgPeriod = ap; factor = f; }
}

enum CandleSettingType {
    BodyLong, BodyVeryLong, BodyShort, BodyDoji,
    ShadowLong, ShadowVeryLong, ShadowShort, ShadowVeryShort,
    Near, Far, Equal, AllCandleSettings;
}

class Core {
    int[] unstablePeriod = new int[FuncUnstId.values().length];
    Compatibility compatibility = Compatibility.Default;
    CandleSetting[] candleSettings = {
        new CandleSetting(RangeType.RealBody, 10, 1.0),   // BodyLong
        new CandleSetting(RangeType.RealBody, 10, 3.0),   // BodyVeryLong
        new CandleSetting(RangeType.RealBody, 10, 1.0),   // BodyShort
        new CandleSetting(RangeType.HighLow,  10, 0.1),   // BodyDoji
        new CandleSetting(RangeType.RealBody, 0,  1.0),   // ShadowLong
        new CandleSetting(RangeType.RealBody, 0,  2.0),   // ShadowVeryLong
        new CandleSetting(RangeType.Shadows,  10, 1.0),   // ShadowShort
        new CandleSetting(RangeType.HighLow,  10, 0.1),   // ShadowVeryShort
        new CandleSetting(RangeType.HighLow,  5,  0.2),   // Near
        new CandleSetting(RangeType.HighLow,  5,  0.6),   // Far
        new CandleSetting(RangeType.HighLow,  5,  0.05),  // Equal
    };

    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  RM       Robert Meier
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  120307 RM     Initial Version
     *  120907 MF     Handling of a few limit cases
     */

       public int accbandsLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 20;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return smaLookback(optInTimePeriod) ;

       }
       public RetCode accbands( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                double inClose[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outRealUpperBand[],
                                double outRealMiddleBand[],
                                double outRealLowerBand[] )
       {
          RetCode retCode;
          double[] tempBuffer1;
          double[] tempBuffer2;
          MInteger outBegIdxDummy = new MInteger();
          MInteger outNbElementDummy = new MInteger();
          int i = 0;
          int j = 0;
          int outputSize = 0;
          int bufferSize = 0;
          int lookbackTotal = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 20;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = smaLookback(optInTimePeriod);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Buffer will contains also the lookback required for SMA
           * to satisfy the caller requested startIdx/endIdx.
           */
          outputSize = endIdx - startIdx + 1;
          bufferSize = outputSize + lookbackTotal;
          tempBuffer1 = new double[(int)(bufferSize * 1)];
          tempBuffer2 = new double[(int)(bufferSize * 1)];
          /* Calculate the upper/lower band at the same time (no SMA yet).
           * Must start calculation back enough to cover the lookback
           * required later for the SMA.
           */
          for( j = 0, i = startIdx - lookbackTotal; i <= endIdx; i += 1, j += 1 ) {
             tempReal = inHigh[i] + inLow[i];
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                tempReal = 4 * (inHigh[i] - inLow[i]) / tempReal;
                tempBuffer1[j] = inHigh[i] * (1 + tempReal);
                tempBuffer2[j] = inLow[i] * (1 - tempReal);
             } else {
                tempBuffer1[j] = inHigh[i];
                tempBuffer2[j] = inLow[i];
             }
          }
          /* Calculate the middle band, which is a moving average of the close. */
          retCode = smaUnguarded(startIdx, endIdx, inClose, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealMiddleBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Now let's take the SMA for the upper band. */
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer1, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealUpperBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Now let's take the SMA for the lower band. */
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer2, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealLowerBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode accbandsUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outRealUpperBand[],
                                         double outRealMiddleBand[],
                                         double outRealLowerBand[] )
       {
          RetCode retCode;
          double[] tempBuffer1;
          double[] tempBuffer2;
          MInteger outBegIdxDummy = new MInteger();
          MInteger outNbElementDummy = new MInteger();
          int i = 0;
          int j = 0;
          int outputSize = 0;
          int bufferSize = 0;
          int lookbackTotal = 0;
          double tempReal = 0;
          lookbackTotal = smaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - startIdx + 1;
          bufferSize = outputSize + lookbackTotal;
          tempBuffer1 = new double[(int)(bufferSize * 1)];
          tempBuffer2 = new double[(int)(bufferSize * 1)];
          for( j = 0, i = startIdx - lookbackTotal; i <= endIdx; i += 1, j += 1 ) {
             tempReal = inHigh[i] + inLow[i];
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                tempReal = 4 * (inHigh[i] - inLow[i]) / tempReal;
                tempBuffer1[j] = inHigh[i] * (1 + tempReal);
                tempBuffer2[j] = inLow[i] * (1 - tempReal);
             } else {
                tempBuffer1[j] = inHigh[i];
                tempBuffer2[j] = inLow[i];
             }
          }
          retCode = smaUnguarded(startIdx, endIdx, inClose, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealMiddleBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer1, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealUpperBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer2, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealLowerBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode accbands( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                float inClose[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outRealUpperBand[],
                                double outRealMiddleBand[],
                                double outRealLowerBand[] )
       {
          RetCode retCode;
          double[] tempBuffer1;
          double[] tempBuffer2;
          MInteger outBegIdxDummy = new MInteger();
          MInteger outNbElementDummy = new MInteger();
          int i = 0;
          int j = 0;
          int outputSize = 0;
          int bufferSize = 0;
          int lookbackTotal = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 20;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = smaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - startIdx + 1;
          bufferSize = outputSize + lookbackTotal;
          tempBuffer1 = new double[(int)(bufferSize * 1)];
          tempBuffer2 = new double[(int)(bufferSize * 1)];
          for( j = 0, i = startIdx - lookbackTotal; i <= endIdx; i += 1, j += 1 ) {
             tempReal = inHigh[i] + inLow[i];
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                tempReal = 4 * (inHigh[i] - inLow[i]) / tempReal;
                tempBuffer1[j] = inHigh[i] * (1 + tempReal);
                tempBuffer2[j] = inLow[i] * (1 - tempReal);
             } else {
                tempBuffer1[j] = inHigh[i];
                tempBuffer2[j] = inLow[i];
             }
          }
          retCode = smaUnguarded(startIdx, endIdx, inClose, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealMiddleBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer1, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealUpperBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer2, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealLowerBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode accbandsUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outRealUpperBand[],
                                         double outRealMiddleBand[],
                                         double outRealLowerBand[] )
       {
          RetCode retCode;
          double[] tempBuffer1;
          double[] tempBuffer2;
          MInteger outBegIdxDummy = new MInteger();
          MInteger outNbElementDummy = new MInteger();
          int i = 0;
          int j = 0;
          int outputSize = 0;
          int bufferSize = 0;
          int lookbackTotal = 0;
          double tempReal = 0;
          lookbackTotal = smaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - startIdx + 1;
          bufferSize = outputSize + lookbackTotal;
          tempBuffer1 = new double[(int)(bufferSize * 1)];
          tempBuffer2 = new double[(int)(bufferSize * 1)];
          for( j = 0, i = startIdx - lookbackTotal; i <= endIdx; i += 1, j += 1 ) {
             tempReal = inHigh[i] + inLow[i];
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                tempReal = 4 * (inHigh[i] - inLow[i]) / tempReal;
                tempBuffer1[j] = inHigh[i] * (1 + tempReal);
                tempBuffer2[j] = inLow[i] * (1 - tempReal);
             } else {
                tempBuffer1[j] = inHigh[i];
                tempBuffer2[j] = inLow[i];
             }
          }
          retCode = smaUnguarded(startIdx, endIdx, inClose, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealMiddleBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer1, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealUpperBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = smaUnguarded(0, bufferSize - 1, tempBuffer2, optInTimePeriod, outBegIdxDummy, outNbElementDummy, outRealLowerBand);
          if( retCode != RetCode.Success || (int)outNbElementDummy.value != outputSize ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int acosLookback( )
       {
          return 0 ;

       }
       public RetCode acos( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.acos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode acosUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.acos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode acos( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.acos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode acosUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.acos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JD       jdoyle
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  120802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  111705 MF,JD  Fix#1359452 for handling properly start/end range.
     */

       public int adLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode ad( int startIdx,
                          int endIdx,
                          double inHigh[],
                          double inLow[],
                          double inClose[],
                          double inVolume[],
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int nbBar = 0;
          int currentBar = 0;
          int outIdx = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double ad = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Note: Results from this function might vary slightly
           *       from Metastock outputs. The reason being that
           *       Metastock use float instead of double and this
           *       cause a different floating-point precision to
           *       be used.
           *
           *       For most function, this is not an apparent difference
           *       but for function using large cummulative values (like
           *       this AD function), minor imprecision adds up and becomes
           *       significative.
           *
           *       For better precision, TA-Lib use double in all its
           *       its calculations.
           */
          /* Default return values */
          nbBar = endIdx - startIdx + 1;
          outNBElement.value = nbBar;
          outBegIdx.value = startIdx;
          currentBar = startIdx;
          outIdx = 0;
          ad = 0.0;
          while( nbBar != 0 ) {
             high = inHigh[currentBar];
             low = inLow[currentBar];
             tmp = high - low;
             close = inClose[currentBar];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[currentBar];
             }
             outReal[outIdx++] = ad;
             currentBar += 1;
             nbBar -= 1;
          }
          return RetCode.Success ;
       }
       public RetCode adUnguarded( int startIdx,
                                   int endIdx,
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   double inVolume[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int nbBar = 0;
          int currentBar = 0;
          int outIdx = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double ad = 0;
          nbBar = endIdx - startIdx + 1;
          outNBElement.value = nbBar;
          outBegIdx.value = startIdx;
          currentBar = startIdx;
          outIdx = 0;
          ad = 0.0;
          while( nbBar != 0 ) {
             high = inHigh[currentBar];
             low = inLow[currentBar];
             tmp = high - low;
             close = inClose[currentBar];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[currentBar];
             }
             outReal[outIdx++] = ad;
             currentBar += 1;
             nbBar -= 1;
          }
          return RetCode.Success ;
       }
       public RetCode ad( int startIdx,
                          int endIdx,
                          float inHigh[],
                          float inLow[],
                          float inClose[],
                          float inVolume[],
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int nbBar = 0;
          int currentBar = 0;
          int outIdx = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double ad = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          nbBar = endIdx - startIdx + 1;
          outNBElement.value = nbBar;
          outBegIdx.value = startIdx;
          currentBar = startIdx;
          outIdx = 0;
          ad = 0.0;
          while( nbBar != 0 ) {
             high = inHigh[currentBar];
             low = inLow[currentBar];
             tmp = high - low;
             close = inClose[currentBar];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[currentBar];
             }
             outReal[outIdx++] = ad;
             currentBar += 1;
             nbBar -= 1;
          }
          return RetCode.Success ;
       }
       public RetCode adUnguarded( int startIdx,
                                   int endIdx,
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   float inVolume[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int nbBar = 0;
          int currentBar = 0;
          int outIdx = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double ad = 0;
          nbBar = endIdx - startIdx + 1;
          outNBElement.value = nbBar;
          outBegIdx.value = startIdx;
          currentBar = startIdx;
          outIdx = 0;
          ad = 0.0;
          while( nbBar != 0 ) {
             high = inHigh[currentBar];
             low = inLow[currentBar];
             tmp = high - low;
             close = inClose[currentBar];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[currentBar];
             }
             outReal[outIdx++] = ad;
             currentBar += 1;
             nbBar -= 1;
          }
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int addLookback( )
       {
          return 0 ;

       }
       public RetCode add( int startIdx,
                           int endIdx,
                           double inReal0[],
                           double inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] + inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode addUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal0[],
                                    double inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] + inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode add( int startIdx,
                           int endIdx,
                           float inReal0[],
                           float inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] + inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode addUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal0[],
                                    float inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] + inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int adOscLookback( int optInFastPeriod, int optInSlowPeriod )
       {
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 3;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return -1;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 10;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return -1;
          }
          int slowestPeriod;
          /* Use the slowest EMA period to evaluate the total lookback. */
          if( optInFastPeriod < optInSlowPeriod ) {
             slowestPeriod = optInSlowPeriod;
          } else {
             slowestPeriod = optInFastPeriod;
          }
          /* Adjust startIdx to account for the lookback period. */
          return emaLookback(slowestPeriod) ;

       }
       public RetCode adOsc( int startIdx,
                             int endIdx,
                             double inHigh[],
                             double inLow[],
                             double inClose[],
                             double inVolume[],
                             int optInFastPeriod,
                             int optInSlowPeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int slowestPeriod = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double slowEMA = 0;
          double slowk = 0;
          double one_minus_slowk = 0;
          double fastEMA = 0;
          double fastk = 0;
          double one_minus_fastk = 0;
          double ad = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 3;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 10;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Implementation Note:
           *     The fastEMA varaible is not neceseraly the
           *     fastest EMA.
           *     In the same way, slowEMA is not neceseraly the
           *     slowest EMA.
           *
           *     The ADOSC is always the (fastEMA - slowEMA) regardless
           *     of the period specified. In other word:
           *
           *     ADOSC(3,10) = EMA(3,AD) - EMA(10,AD)
           *
           *        while
           *
           *     ADOSC(10,3) = EMA(10,AD)- EMA(3,AD)
           *
           *     In the first case the EMA(3) is truly a faster EMA,
           *     while in the second case, the EMA(10) is still call
           *     fastEMA in the algorithm, even if it is in fact slower.
           *
           *     This gives more flexibility to the user if they want to
           *     experiment with unusual parameter settings.
           */
          /* Identify the slowest period.
           * This infomration is used soleley to bootstrap
           * the algorithm (skip the lookback period).
           */
          if( optInFastPeriod < optInSlowPeriod ) {
             slowestPeriod = optInSlowPeriod;
          } else {
             slowestPeriod = optInFastPeriod;
          }
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = emaLookback(slowestPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          /* The following variables are used to
           * calculate the "ad".
           */
          ad = 0.0;
          /* Constants for EMA */
          fastk = 2.0 / ((double)optInFastPeriod + 1.0);
          one_minus_fastk = 1.0 - fastk;
          slowk = 2.0 / ((double)optInSlowPeriod + 1.0);
          one_minus_slowk = 1.0 - slowk;
          /* Initialize the two EMA
           *
           * Use the same range of initialization inputs for
           * both EMA and simply seed with the first A/D value.
           *
           * Note: Metastock do the same.
           */
          high = inHigh[today];
          low = inLow[today];
          tmp = high - low;
          close = inClose[today];
          if( tmp > 0.0 ) {
             ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
          }
          today += 1;
          fastEMA = ad;
          slowEMA = ad;
          /* Initialize the EMA and skip the unstable period. */
          while( today < startIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
          }
          /* Perform the calculation for the requested range */
          outIdx = 0;
          while( today <= endIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
             outReal[outIdx++] = fastEMA - slowEMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adOscUnguarded( int startIdx,
                                      int endIdx,
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      double inVolume[],
                                      int optInFastPeriod,
                                      int optInSlowPeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int slowestPeriod = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double slowEMA = 0;
          double slowk = 0;
          double one_minus_slowk = 0;
          double fastEMA = 0;
          double fastk = 0;
          double one_minus_fastk = 0;
          double ad = 0;
          if( optInFastPeriod < optInSlowPeriod ) {
             slowestPeriod = optInSlowPeriod;
          } else {
             slowestPeriod = optInFastPeriod;
          }
          lookbackTotal = emaLookback(slowestPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          ad = 0.0;
          fastk = 2.0 / ((double)optInFastPeriod + 1.0);
          one_minus_fastk = 1.0 - fastk;
          slowk = 2.0 / ((double)optInSlowPeriod + 1.0);
          one_minus_slowk = 1.0 - slowk;
          high = inHigh[today];
          low = inLow[today];
          tmp = high - low;
          close = inClose[today];
          if( tmp > 0.0 ) {
             ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
          }
          today += 1;
          fastEMA = ad;
          slowEMA = ad;
          while( today < startIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
          }
          outIdx = 0;
          while( today <= endIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
             outReal[outIdx++] = fastEMA - slowEMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adOsc( int startIdx,
                             int endIdx,
                             float inHigh[],
                             float inLow[],
                             float inClose[],
                             float inVolume[],
                             int optInFastPeriod,
                             int optInSlowPeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int slowestPeriod = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double slowEMA = 0;
          double slowk = 0;
          double one_minus_slowk = 0;
          double fastEMA = 0;
          double fastk = 0;
          double one_minus_fastk = 0;
          double ad = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 3;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 10;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastPeriod < optInSlowPeriod ) {
             slowestPeriod = optInSlowPeriod;
          } else {
             slowestPeriod = optInFastPeriod;
          }
          lookbackTotal = emaLookback(slowestPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          ad = 0.0;
          fastk = 2.0 / ((double)optInFastPeriod + 1.0);
          one_minus_fastk = 1.0 - fastk;
          slowk = 2.0 / ((double)optInSlowPeriod + 1.0);
          one_minus_slowk = 1.0 - slowk;
          high = inHigh[today];
          low = inLow[today];
          tmp = high - low;
          close = inClose[today];
          if( tmp > 0.0 ) {
             ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
          }
          today += 1;
          fastEMA = ad;
          slowEMA = ad;
          while( today < startIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
          }
          outIdx = 0;
          while( today <= endIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
             outReal[outIdx++] = fastEMA - slowEMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adOscUnguarded( int startIdx,
                                      int endIdx,
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      float inVolume[],
                                      int optInFastPeriod,
                                      int optInSlowPeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int slowestPeriod = 0;
          double high = 0;
          double low = 0;
          double close = 0;
          double tmp = 0;
          double slowEMA = 0;
          double slowk = 0;
          double one_minus_slowk = 0;
          double fastEMA = 0;
          double fastk = 0;
          double one_minus_fastk = 0;
          double ad = 0;
          if( optInFastPeriod < optInSlowPeriod ) {
             slowestPeriod = optInSlowPeriod;
          } else {
             slowestPeriod = optInFastPeriod;
          }
          lookbackTotal = emaLookback(slowestPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          ad = 0.0;
          fastk = 2.0 / ((double)optInFastPeriod + 1.0);
          one_minus_fastk = 1.0 - fastk;
          slowk = 2.0 / ((double)optInSlowPeriod + 1.0);
          one_minus_slowk = 1.0 - slowk;
          high = inHigh[today];
          low = inLow[today];
          tmp = high - low;
          close = inClose[today];
          if( tmp > 0.0 ) {
             ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
          }
          today += 1;
          fastEMA = ad;
          slowEMA = ad;
          while( today < startIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
          }
          outIdx = 0;
          while( today <= endIdx ) {
             high = inHigh[today];
             low = inLow[today];
             tmp = high - low;
             close = inClose[today];
             if( tmp > 0.0 ) {
                ad += (close - low - (high - close)) / tmp * (double)inVolume[today];
             }
             today += 1;
             fastEMA = fastk * ad + one_minus_fastk * fastEMA;
             slowEMA = slowk * ad + one_minus_slowk * slowEMA;
             outReal[outIdx++] = fastEMA - slowEMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel
     *  MIF      Mirek Fontan (mira@fontan.cz)
     *  GC       guycom@users.sourceforge.net
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  082303 MF   Fix #792298. Remove rounding. Bug reported by AM.
     *  062704 MF   Fix #965557. Div by zero bug reported by MIF.
     *  082206 MF   Fix #1544555. Div by zero bug reported by GC.
     */

       public int adxLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return 2 * optInTimePeriod + this.unstablePeriod[FuncUnstId.Adx.ordinal()] - 1 ;

       }
       public RetCode adx( int startIdx,
                           int endIdx,
                           double inHigh[],
                           double inLow[],
                           double inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          double sumDX = 0;
          double prevADX = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM=0
           * B|  | -DM=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a -DM14, sum the -DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous -DM14
           *  Today's -DM14 = Previous -DM14 -  -------------- + Today's -DM1
           *                                         14
           *
           * (Same thing for +DM14)
           *
           * Calculation of a -DI14 is as follow:
           *
           *               -DM14
           *     -DI14 =  --------
           *                TR14
           *
           * (Same thing for +DI14)
           *
           * Calculation of the TR14 is:
           *
           *                                   Previous TR14
           *    Today's TR14 = Previous TR14 - -------------- + Today's TR1
           *                                         14
           *
           *    The first TR14 is the summation of the first 14 TR1. See the
           *    TA_TRANGE function on how to calculate the true range.
           *
           * Calculation of the DX14 is:
           *
           *    diffDI = ABS( (-DI14) - (+DI14) )
           *    sumDI  = (-DI14) + (+DI14)
           *
           *    DX14 = 100 * (diffDI / sumDI)
           *
           * Calculation of the first ADX:
           *
           *    ADX14 = SUM of the first 14 DX
           *
           * Calculation of subsequent ADX:
           *
           *            ((Previous ADX14)*(14-1))+ Today's DX
           *    ADX14 = -------------------------------------
           *                             14
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          /* Original implementation from Wilder's book was doing some integer
           * rounding in its calculations.
           *
           * This was understandable in the context that at the time the book
           * was written, most user were doing the calculation by hand.
           *
           * For a computer, rounding is unnecessary (and even problematic when inputs
           * are close to 1).
           *
           * TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
           * you can comment out the following #undef/#define and rebuild the library.
           */
          lookbackTotal = 2 * optInTimePeriod + this.unstablePeriod[FuncUnstId.Adx.ordinal()] - 1;
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Process the initial DM and TR */
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          /* Add up all the initial DX. */
          sumDX = 0.0;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             /* Calculate the prevTR */
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             /* Calculate the DX. The value is rounded (see Wilder book). */
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                /* This loop is just to accumulate the initial DX */
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   sumDX += (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                }
             }
          }
          /* Calculate the first ADX */
          prevADX = (sumDX / optInTimePeriod);
          /* Skip the unstable period */
          i = this.unstablePeriod[FuncUnstId.Adx.ordinal()];
          while( i-- > 0 ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             /* Calculate the prevTR */
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                /* Calculate the DX. The value is rounded (see Wilder book). */
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   /* Calculate the ADX */
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
          }
          /* Output the first ADX */
          outReal[0] = prevADX;
          outIdx = 1;
          /* Calculate and output subsequent ADX */
          while( today < endIdx ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             /* Calculate the prevTR */
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                /* Calculate the DX. The value is rounded (see Wilder book). */
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   /* Calculate the ADX */
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
             /* Output the ADX */
             outReal[outIdx++] = prevADX;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adxUnguarded( int startIdx,
                                    int endIdx,
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          double sumDX = 0;
          double prevADX = 0;
          int i = 0;
          lookbackTotal = 2 * optInTimePeriod + this.unstablePeriod[FuncUnstId.Adx.ordinal()] - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          sumDX = 0.0;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   sumDX += (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                }
             }
          }
          prevADX = (sumDX / optInTimePeriod);
          i = this.unstablePeriod[FuncUnstId.Adx.ordinal()];
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
          }
          outReal[0] = prevADX;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
             outReal[outIdx++] = prevADX;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adx( int startIdx,
                           int endIdx,
                           float inHigh[],
                           float inLow[],
                           float inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          double sumDX = 0;
          double prevADX = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = 2 * optInTimePeriod + this.unstablePeriod[FuncUnstId.Adx.ordinal()] - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          sumDX = 0.0;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   sumDX += (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                }
             }
          }
          prevADX = (sumDX / optInTimePeriod);
          i = this.unstablePeriod[FuncUnstId.Adx.ordinal()];
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
          }
          outReal[0] = prevADX;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
             outReal[outIdx++] = prevADX;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adxUnguarded( int startIdx,
                                    int endIdx,
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          double sumDX = 0;
          double prevADX = 0;
          int i = 0;
          lookbackTotal = 2 * optInTimePeriod + this.unstablePeriod[FuncUnstId.Adx.ordinal()] - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          sumDX = 0.0;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   sumDX += (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                }
             }
          }
          prevADX = (sumDX / optInTimePeriod);
          i = this.unstablePeriod[FuncUnstId.Adx.ordinal()];
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
          }
          outReal[0] = prevADX;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   tempReal = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                   prevADX = ((prevADX * (optInTimePeriod - 1) + tempReal) / optInTimePeriod);
                }
             }
             outReal[outIdx++] = prevADX;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  082303 MF   Fix #792298. Remove rounding. Bug reported by AM.
     */

       public int adxrLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + adxLookback(optInTimePeriod) - 1 ;
          } else {
             return 3 ;
          }

       }
       public RetCode adxr( int startIdx,
                            int endIdx,
                            double inHigh[],
                            double inLow[],
                            double inClose[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] adx;
          int adxrLookback = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int nbElement = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Original implementation from Wilder's book was doing some integer
           * rounding in its calculations.
           *
           * This was understandable in the context that at the time the book
           * was written, most user were doing the calculation by hand.
           *
           * For a computer, rounding is unnecessary (and even problematic when inputs
           * are close to 1).
           *
           * TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
           * you can comment out the following #undef/#define and rebuild the library.
           */
          /* Move up the start index if there is not
           * enough initial data.
           * Always one price bar gets consumed.
           */
          adxrLookback = adxrLookback(optInTimePeriod);
          if( startIdx < adxrLookback ) {
             startIdx = adxrLookback;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          adx = new double[(int)((endIdx - startIdx + optInTimePeriod) * 1)];
          retCode = adxUnguarded(startIdx - (optInTimePeriod - 1), endIdx, inHigh, inLow, inClose, optInTimePeriod, outBegIdx, outNBElement, adx);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          i = optInTimePeriod - 1;
          j = 0;
          outIdx = 0;
          nbElement = endIdx - startIdx + 2;
          while( --nbElement != 0 ) {
             outReal[outIdx++] = ((adx[i++] + adx[j++]) / 2.0);
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adxrUnguarded( int startIdx,
                                     int endIdx,
                                     double inHigh[],
                                     double inLow[],
                                     double inClose[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] adx;
          int adxrLookback = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int nbElement = 0;
          RetCode retCode;
          adxrLookback = adxrLookback(optInTimePeriod);
          if( startIdx < adxrLookback ) {
             startIdx = adxrLookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          adx = new double[(int)((endIdx - startIdx + optInTimePeriod) * 1)];
          retCode = adxUnguarded(startIdx - (optInTimePeriod - 1), endIdx, inHigh, inLow, inClose, optInTimePeriod, outBegIdx, outNBElement, adx);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          i = optInTimePeriod - 1;
          j = 0;
          outIdx = 0;
          nbElement = endIdx - startIdx + 2;
          while( --nbElement != 0 ) {
             outReal[outIdx++] = ((adx[i++] + adx[j++]) / 2.0);
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adxr( int startIdx,
                            int endIdx,
                            float inHigh[],
                            float inLow[],
                            float inClose[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] adx;
          int adxrLookback = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int nbElement = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          adxrLookback = adxrLookback(optInTimePeriod);
          if( startIdx < adxrLookback ) {
             startIdx = adxrLookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          adx = new double[(int)((endIdx - startIdx + optInTimePeriod) * 1)];
          retCode = adxUnguarded(startIdx - (optInTimePeriod - 1), endIdx, inHigh, inLow, inClose, optInTimePeriod, outBegIdx, outNBElement, adx);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          i = optInTimePeriod - 1;
          j = 0;
          outIdx = 0;
          nbElement = endIdx - startIdx + 2;
          while( --nbElement != 0 ) {
             outReal[outIdx++] = ((adx[i++] + adx[j++]) / 2.0);
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode adxrUnguarded( int startIdx,
                                     int endIdx,
                                     float inHigh[],
                                     float inLow[],
                                     float inClose[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] adx;
          int adxrLookback = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int nbElement = 0;
          RetCode retCode;
          adxrLookback = adxrLookback(optInTimePeriod);
          if( startIdx < adxrLookback ) {
             startIdx = adxrLookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          adx = new double[(int)((endIdx - startIdx + optInTimePeriod) * 1)];
          retCode = adxUnguarded(startIdx - (optInTimePeriod - 1), endIdx, inHigh, inLow, inClose, optInTimePeriod, outBegIdx, outNBElement, adx);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          i = optInTimePeriod - 1;
          j = 0;
          outIdx = 0;
          nbElement = endIdx - startIdx + 2;
          while( --nbElement != 0 ) {
             outReal[outIdx++] = ((adx[i++] + adx[j++]) / 2.0);
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AA       Andrew Atkinson
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  062804 MF   Resolve div by zero bug on limit case.
     *  020605 AA   Fix #1117666 Lookback & out-of-bound bug.
     */

       public int apoLookback( int optInFastPeriod, int optInSlowPeriod, MAType optInMAType )
       {
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return -1;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return -1;
          }
          /* The slow MA is the key factor determining the lookback period. */
          return movingAverageLookback(Math.max(optInSlowPeriod, optInFastPeriod), optInMAType) ;

       }
       public RetCode apo( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInFastPeriod,
                           int optInSlowPeriod,
                           MAType optInMAType,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Allocate an intermediate buffer. */
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          /* Make sure slow is really slower than
           * the fast period! if not, swap...
           */
          if( optInSlowPeriod < optInFastPeriod ) {
             /* swap */
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          /* Calculate the fast MA into the tempBuffer. */
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             /* Calculate the slow MA into the output. */
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                /* Calculate (fast MA)-(slow MA) in the output. */
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   outReal[i] = tempBuffer[j] - outReal[i];
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode apoUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInFastPeriod,
                                    int optInSlowPeriod,
                                    MAType optInMAType,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   outReal[i] = tempBuffer[j] - outReal[i];
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode apo( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInFastPeriod,
                           int optInSlowPeriod,
                           MAType optInMAType,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   outReal[i] = tempBuffer[j] - outReal[i];
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode apoUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInFastPeriod,
                                    int optInSlowPeriod,
                                    MAType optInMAType,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   outReal[i] = tempBuffer[j] - outReal[i];
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel <michel@pacbell.net>
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  050703 MF   Fix algorithm base on Adrian Michel bug report #748163
     */

       public int aroonLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode aroon( int startIdx,
                             int endIdx,
                             double inHigh[],
                             double inLow[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outAroonDown[],
                             double outAroonUp[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* This function is using a speed optimized algorithm
           * for the min/max logic.
           *
           * You might want to first look at how TA_MIN/TA_MAX works
           * and this function will become easier to understand.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             /* Keep track of the lowestIdx */
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             /* Keep track of the highestIdx */
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             /* Note: Do not forget that input and output buffer can be the same,
              *       so writing to the output is the last thing being done here.
              */
             outAroonUp[outIdx] = factor * (optInTimePeriod - (today - highestIdx));
             outAroonDown[outIdx] = factor * (optInTimePeriod - (today - lowestIdx));
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroonUnguarded( int startIdx,
                                      int endIdx,
                                      double inHigh[],
                                      double inLow[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outAroonDown[],
                                      double outAroonUp[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outAroonUp[outIdx] = factor * (optInTimePeriod - (today - highestIdx));
             outAroonDown[outIdx] = factor * (optInTimePeriod - (today - lowestIdx));
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroon( int startIdx,
                             int endIdx,
                             float inHigh[],
                             float inLow[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outAroonDown[],
                             double outAroonUp[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outAroonUp[outIdx] = factor * (optInTimePeriod - (today - highestIdx));
             outAroonDown[outIdx] = factor * (optInTimePeriod - (today - lowestIdx));
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroonUnguarded( int startIdx,
                                      int endIdx,
                                      float inHigh[],
                                      float inLow[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outAroonDown[],
                                      double outAroonUp[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outAroonUp[outIdx] = factor * (optInTimePeriod - (today - highestIdx));
             outAroonDown[outIdx] = factor * (optInTimePeriod - (today - lowestIdx));
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel <michel@pacbell.net>
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  050703 MF   Fix algorithm base on Adrian Michel bug report #748163
     */

       public int aroonOscLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode aroonOsc( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          double aroon = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* This code is almost identical to the TA_AROON function
           * except that instead of outputing ArroonUp and AroonDown
           * individually, an oscillator is build from both.
           *
           *  AroonOsc = AroonUp- AroonDown;
           */
          /* This function is using a speed optimized algorithm
           * for the min/max logic.
           *
           * You might want to first look at how TA_MIN/TA_MAX works
           * and this function will become easier to understand.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             /* Keep track of the lowestIdx */
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             /* Keep track of the highestIdx */
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             /* The oscillator is the following:
              *  AroonUp   = factor*(optInTimePeriod-(today-highestIdx));
              *  AroonDown = factor*(optInTimePeriod-(today-lowestIdx));
              *  AroonOsc  = AroonUp-AroonDown;
              *
              * An arithmetic simplification give us:
              *  Aroon = factor*(highestIdx-lowestIdx)
              */
             aroon = factor * (highestIdx - lowestIdx);
             /* Note: Do not forget that input and output buffer can be the same,
              *       so writing to the output is the last thing being done here.
              */
             outReal[outIdx] = aroon;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroonOscUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          double aroon = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             aroon = factor * (highestIdx - lowestIdx);
             outReal[outIdx] = aroon;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroonOsc( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          double aroon = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             aroon = factor * (highestIdx - lowestIdx);
             outReal[outIdx] = aroon;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode aroonOscUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double factor = 0;
          double aroon = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          lowestIdx = 0 - 1;
          highestIdx = 0 - 1;
          lowest = 0.0;
          highest = 0.0;
          factor = (double)100.0 / (double)optInTimePeriod;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp <= lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp >= highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             aroon = factor * (highestIdx - lowestIdx);
             outReal[outIdx] = aroon;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int asinLookback( )
       {
          return 0 ;

       }
       public RetCode asin( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.asin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode asinUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.asin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode asin( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.asin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode asinUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.asin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int atanLookback( )
       {
          return 0 ;

       }
       public RetCode atan( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Default return values */
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.atan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode atanUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.atan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode atan( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.atan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode atanUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.atan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int atrLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          /* The ATR lookback is the sum of:
           *    1 + (optInTimePeriod - 1)
           *
           * Where 1 is for the True Range, and
           * (optInTimePeriod-1) is for the simple
           * moving average.
           */
          return optInTimePeriod + this.unstablePeriod[FuncUnstId.Atr.ordinal()] ;

       }
       public RetCode atr( int startIdx,
                           int endIdx,
                           double inHigh[],
                           double inLow[],
                           double inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double[] tempBuffer;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Average True Range is the greatest of the following:
           *
           *  val1 = distance from today's high to today's low.
           *  val2 = distance from yesterday's close to today's high.
           *  val3 = distance from yesterday's close to today's low.
           *
           * These value are averaged for the specified period using
           * Wilder method. This method have an unstable period comparable
           * to and Exponential Moving Average (EMA).
           */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = atrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do a TRANGE. */
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          /* Allocate an intermediate buffer for TRANGE. */
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          /* Do TRANGE in the intermediate buffer. */
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          /* First value of the ATR is a simple Average of
           * the TRANGE output for the specified period.
           */
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          /* Subsequent value are smoothed using the
           * previous ATR value (Wilder's approach).
           *  1) Multiply the previous ATR by 'period-1'.
           *  2) Add today TR value.
           *  3) Divide by 'period'.
           */
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Atr.ordinal()];
          /* Skip the unstable period. */
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          /* Now start to write the final ATR in the caller
           * provided outReal.
           */
          outIdx = 1;
          outReal[0] = prevATR[0];
          /* Now do the number of requested ATR. */
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outReal[outIdx++] = prevATR[0];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode atrUnguarded( int startIdx,
                                    int endIdx,
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double[] tempBuffer;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = atrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Atr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          outReal[0] = prevATR[0];
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outReal[outIdx++] = prevATR[0];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode atr( int startIdx,
                           int endIdx,
                           float inHigh[],
                           float inLow[],
                           float inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double[] tempBuffer;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = atrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Atr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          outReal[0] = prevATR[0];
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outReal[outIdx++] = prevATR[0];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode atrUnguarded( int startIdx,
                                    int endIdx,
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double[] tempBuffer;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = atrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Atr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          outReal[0] = prevATR[0];
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outReal[outIdx++] = prevATR[0];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AB       Anatoliy Belsky
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090812 AB     Initial Version
     */

       public int avgDevLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode avgDev( int startIdx,
                              int endIdx,
                              double inReal[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookback = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookback = optInTimePeriod - 1;
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          today = startIdx;
          /* Make sure there is still something to evaluate. */
          if( today > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Process the initial DM and TR */
          outBegIdx.value = today;
          outIdx = 0;
          while( today <= endIdx ) {
             double todaySum;
             double todayDev;
             int i;
             todaySum = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todaySum += inReal[today - i];
             }
             todayDev = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todayDev += Math.abs(inReal[today - i] - todaySum / optInTimePeriod);
             }
             outReal[outIdx] = todayDev / optInTimePeriod;
             outIdx += 1;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode avgDevUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookback = 0;
          lookback = optInTimePeriod - 1;
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          today = startIdx;
          if( today > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = today;
          outIdx = 0;
          while( today <= endIdx ) {
             double todaySum;
             double todayDev;
             int i;
             todaySum = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todaySum += inReal[today - i];
             }
             todayDev = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todayDev += Math.abs(inReal[today - i] - todaySum / optInTimePeriod);
             }
             outReal[outIdx] = todayDev / optInTimePeriod;
             outIdx += 1;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode avgDev( int startIdx,
                              int endIdx,
                              float inReal[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookback = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookback = optInTimePeriod - 1;
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          today = startIdx;
          if( today > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = today;
          outIdx = 0;
          while( today <= endIdx ) {
             double todaySum;
             double todayDev;
             int i;
             todaySum = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todaySum += inReal[today - i];
             }
             todayDev = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todayDev += Math.abs(inReal[today - i] - todaySum / optInTimePeriod);
             }
             outReal[outIdx] = todayDev / optInTimePeriod;
             outIdx += 1;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode avgDevUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          int lookback = 0;
          lookback = optInTimePeriod - 1;
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          today = startIdx;
          if( today > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = today;
          outIdx = 0;
          while( today <= endIdx ) {
             double todaySum;
             double todayDev;
             int i;
             todaySum = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todaySum += inReal[today - i];
             }
             todayDev = 0.0;
             for( i = 0; i < optInTimePeriod; i += 1 ) {
                todayDev += Math.abs(inReal[today - i] - todaySum / optInTimePeriod);
             }
             outReal[outIdx] = todayDev / optInTimePeriod;
             outIdx += 1;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  112605 MF   Fix outBegIdx when startIdx != 0
     */

       public int avgPriceLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode avgPrice( int startIdx,
                                int endIdx,
                                double inOpen[],
                                double inHigh[],
                                double inLow[],
                                double inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Average price = (High + Low + Open + Close) / 4 */
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode avgPriceUnguarded( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode avgPrice( int startIdx,
                                int endIdx,
                                float inOpen[],
                                float inHigh[],
                                float inLow[],
                                float inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode avgPriceUnguarded( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JV       Jesus Viver <324122@cienz.unizar.es>
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  010503 MF   Fix to always use SMA for the STDDEV (Thanks to JV).
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int bbandsLookback( int optInTimePeriod, double optInNbDevUp, double optInNbDevDn, MAType optInMAType )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInNbDevUp == -4e37 ) {
             optInNbDevUp = 2e0;
          }
          if( optInNbDevDn == -4e37 ) {
             optInNbDevDn = 2e0;
          }
          /* The lookback is driven by the middle band moving average. */
          return movingAverageLookback(optInTimePeriod, optInMAType) ;

       }
       public RetCode bbands( int startIdx,
                              int endIdx,
                              double inReal[],
                              int optInTimePeriod,
                              double optInNbDevUp,
                              double optInNbDevDn,
                              MAType optInMAType,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outRealUpperBand[],
                              double outRealMiddleBand[],
                              double outRealLowerBand[] )
       {
          RetCode retCode;
          int i = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double[] tempBuffer1;
          double[] tempBuffer2;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDevUp == -4e37 ) {
             optInNbDevUp = 2e0;
          }
          if( optInNbDevDn == -4e37 ) {
             optInNbDevDn = 2e0;
          }
          /* Identify TWO temporary buffer among the outputs.
           *
           * These temporary buffers allows to perform the
           * calculation without any memory allocation.
           *
           * Whenever possible, make the tempBuffer1 be the
           * middle band output. This will save one copy operation.
           */
          if( inReal == outRealUpperBand ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealLowerBand;
          } else if( inReal == outRealLowerBand ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          } else if( inReal == outRealMiddleBand ) {
             tempBuffer1 = outRealLowerBand;
             tempBuffer2 = outRealUpperBand;
          } else {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          }
          /* Check that the caller is not doing tricky things.
           * (like using the input buffer in two output!)
           */
          if( tempBuffer1 == inReal || tempBuffer2 == inReal ) {
             return RetCode.BadParam ;
          }
          /* Calculate the middle band, which is a moving average.
           * The other two bands will simply add/substract the
           * standard deviation from this middle band.
           */
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInTimePeriod, optInMAType, outBegIdx, outNBElement, tempBuffer1);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the standard deviation into tempBuffer2. */
          if( optInMAType == MAType.Sma ) {
             /* A small speed optimization by re-using the
              * already calculated SMA.
              */
             /* Inline stddev_using_precalc_ma */
             double _tempReal;
             double _periodTotal2;
             double _meanValue2;
             int _outIdx;
             int _startSum;
             int _endSum;
             _startSum = 1 + (int)outBegIdx.value - optInTimePeriod;
             _endSum = (int)outBegIdx.value;
             _periodTotal2 = 0;
             for( _outIdx = _startSum; _outIdx < _endSum; _outIdx += 1 ) {
                _tempReal = inReal[_outIdx];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
             }
             for( _outIdx = 0; _outIdx < (int)outNBElement.value; _outIdx += 1, _startSum += 1, _endSum += 1 ) {
                _tempReal = inReal[_endSum];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
                _meanValue2 = _periodTotal2 / optInTimePeriod;
                _tempReal = inReal[_startSum];
                _tempReal *= _tempReal;
                _periodTotal2 -= _tempReal;
                _tempReal = tempBuffer1[_outIdx];
                _tempReal *= _tempReal;
                _meanValue2 -= _tempReal;
                if( !(_meanValue2 < 0.00000000000001) ) {
                   tempBuffer2[_outIdx] = Math.sqrt(_meanValue2);
                } else {
                   tempBuffer2[_outIdx] = 0.0;
                }
             }
          } else {
             /* Calculate the Standard Deviation */
             retCode = stdDevUnguarded((int)outBegIdx.value, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, tempBuffer2);
             if( retCode != RetCode.Success ) {
                outNBElement.value = 0;
                return retCode ;
             }
          }
          /* Copy the MA calculation into the middle band ouput, unless
           * the calculation was done into it already!
           */
          if( tempBuffer1 != outRealMiddleBand ) {
             System.arraycopy(tempBuffer1, 0, outRealMiddleBand, 0, outNBElement.value * 1);
          }
          /* Now do a tight loop to calculate the upper/lower band at
           * the same time.
           *
           * All the following 5 loops are doing the same, except there
           * is an attempt to speed optimize by eliminating uneeded
           * multiplication.
           */
          if( optInNbDevUp == optInNbDevDn ) {
             if( optInNbDevUp == 1.0 ) {
                /* No standard deviation multiplier needed. */
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i];
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             } else {
                /* Upper/lower band use the same standard deviation multiplier. */
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i] * optInNbDevUp;
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             }
          } else if( optInNbDevUp == 1.0 ) {
             /* Only lower band has a standard deviation multiplier. */
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          } else if( optInNbDevDn == 1.0 ) {
             /* Only upper band has a standard deviation multiplier. */
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealLowerBand[i] = tempReal2 - tempReal;
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
             }
          } else {
             /* Upper/lower band have distinctive standard deviation multiplier. */
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          }
          return RetCode.Success ;
       }
       public RetCode bbandsUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal[],
                                       int optInTimePeriod,
                                       double optInNbDevUp,
                                       double optInNbDevDn,
                                       MAType optInMAType,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outRealUpperBand[],
                                       double outRealMiddleBand[],
                                       double outRealLowerBand[] )
       {
          RetCode retCode;
          int i = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double[] tempBuffer1;
          double[] tempBuffer2;
          if( inReal == outRealUpperBand ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealLowerBand;
          } else if( inReal == outRealLowerBand ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          } else if( inReal == outRealMiddleBand ) {
             tempBuffer1 = outRealLowerBand;
             tempBuffer2 = outRealUpperBand;
          } else {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          }
          if( tempBuffer1 == inReal || tempBuffer2 == inReal ) {
             return RetCode.BadParam ;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInTimePeriod, optInMAType, outBegIdx, outNBElement, tempBuffer1);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             return retCode ;
          }
          if( optInMAType == MAType.Sma ) {
             double _tempReal;
             double _periodTotal2;
             double _meanValue2;
             int _outIdx;
             int _startSum;
             int _endSum;
             _startSum = 1 + (int)outBegIdx.value - optInTimePeriod;
             _endSum = (int)outBegIdx.value;
             _periodTotal2 = 0;
             for( _outIdx = _startSum; _outIdx < _endSum; _outIdx += 1 ) {
                _tempReal = inReal[_outIdx];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
             }
             for( _outIdx = 0; _outIdx < (int)outNBElement.value; _outIdx += 1, _startSum += 1, _endSum += 1 ) {
                _tempReal = inReal[_endSum];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
                _meanValue2 = _periodTotal2 / optInTimePeriod;
                _tempReal = inReal[_startSum];
                _tempReal *= _tempReal;
                _periodTotal2 -= _tempReal;
                _tempReal = tempBuffer1[_outIdx];
                _tempReal *= _tempReal;
                _meanValue2 -= _tempReal;
                if( !(_meanValue2 < 0.00000000000001) ) {
                   tempBuffer2[_outIdx] = Math.sqrt(_meanValue2);
                } else {
                   tempBuffer2[_outIdx] = 0.0;
                }
             }
          } else {
             retCode = stdDevUnguarded((int)outBegIdx.value, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, tempBuffer2);
             if( retCode != RetCode.Success ) {
                outNBElement.value = 0;
                return retCode ;
             }
          }
          if( tempBuffer1 != outRealMiddleBand ) {
             System.arraycopy(tempBuffer1, 0, outRealMiddleBand, 0, outNBElement.value * 1);
          }
          if( optInNbDevUp == optInNbDevDn ) {
             if( optInNbDevUp == 1.0 ) {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i];
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             } else {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i] * optInNbDevUp;
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             }
          } else if( optInNbDevUp == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          } else if( optInNbDevDn == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealLowerBand[i] = tempReal2 - tempReal;
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          }
          return RetCode.Success ;
       }
       public RetCode bbands( int startIdx,
                              int endIdx,
                              float inReal[],
                              int optInTimePeriod,
                              double optInNbDevUp,
                              double optInNbDevDn,
                              MAType optInMAType,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outRealUpperBand[],
                              double outRealMiddleBand[],
                              double outRealLowerBand[] )
       {
          RetCode retCode;
          int i = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double[] tempBuffer1;
          double[] tempBuffer2;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDevUp == -4e37 ) {
             optInNbDevUp = 2e0;
          }
          if( optInNbDevDn == -4e37 ) {
             optInNbDevDn = 2e0;
          }
          if( false ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealLowerBand;
          } else if( false ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          } else if( false ) {
             tempBuffer1 = outRealLowerBand;
             tempBuffer2 = outRealUpperBand;
          } else {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          }
          if( false || false ) {
             return RetCode.BadParam ;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInTimePeriod, optInMAType, outBegIdx, outNBElement, tempBuffer1);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             return retCode ;
          }
          if( optInMAType == MAType.Sma ) {
             double _tempReal;
             double _periodTotal2;
             double _meanValue2;
             int _outIdx;
             int _startSum;
             int _endSum;
             _startSum = 1 + (int)outBegIdx.value - optInTimePeriod;
             _endSum = (int)outBegIdx.value;
             _periodTotal2 = 0;
             for( _outIdx = _startSum; _outIdx < _endSum; _outIdx += 1 ) {
                _tempReal = inReal[_outIdx];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
             }
             for( _outIdx = 0; _outIdx < (int)outNBElement.value; _outIdx += 1, _startSum += 1, _endSum += 1 ) {
                _tempReal = inReal[_endSum];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
                _meanValue2 = _periodTotal2 / optInTimePeriod;
                _tempReal = inReal[_startSum];
                _tempReal *= _tempReal;
                _periodTotal2 -= _tempReal;
                _tempReal = tempBuffer1[_outIdx];
                _tempReal *= _tempReal;
                _meanValue2 -= _tempReal;
                if( !(_meanValue2 < 0.00000000000001) ) {
                   tempBuffer2[_outIdx] = Math.sqrt(_meanValue2);
                } else {
                   tempBuffer2[_outIdx] = 0.0;
                }
             }
          } else {
             retCode = stdDevUnguarded((int)outBegIdx.value, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, tempBuffer2);
             if( retCode != RetCode.Success ) {
                outNBElement.value = 0;
                return retCode ;
             }
          }
          if( tempBuffer1 != outRealMiddleBand ) {
             System.arraycopy(tempBuffer1, 0, outRealMiddleBand, 0, outNBElement.value * 1);
          }
          if( optInNbDevUp == optInNbDevDn ) {
             if( optInNbDevUp == 1.0 ) {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i];
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             } else {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i] * optInNbDevUp;
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             }
          } else if( optInNbDevUp == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          } else if( optInNbDevDn == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealLowerBand[i] = tempReal2 - tempReal;
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          }
          return RetCode.Success ;
       }
       public RetCode bbandsUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal[],
                                       int optInTimePeriod,
                                       double optInNbDevUp,
                                       double optInNbDevDn,
                                       MAType optInMAType,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outRealUpperBand[],
                                       double outRealMiddleBand[],
                                       double outRealLowerBand[] )
       {
          RetCode retCode;
          int i = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double[] tempBuffer1;
          double[] tempBuffer2;
          if( false ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealLowerBand;
          } else if( false ) {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          } else if( false ) {
             tempBuffer1 = outRealLowerBand;
             tempBuffer2 = outRealUpperBand;
          } else {
             tempBuffer1 = outRealMiddleBand;
             tempBuffer2 = outRealUpperBand;
          }
          if( false || false ) {
             return RetCode.BadParam ;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInTimePeriod, optInMAType, outBegIdx, outNBElement, tempBuffer1);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             return retCode ;
          }
          if( optInMAType == MAType.Sma ) {
             double _tempReal;
             double _periodTotal2;
             double _meanValue2;
             int _outIdx;
             int _startSum;
             int _endSum;
             _startSum = 1 + (int)outBegIdx.value - optInTimePeriod;
             _endSum = (int)outBegIdx.value;
             _periodTotal2 = 0;
             for( _outIdx = _startSum; _outIdx < _endSum; _outIdx += 1 ) {
                _tempReal = inReal[_outIdx];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
             }
             for( _outIdx = 0; _outIdx < (int)outNBElement.value; _outIdx += 1, _startSum += 1, _endSum += 1 ) {
                _tempReal = inReal[_endSum];
                _tempReal *= _tempReal;
                _periodTotal2 += _tempReal;
                _meanValue2 = _periodTotal2 / optInTimePeriod;
                _tempReal = inReal[_startSum];
                _tempReal *= _tempReal;
                _periodTotal2 -= _tempReal;
                _tempReal = tempBuffer1[_outIdx];
                _tempReal *= _tempReal;
                _meanValue2 -= _tempReal;
                if( !(_meanValue2 < 0.00000000000001) ) {
                   tempBuffer2[_outIdx] = Math.sqrt(_meanValue2);
                } else {
                   tempBuffer2[_outIdx] = 0.0;
                }
             }
          } else {
             retCode = stdDevUnguarded((int)outBegIdx.value, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, tempBuffer2);
             if( retCode != RetCode.Success ) {
                outNBElement.value = 0;
                return retCode ;
             }
          }
          if( tempBuffer1 != outRealMiddleBand ) {
             System.arraycopy(tempBuffer1, 0, outRealMiddleBand, 0, outNBElement.value * 1);
          }
          if( optInNbDevUp == optInNbDevDn ) {
             if( optInNbDevUp == 1.0 ) {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i];
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             } else {
                for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                   tempReal = tempBuffer2[i] * optInNbDevUp;
                   tempReal2 = outRealMiddleBand[i];
                   outRealUpperBand[i] = tempReal2 + tempReal;
                   outRealLowerBand[i] = tempReal2 - tempReal;
                }
             }
          } else if( optInNbDevUp == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          } else if( optInNbDevDn == 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealLowerBand[i] = tempReal2 - tempReal;
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = tempBuffer2[i];
                tempReal2 = outRealMiddleBand[i];
                outRealUpperBand[i] = tempReal2 + tempReal * optInNbDevUp;
                outRealLowerBand[i] = tempReal2 - tempReal * optInNbDevDn;
             }
          }
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MW       Michael Williamson
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  122006 MW   Initial Version
     */

       public int betaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode beta( int startIdx,
                            int endIdx,
                            double inReal0[],
                            double inReal1[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double S_xx = 0;
          double S_xy = 0;
          double S_x = 0;
          double S_y = 0;
          double last_price_x = 0;
          double last_price_y = 0;
          double trailing_last_price_x = 0;
          double trailing_last_price_y = 0;
          double tmp_real = 0;
          double x = 0;
          double y = 0;
          double n = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          S_xx = 0.0;
          S_xy = 0.0;
          S_x = 0.0;
          S_y = 0.0;
          last_price_x = 0.0;
          last_price_y = 0.0;
          trailing_last_price_x = 0.0;
          trailing_last_price_y = 0.0;
          tmp_real = 0.0;
          n = 0.0;
          /* sum of x * x */
          /* sum of x * y */
          /* sum of x */
          /* sum of y */
          /* the last price read from inReal0 */
          /* the last price read from inReal1 */
          /* same as last_price_x except used to remove elements from the trailing summation */
          /* same as last_price_y except used to remove elements from the trailing summation */
          /* temporary variable */
          /* the 'x' value, which is the last change between values in inReal0 */
          /* the 'y' value, which is the last change between values in inReal1 */
          /* DESCRIPTION OF ALGORITHM:
           *   The Beta 'algorithm' is a measure of a stocks volatility vs from index. The stock prices
           *   are given in inReal0 and the index prices are give in inReal1. The size of these vectors
           *   should be equal. The algorithm is to calculate the change between prices in both vectors
           *   and then 'plot' these changes are points in the Euclidean plane. The x value of the point
           *   is market return and the y value is the security return. The beta value is the slope of a
           *   linear regression through these points. A beta of 1 is simple the line y=x, so the stock
           *   varies percisely with the market. A beta of less than one means the stock varies less than
           *   the market and a beta of more than one means the stock varies more than market. A related
           *   value is the Alpha value (see TA_ALPHA) which is the Y-intercept of the same linear regression.
           */
          /* Validate the calculation method type and
           * identify the minimum number of input
           * consume before the first value is output..
           */
          nbInitialElementNeeded = optInTimePeriod;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Consume first input. */
          trailingIdx = startIdx - nbInitialElementNeeded;
          trailing_last_price_x = inReal0[trailingIdx];
          last_price_x = trailing_last_price_x;
          trailing_last_price_y = inReal1[trailingIdx];
          last_price_y = trailing_last_price_y;
          /* Process remaining of lookback until ready to output the first value. */
          i = ++trailingIdx;
          while( i < startIdx ) {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
          }
          outIdx = 0;
          /* First output always start at index zero */
          n = (double)optInTimePeriod;
          do {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
             /* Always read the trailing before writing the output because the input and output
              * buffer can be the same.
              */
             tmp_real = inReal0[trailingIdx];
             if( !((-0.00000000000001 < trailing_last_price_x) && (trailing_last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - trailing_last_price_x) / trailing_last_price_x;
             } else {
                x = 0.0;
             }
             trailing_last_price_x = tmp_real;
             tmp_real = inReal1[trailingIdx++];
             if( !((-0.00000000000001 < trailing_last_price_y) && (trailing_last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - trailing_last_price_y) / trailing_last_price_y;
             } else {
                y = 0.0;
             }
             trailing_last_price_y = tmp_real;
             /* Write the output */
             tmp_real = n * S_xx - S_x * S_x;
             if( !((-0.00000000000001 < tmp_real) && (tmp_real < 0.00000000000001)) ) {
                outReal[outIdx++] = (n * S_xy - S_x * S_y) / tmp_real;
             } else {
                outReal[outIdx++] = 0.0;
             }
             /* Remove the calculation starting with the trailingIdx. */
             S_xx -= x * x;
             S_xy -= x * y;
             S_x -= x;
             S_y -= y;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode betaUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal0[],
                                     double inReal1[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double S_xx = 0;
          double S_xy = 0;
          double S_x = 0;
          double S_y = 0;
          double last_price_x = 0;
          double last_price_y = 0;
          double trailing_last_price_x = 0;
          double trailing_last_price_y = 0;
          double tmp_real = 0;
          double x = 0;
          double y = 0;
          double n = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          S_xx = 0.0;
          S_xy = 0.0;
          S_x = 0.0;
          S_y = 0.0;
          last_price_x = 0.0;
          last_price_y = 0.0;
          trailing_last_price_x = 0.0;
          trailing_last_price_y = 0.0;
          tmp_real = 0.0;
          n = 0.0;
          nbInitialElementNeeded = optInTimePeriod;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          trailingIdx = startIdx - nbInitialElementNeeded;
          trailing_last_price_x = inReal0[trailingIdx];
          last_price_x = trailing_last_price_x;
          trailing_last_price_y = inReal1[trailingIdx];
          last_price_y = trailing_last_price_y;
          i = ++trailingIdx;
          while( i < startIdx ) {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
          }
          outIdx = 0;
          n = (double)optInTimePeriod;
          do {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
             tmp_real = inReal0[trailingIdx];
             if( !((-0.00000000000001 < trailing_last_price_x) && (trailing_last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - trailing_last_price_x) / trailing_last_price_x;
             } else {
                x = 0.0;
             }
             trailing_last_price_x = tmp_real;
             tmp_real = inReal1[trailingIdx++];
             if( !((-0.00000000000001 < trailing_last_price_y) && (trailing_last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - trailing_last_price_y) / trailing_last_price_y;
             } else {
                y = 0.0;
             }
             trailing_last_price_y = tmp_real;
             tmp_real = n * S_xx - S_x * S_x;
             if( !((-0.00000000000001 < tmp_real) && (tmp_real < 0.00000000000001)) ) {
                outReal[outIdx++] = (n * S_xy - S_x * S_y) / tmp_real;
             } else {
                outReal[outIdx++] = 0.0;
             }
             S_xx -= x * x;
             S_xy -= x * y;
             S_x -= x;
             S_y -= y;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode beta( int startIdx,
                            int endIdx,
                            float inReal0[],
                            float inReal1[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double S_xx = 0;
          double S_xy = 0;
          double S_x = 0;
          double S_y = 0;
          double last_price_x = 0;
          double last_price_y = 0;
          double trailing_last_price_x = 0;
          double trailing_last_price_y = 0;
          double tmp_real = 0;
          double x = 0;
          double y = 0;
          double n = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          S_xx = 0.0;
          S_xy = 0.0;
          S_x = 0.0;
          S_y = 0.0;
          last_price_x = 0.0;
          last_price_y = 0.0;
          trailing_last_price_x = 0.0;
          trailing_last_price_y = 0.0;
          tmp_real = 0.0;
          n = 0.0;
          nbInitialElementNeeded = optInTimePeriod;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          trailingIdx = startIdx - nbInitialElementNeeded;
          trailing_last_price_x = inReal0[trailingIdx];
          last_price_x = trailing_last_price_x;
          trailing_last_price_y = inReal1[trailingIdx];
          last_price_y = trailing_last_price_y;
          i = ++trailingIdx;
          while( i < startIdx ) {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
          }
          outIdx = 0;
          n = (double)optInTimePeriod;
          do {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
             tmp_real = inReal0[trailingIdx];
             if( !((-0.00000000000001 < trailing_last_price_x) && (trailing_last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - trailing_last_price_x) / trailing_last_price_x;
             } else {
                x = 0.0;
             }
             trailing_last_price_x = tmp_real;
             tmp_real = inReal1[trailingIdx++];
             if( !((-0.00000000000001 < trailing_last_price_y) && (trailing_last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - trailing_last_price_y) / trailing_last_price_y;
             } else {
                y = 0.0;
             }
             trailing_last_price_y = tmp_real;
             tmp_real = n * S_xx - S_x * S_x;
             if( !((-0.00000000000001 < tmp_real) && (tmp_real < 0.00000000000001)) ) {
                outReal[outIdx++] = (n * S_xy - S_x * S_y) / tmp_real;
             } else {
                outReal[outIdx++] = 0.0;
             }
             S_xx -= x * x;
             S_xy -= x * y;
             S_x -= x;
             S_y -= y;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode betaUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal0[],
                                     float inReal1[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double S_xx = 0;
          double S_xy = 0;
          double S_x = 0;
          double S_y = 0;
          double last_price_x = 0;
          double last_price_y = 0;
          double trailing_last_price_x = 0;
          double trailing_last_price_y = 0;
          double tmp_real = 0;
          double x = 0;
          double y = 0;
          double n = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          S_xx = 0.0;
          S_xy = 0.0;
          S_x = 0.0;
          S_y = 0.0;
          last_price_x = 0.0;
          last_price_y = 0.0;
          trailing_last_price_x = 0.0;
          trailing_last_price_y = 0.0;
          tmp_real = 0.0;
          n = 0.0;
          nbInitialElementNeeded = optInTimePeriod;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          trailingIdx = startIdx - nbInitialElementNeeded;
          trailing_last_price_x = inReal0[trailingIdx];
          last_price_x = trailing_last_price_x;
          trailing_last_price_y = inReal1[trailingIdx];
          last_price_y = trailing_last_price_y;
          i = ++trailingIdx;
          while( i < startIdx ) {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
          }
          outIdx = 0;
          n = (double)optInTimePeriod;
          do {
             tmp_real = inReal0[i];
             if( !((-0.00000000000001 < last_price_x) && (last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - last_price_x) / last_price_x;
             } else {
                x = 0.0;
             }
             last_price_x = tmp_real;
             tmp_real = inReal1[i++];
             if( !((-0.00000000000001 < last_price_y) && (last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - last_price_y) / last_price_y;
             } else {
                y = 0.0;
             }
             last_price_y = tmp_real;
             S_xx += x * x;
             S_xy += x * y;
             S_x += x;
             S_y += y;
             tmp_real = inReal0[trailingIdx];
             if( !((-0.00000000000001 < trailing_last_price_x) && (trailing_last_price_x < 0.00000000000001)) ) {
                x = (tmp_real - trailing_last_price_x) / trailing_last_price_x;
             } else {
                x = 0.0;
             }
             trailing_last_price_x = tmp_real;
             tmp_real = inReal1[trailingIdx++];
             if( !((-0.00000000000001 < trailing_last_price_y) && (trailing_last_price_y < 0.00000000000001)) ) {
                y = (tmp_real - trailing_last_price_y) / trailing_last_price_y;
             } else {
                y = 0.0;
             }
             trailing_last_price_y = tmp_real;
             tmp_real = n * S_xx - S_x * S_x;
             if( !((-0.00000000000001 < tmp_real) && (tmp_real < 0.00000000000001)) ) {
                outReal[outIdx++] = (n * S_xy - S_x * S_y) / tmp_real;
             } else {
                outReal[outIdx++] = 0.0;
             }
             S_xx -= x * x;
             S_xy -= x * y;
             S_x -= x;
             S_y -= y;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112605 MF   Initial coding.
     */

       public int bopLookback( )
       {
          return 0 ;

       }
       public RetCode bop( int startIdx,
                           int endIdx,
                           double inOpen[],
                           double inHigh[],
                           double inLow[],
                           double inClose[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* BOP = (Close - Open)/(High - Low) */
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inHigh[i] - inLow[i];
             if( (tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = (inClose[i] - inOpen[i]) / tempReal;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode bopUnguarded( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          double tempReal = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inHigh[i] - inLow[i];
             if( (tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = (inClose[i] - inOpen[i]) / tempReal;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode bop( int startIdx,
                           int endIdx,
                           float inOpen[],
                           float inHigh[],
                           float inLow[],
                           float inClose[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inHigh[i] - inLow[i];
             if( (tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = (inClose[i] - inOpen[i]) / tempReal;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode bopUnguarded( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          double tempReal = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inHigh[i] - inLow[i];
             if( (tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = (inClose[i] - inOpen[i]) / tempReal;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  031202 MF   Template creation.
     *  052603 MF   Port to managed C++. Change to use CIRCBUF macros.
     *  061704 MF   Lower limit for period to 2, and correct algorithm
     *              to avoid cummulative error when value are close to
     *              the floating point epsilon.
     */

       public int cciLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode cci( int startIdx,
                           int endIdx,
                           double inHigh[],
                           double inLow[],
                           double inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double tempReal = 0;
          double tempReal2 = 0;
          double theAverage = 0;
          double lastValue = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double[] circBuffer;
          int circBuffer_Idx = 0;
          int maxIdx_circBuffer = (30)-1;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* This ptr will points on a circular buffer of
           * at least "optInTimePeriod" element.
           */
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Allocate a circular buffer equal to the requested
           * period.
           */
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          circBuffer = new double[optInTimePeriod];
          maxIdx_circBuffer = (optInTimePeriod)-1;
          circBuffer_Idx = 0;
          /* Do the MA calculation using tight loops. */
          /* Add-up the initial period, except for the last value.
           * Fill up the circular buffer at the same time.
           */
          i = startIdx - lookbackTotal;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                circBuffer[circBuffer_Idx] = (inHigh[i] + inLow[i] + inClose[i]) / 3;
                i += 1;
                circBuffer_Idx++;
                if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             }
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the inReal and
           * outReal to be the same buffer.
           */
          outIdx = 0;
          do {
             lastValue = (inHigh[i] + inLow[i] + inClose[i]) / 3;
             circBuffer[circBuffer_Idx] = lastValue;
             /* Calculate the average for the whole period. */
             theAverage = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                theAverage += circBuffer[j];
             }
             theAverage /= optInTimePeriod;
             /* Do the summation of the ABS(TypePrice-average)
              * for the whole period.
              */
             tempReal2 = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                tempReal2 += Math.abs(circBuffer[j] - theAverage);
             }
             /* And finally, the CCI... */
             tempReal = lastValue - theAverage;
             if( tempReal != 0.0 && tempReal2 != 0.0 ) {
                outReal[outIdx++] = tempReal / (0.015 * (tempReal2 / optInTimePeriod));
             } else {
                outReal[outIdx++] = 0.0;
             }
             /* Move forward the circular buffer indexes. */
             circBuffer_Idx++;
             if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          /* Free the circular buffer if it was dynamically allocated. */
          return RetCode.Success ;
       }
       public RetCode cciUnguarded( int startIdx,
                                    int endIdx,
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double tempReal = 0;
          double tempReal2 = 0;
          double theAverage = 0;
          double lastValue = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double[] circBuffer;
          int circBuffer_Idx = 0;
          int maxIdx_circBuffer = (30)-1;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          circBuffer = new double[optInTimePeriod];
          maxIdx_circBuffer = (optInTimePeriod)-1;
          circBuffer_Idx = 0;
          i = startIdx - lookbackTotal;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                circBuffer[circBuffer_Idx] = (inHigh[i] + inLow[i] + inClose[i]) / 3;
                i += 1;
                circBuffer_Idx++;
                if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             }
          }
          outIdx = 0;
          do {
             lastValue = (inHigh[i] + inLow[i] + inClose[i]) / 3;
             circBuffer[circBuffer_Idx] = lastValue;
             theAverage = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                theAverage += circBuffer[j];
             }
             theAverage /= optInTimePeriod;
             tempReal2 = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                tempReal2 += Math.abs(circBuffer[j] - theAverage);
             }
             tempReal = lastValue - theAverage;
             if( tempReal != 0.0 && tempReal2 != 0.0 ) {
                outReal[outIdx++] = tempReal / (0.015 * (tempReal2 / optInTimePeriod));
             } else {
                outReal[outIdx++] = 0.0;
             }
             circBuffer_Idx++;
             if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cci( int startIdx,
                           int endIdx,
                           float inHigh[],
                           float inLow[],
                           float inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double tempReal = 0;
          double tempReal2 = 0;
          double theAverage = 0;
          double lastValue = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double[] circBuffer;
          int circBuffer_Idx = 0;
          int maxIdx_circBuffer = (30)-1;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          circBuffer = new double[optInTimePeriod];
          maxIdx_circBuffer = (optInTimePeriod)-1;
          circBuffer_Idx = 0;
          i = startIdx - lookbackTotal;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                circBuffer[circBuffer_Idx] = (inHigh[i] + inLow[i] + inClose[i]) / 3;
                i += 1;
                circBuffer_Idx++;
                if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             }
          }
          outIdx = 0;
          do {
             lastValue = (inHigh[i] + inLow[i] + inClose[i]) / 3;
             circBuffer[circBuffer_Idx] = lastValue;
             theAverage = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                theAverage += circBuffer[j];
             }
             theAverage /= optInTimePeriod;
             tempReal2 = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                tempReal2 += Math.abs(circBuffer[j] - theAverage);
             }
             tempReal = lastValue - theAverage;
             if( tempReal != 0.0 && tempReal2 != 0.0 ) {
                outReal[outIdx++] = tempReal / (0.015 * (tempReal2 / optInTimePeriod));
             } else {
                outReal[outIdx++] = 0.0;
             }
             circBuffer_Idx++;
             if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cciUnguarded( int startIdx,
                                    int endIdx,
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double tempReal = 0;
          double tempReal2 = 0;
          double theAverage = 0;
          double lastValue = 0;
          int i = 0;
          int j = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double[] circBuffer;
          int circBuffer_Idx = 0;
          int maxIdx_circBuffer = (30)-1;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          circBuffer = new double[optInTimePeriod];
          maxIdx_circBuffer = (optInTimePeriod)-1;
          circBuffer_Idx = 0;
          i = startIdx - lookbackTotal;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                circBuffer[circBuffer_Idx] = (inHigh[i] + inLow[i] + inClose[i]) / 3;
                i += 1;
                circBuffer_Idx++;
                if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             }
          }
          outIdx = 0;
          do {
             lastValue = (inHigh[i] + inLow[i] + inClose[i]) / 3;
             circBuffer[circBuffer_Idx] = lastValue;
             theAverage = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                theAverage += circBuffer[j];
             }
             theAverage /= optInTimePeriod;
             tempReal2 = 0;
             for( j = 0; j < optInTimePeriod; j += 1 ) {
                tempReal2 += Math.abs(circBuffer[j] - theAverage);
             }
             tempReal = lastValue - theAverage;
             if( tempReal != 0.0 && tempReal2 != 0.0 ) {
                outReal[outIdx++] = tempReal / (0.015 * (tempReal2 / optInTimePeriod));
             } else {
                outReal[outIdx++] = 0.0;
             }
             circBuffer_Idx++;
             if( circBuffer_Idx > maxIdx_circBuffer ) { circBuffer_Idx = 0; }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdl2CrowsLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return BodyLong_avgPeriod + 2 ;

       }
       public RetCode cdl2Crows( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl2CrowsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white candle
           * - second candle: black real body
           * - gap between the first and the second candle's real bodies
           * - third candle: black candle that opens within the second real body and closes within the first real body
           * The meaning of "long" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): two crows is always bearish;
           * the user should consider that two crows is significant when it appears in an uptrend, while this function
           * does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 &&     /* 1st: white */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd: black */
                 (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && /* gapping up */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 3rd: black */
                 inOpen[i] < inOpen[i - 1] &&
                 inOpen[i] > inClose[i - 1] &&                               /* opening within 2nd rb */
                 inClose[i] > inOpen[i - 2] &&
                 inClose[i] < inClose[i - 2] )                               /* closing within 1st rb */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl2CrowsUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdl2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 2] && inClose[i] < inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl2Crows( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 2] && inClose[i] < inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl2CrowsUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdl2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 2] && inClose[i] < inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  103004 AC   Creation
     */

       public int cdl3BlackCrowsLookback( )
       {
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return ShadowVeryShort_avgPeriod + 3 ;

       }
       public RetCode cdl3BlackCrows( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3BlackCrowsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three consecutive and declining black candlesticks
           * - each candle must have no or very short lower shadow
           * - each candle after the first must open within the prior candle's real body
           * - the first candle's close should be under the prior white candle's high
           * The meaning of "very short" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): three black crows is always bearish;
           * the user should consider that 3 black crows is significant when it appears after a mature advance or at high levels,
           * while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 1 &&     /* white */
                 ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* 1st black */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 3rd black */
                 inOpen[i - 1] < inOpen[i - 2] &&
                 inOpen[i - 1] > inClose[i - 2] &&                           /* 2nd black opens within 1st black's rb */
                 inOpen[i] < inOpen[i - 1] &&
                 inOpen[i] > inClose[i - 1] &&                               /* 3rd black opens within 2nd black's rb */
                 inHigh[i - 3] > inClose[i - 2] &&                           /* 1st black closes under prior candle's high */
                 inClose[i - 2] > inClose[i - 1] &&                          /* three declining */
                 inClose[i - 1] > inClose[i] &&                              /* three declining */
                 (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short lower shadow */
                 (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short lower shadow */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* very short lower shadow */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3BlackCrowsUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3BlackCrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 1] < inOpen[i - 2] && inOpen[i - 1] > inClose[i - 2] && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inHigh[i - 3] > inClose[i - 2] && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3BlackCrows( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3BlackCrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 1] < inOpen[i - 2] && inOpen[i - 1] > inClose[i - 2] && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inHigh[i - 3] > inClose[i - 2] && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3BlackCrowsUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3BlackCrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 1] < inOpen[i - 2] && inOpen[i - 1] > inClose[i - 2] && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inHigh[i - 3] > inClose[i - 2] && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdl3InsideLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdl3Inside( int startIdx,
                                  int endIdx,
                                  double inOpen[],
                                  double inHigh[],
                                  double inLow[],
                                  double inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3InsideLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white (black) real body
           * - second candle: short real body totally engulfed by the first
           * - third candle: black (white) candle that closes lower (higher) than the first candle's open
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) for the three inside up or negative (-1 to -100) for the three inside down;
           * the user should consider that a three inside up is significant when it appears in a downtrend and a three inside
           * down is significant when it appears in an uptrend, while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && /* engulfed by 1st */
                 Math.min(inClose[i - 1], inOpen[i - 1]) > Math.min(inClose[i - 2], inOpen[i - 2]) &&
                 (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inOpen[i - 2] || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inOpen[i - 2]) && /* 3rd: opposite to 1st and closing out */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 2nd: short */
             {
                outInteger[outIdx++] = (0 - ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3InsideUnguarded( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdl3InsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && Math.min(inClose[i - 1], inOpen[i - 1]) > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inOpen[i - 2] || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inOpen[i - 2]) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3Inside( int startIdx,
                                  int endIdx,
                                  float inOpen[],
                                  float inHigh[],
                                  float inLow[],
                                  float inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3InsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && Math.min(inClose[i - 1], inOpen[i - 1]) > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inOpen[i - 2] || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inOpen[i - 2]) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3InsideUnguarded( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdl3InsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && Math.min(inClose[i - 1], inOpen[i - 1]) > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inOpen[i - 2] || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inOpen[i - 2]) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdl3LineStrikeLookback( )
       {
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          return Near_avgPeriod + 3 ;

       }
       public RetCode cdl3LineStrike( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double[] NearPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3LineStrikeLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          NearPeriodTotal[3] = 0;
          NearPeriodTotal[2] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[3] = NearPeriodTotal[3] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three white soldiers (three black crows): three white (black) candlesticks with consecutively higher (lower) closes,
           * each opening within or near the previous real body
           * - fourth candle: black (white) candle that opens above (below) prior candle's close and closes below (above)
           * the first candle's open
           * The meaning of "near" is specified with TA_SetCandleSettings;
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that 3-line strike is significant when it appears in a trend in the same direction of
           * the first three candles, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && /* three with same color */
                 ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) &&
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && /* 4th opposite color */
                 inOpen[i - 2] >= Math.min(inOpen[i - 3], inClose[i - 3]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd opens within/near 1st rb */
                 inOpen[i - 2] <= Math.max(inOpen[i - 3], inClose[i - 3]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inOpen[i - 1] >= Math.min(inOpen[i - 2], inClose[i - 2]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && /* 3rd opens within/near 2nd rb */
                 inOpen[i - 1] <= Math.max(inOpen[i - 2], inClose[i - 2]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inClose[i - 2] > inClose[i - 3] && inOpen[i] > inClose[i - 1] && inClose[i] < inOpen[i - 3] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] < inClose[i - 2] && inClose[i - 2] < inClose[i - 3] && inOpen[i] < inClose[i - 1] && inClose[i] > inOpen[i - 3]) ) /* if three white consecutive higher closes 4th opens above prior close 4th closes below 1st open if three black consecutive lower closes 4th opens below prior close 4th closes above 1st open */
             {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 3; totIdx >= 2; totIdx -= 1 ) {
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3LineStrikeUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double[] NearPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdl3LineStrikeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal[3] = 0;
          NearPeriodTotal[2] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[3] = NearPeriodTotal[3] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && inOpen[i - 2] >= Math.min(inOpen[i - 3], inClose[i - 3]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 2] <= Math.max(inOpen[i - 3], inClose[i - 3]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= Math.min(inOpen[i - 2], inClose[i - 2]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] <= Math.max(inOpen[i - 2], inClose[i - 2]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inClose[i - 2] > inClose[i - 3] && inOpen[i] > inClose[i - 1] && inClose[i] < inOpen[i - 3] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] < inClose[i - 2] && inClose[i - 2] < inClose[i - 3] && inOpen[i] < inClose[i - 1] && inClose[i] > inOpen[i - 3]) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 2; totIdx -= 1 ) {
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3LineStrike( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double[] NearPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3LineStrikeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal[3] = 0;
          NearPeriodTotal[2] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[3] = NearPeriodTotal[3] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && inOpen[i - 2] >= Math.min(inOpen[i - 3], inClose[i - 3]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 2] <= Math.max(inOpen[i - 3], inClose[i - 3]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= Math.min(inOpen[i - 2], inClose[i - 2]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] <= Math.max(inOpen[i - 2], inClose[i - 2]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inClose[i - 2] > inClose[i - 3] && inOpen[i] > inClose[i - 1] && inClose[i] < inOpen[i - 3] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] < inClose[i - 2] && inClose[i - 2] < inClose[i - 3] && inOpen[i] < inClose[i - 1] && inClose[i] > inOpen[i - 3]) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 2; totIdx -= 1 ) {
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3LineStrikeUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double[] NearPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdl3LineStrikeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal[3] = 0;
          NearPeriodTotal[2] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[3] = NearPeriodTotal[3] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && inOpen[i - 2] >= Math.min(inOpen[i - 3], inClose[i - 3]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 2] <= Math.max(inOpen[i - 3], inClose[i - 3]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[3] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((Near_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((Near_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= Math.min(inOpen[i - 2], inClose[i - 2]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] <= Math.max(inOpen[i - 2], inClose[i - 2]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inClose[i - 2] > inClose[i - 3] && inOpen[i] > inClose[i - 1] && inClose[i] < inOpen[i - 3] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] < inClose[i - 2] && inClose[i - 2] < inClose[i - 3] && inOpen[i] < inClose[i - 1] && inClose[i] > inOpen[i - 3]) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 2; totIdx -= 1 ) {
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdl3OutsideLookback( )
       {
          return 3 ;

       }
       public RetCode cdl3Outside( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3OutsideLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first: black (white) real body
           * - second: white (black) real body that engulfs the prior real body
           * - third: candle that closes higher (lower) than the second candle
           * outInteger is positive (1 to 100) for the three outside up or negative (-1 to -100) for the three outside down;
           * the user should consider that a three outside up must appear in a downtrend and three outside down must appear
           * in an uptrend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] > inOpen[i - 2] && inOpen[i - 1] < inClose[i - 2] && inClose[i] > inClose[i - 1] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && inOpen[i - 1] > inClose[i - 2] && inClose[i - 1] < inOpen[i - 2] && inClose[i] < inClose[i - 1] ) {
                /* white engulfs black */
                /* third candle higher */
                /* black engulfs white */
                /* third candle lower */
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3OutsideUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdl3OutsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] > inOpen[i - 2] && inOpen[i - 1] < inClose[i - 2] && inClose[i] > inClose[i - 1] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && inOpen[i - 1] > inClose[i - 2] && inClose[i - 1] < inOpen[i - 2] && inClose[i] < inClose[i - 1] ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3Outside( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3OutsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] > inOpen[i - 2] && inOpen[i - 1] < inClose[i - 2] && inClose[i] > inClose[i - 1] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && inOpen[i - 1] > inClose[i - 2] && inClose[i - 1] < inOpen[i - 2] && inClose[i] < inClose[i - 1] ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3OutsideUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdl3OutsideLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inClose[i - 1] > inOpen[i - 2] && inOpen[i - 1] < inClose[i - 2] && inClose[i] > inClose[i - 1] || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && inOpen[i - 1] > inClose[i - 2] && inClose[i - 1] < inOpen[i - 2] && inClose[i] < inClose[i - 1] ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  022705 AC   Creation
     */

       public int cdl3StarsInSouthLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(ShadowVeryShort_avgPeriod, ShadowLong_avgPeriod), Math.max(BodyLong_avgPeriod, BodyShort_avgPeriod)) + 2 ;

       }
       public RetCode cdl3StarsInSouth( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double[] ShadowVeryShortPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3StarsInSouthLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle with long lower shadow
           * - second candle: smaller black candle that opens higher than prior close but within prior candle's range
           *   and trades lower than prior close but not lower than prior low and closes off of its low (it has a shadow)
           * - third candle: small black marubozu (or candle with very short shadows) engulfed by prior candle's range
           * The meanings of "long body", "short body", "very short shadow" are specified with TA_SetCandleSettings;
           * outInteger is positive (1 to 100): 3 stars in the south is always bullish;
           * the user should consider that 3 stars in the south is significant when it appears in downtrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* 1st black */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 3rd black */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* with long lower shadow */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && /* 2nd: smaller candle */
                 inOpen[i - 1] > inClose[i - 2] &&
                 inOpen[i - 1] <= inHigh[i - 2] &&                           /* that opens higher but within 1st range */
                 inLow[i - 1] < inClose[i - 2] &&                            /* and trades lower than 1st close */
                 inLow[i - 1] >= inLow[i - 2] &&                             /* but not lower than 1st low */
                 (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* and has a lower shadow */
                 Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 3rd: small marubozu */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inLow[i] > inLow[i - 1] &&
                 inHigh[i] < inHigh[i - 1] )                                 /* engulfed by prior candle's range */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) - Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3StarsInSouthUnguarded( int startIdx,
                                                 int endIdx,
                                                 double inOpen[],
                                                 double inHigh[],
                                                 double inLow[],
                                                 double inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double[] ShadowVeryShortPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3StarsInSouthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && inOpen[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inHigh[i - 2] && inLow[i - 1] < inClose[i - 2] && inLow[i - 1] >= inLow[i - 2] && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inLow[i] > inLow[i - 1] && inHigh[i] < inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) - Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3StarsInSouth( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double[] ShadowVeryShortPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3StarsInSouthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && inOpen[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inHigh[i - 2] && inLow[i - 1] < inClose[i - 2] && inLow[i - 1] >= inLow[i - 2] && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inLow[i] > inLow[i - 1] && inHigh[i] < inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) - Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3StarsInSouthUnguarded( int startIdx,
                                                 int endIdx,
                                                 float inOpen[],
                                                 float inHigh[],
                                                 float inLow[],
                                                 float inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double[] ShadowVeryShortPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3StarsInSouthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && inOpen[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inHigh[i - 2] && inLow[i - 1] < inClose[i - 2] && inLow[i - 1] >= inLow[i - 2] && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inLow[i] > inLow[i - 1] && inHigh[i] < inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - 2] - inLow[ShadowLongTrailingIdx - 2]) - Math.abs(inClose[ShadowLongTrailingIdx - 2] - inOpen[ShadowLongTrailingIdx - 2])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120404 AC   Creation
     */

       public int cdl3WhiteSoldiersLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(ShadowVeryShort_avgPeriod, BodyShort_avgPeriod), Math.max(Far_avgPeriod, Near_avgPeriod)) + 2 ;

       }
       public RetCode cdl3WhiteSoldiers( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdl3WhiteSoldiersLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three white candlesticks with consecutively higher closes
           * - Greg Morris wants them to be long, Steve Nison doesn't; anyway they should not be short
           * - each candle opens within or near the previous white real body
           * - each candle must have no or very short upper shadow
           * - to differentiate this pattern from advance block, each candle must not be far shorter than the prior candle
           * The meanings of "not short", "very short shadow", "far" and "near" are specified with TA_SetCandleSettings;
           * here the 3 candles must be not short, if you want them to be long use TA_SetCandleSettings on BodyShort;
           * outInteger is positive (1 to 100): advancing 3 white soldiers is always bullish;
           * the user should consider that 3 white soldiers is significant when it appears in downtrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && /* 1st white */
                 (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && /* very short upper shadow 2nd white */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&         /* very short upper shadow 3rd white */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inClose[i] > inClose[i - 1] &&                          /* very short upper shadow */
                 inClose[i - 1] > inClose[i - 2] &&                      /* consecutive higher closes */
                 inOpen[i - 1] > inOpen[i - 2] &&                        /* 2nd opens within/near 1st real body */
                 inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inOpen[i] > inOpen[i - 1] &&                            /* 3rd opens within/near 2nd real body */
                 inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd not far shorter than 1st */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd not far shorter than 2nd not short real body */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3WhiteSoldiersUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3WhiteSoldiersLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3WhiteSoldiers( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdl3WhiteSoldiersLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdl3WhiteSoldiersUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdl3WhiteSoldiersLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102304 AC   Creation
     */

       public int cdlAbandonedBabyLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(Math.max(BodyDoji_avgPeriod, BodyLong_avgPeriod), BodyShort_avgPeriod) + 2 ;

       }
       public RetCode cdlAbandonedBaby( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        double optInPenetration,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlAbandonedBabyLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white (black) real body
           * - second candle: doji
           * - third candle: black (white) real body that moves well within the first candle's real body
           * - upside (downside) gap between the first candle and the doji (the shadows of the two candles don't touch)
           * - downside (upside) gap between the doji and the third candle (the shadows of the two candles don't touch)
           * The meaning of "doji" and "long" is specified with TA_SetCandleSettings
           * The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
           * not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
           * it to be relatively long
           * outInteger is positive (1 to 100) when it's an abandoned baby bottom or negative (-1 to -100) when it's
           * an abandoned baby top; the user should consider that an abandoned baby is significant when it appears in
           * an uptrend or downtrend, while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: doji */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 3rd: longer than short */
                 (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inLow[i - 1] > inHigh[i - 2]) && (inHigh[i] < inLow[i - 1]) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inHigh[i - 1] < inLow[i - 2]) && (inLow[i] > inHigh[i - 1])) ) /* 1st white 3rd black 3rd closes well within 1st rb upside gap between 1st and 2nd downside gap between 2nd and 3rd 1st black 3rd white 3rd closes well within 1st rb downside gap between 1st and 2nd upside gap between 2nd and 3rd */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAbandonedBabyUnguarded( int startIdx,
                                                 int endIdx,
                                                 double inOpen[],
                                                 double inHigh[],
                                                 double inLow[],
                                                 double inClose[],
                                                 double optInPenetration,
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlAbandonedBabyLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inLow[i - 1] > inHigh[i - 2]) && (inHigh[i] < inLow[i - 1]) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inHigh[i - 1] < inLow[i - 2]) && (inLow[i] > inHigh[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAbandonedBaby( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        double optInPenetration,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlAbandonedBabyLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inLow[i - 1] > inHigh[i - 2]) && (inHigh[i] < inLow[i - 1]) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inHigh[i - 1] < inLow[i - 2]) && (inLow[i] > inHigh[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAbandonedBabyUnguarded( int startIdx,
                                                 int endIdx,
                                                 float inOpen[],
                                                 float inHigh[],
                                                 float inLow[],
                                                 float inClose[],
                                                 double optInPenetration,
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlAbandonedBabyLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inLow[i - 1] > inHigh[i - 2]) && (inHigh[i] < inLow[i - 1]) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && (inHigh[i - 1] < inLow[i - 2]) && (inLow[i] > inHigh[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120404 AC   Creation
     */

       public int cdlAdvanceBlockLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          return Math.max(Math.max(Math.max(ShadowLong_avgPeriod, ShadowShort_avgPeriod), Math.max(Far_avgPeriod, Near_avgPeriod)), BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdlAdvanceBlock( int startIdx,
                                       int endIdx,
                                       double inOpen[],
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double[] ShadowShortPeriodTotal = new double[3];
          double[] ShadowLongPeriodTotal = new double[2];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlAdvanceBlockLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowShortPeriodTotal[2] = 0;
          ShadowShortPeriodTotal[1] = 0;
          ShadowShortPeriodTotal[0] = 0;
          ShadowShortTrailingIdx = startIdx - ShadowShort_avgPeriod;
          ShadowLongPeriodTotal[1] = 0;
          ShadowLongPeriodTotal[0] = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowShortTrailingIdx;
          while( i < startIdx ) {
             ShadowShortPeriodTotal[2] = ShadowShortPeriodTotal[2] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowShortPeriodTotal[1] = ShadowShortPeriodTotal[1] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowShortPeriodTotal[0] = ShadowShortPeriodTotal[0] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal[1] = ShadowLongPeriodTotal[1] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowLongPeriodTotal[0] = ShadowLongPeriodTotal[0] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three white candlesticks with consecutively higher closes
           * - each candle opens within or near the previous white real body
           * - first candle: long white with no or very short upper shadow (a short shadow is accepted too for more flexibility)
           * - second and third candles, or only third candle, show signs of weakening: progressively smaller white real bodies
           * and/or relatively long upper shadows; see below for specific conditions
           * The meanings of "long body", "short shadow", "far" and "near" are specified with TA_SetCandleSettings;
           * outInteger is negative (-1 to -100): advance block is always bearish;
           * the user should consider that advance block is significant when it appears in uptrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && /* 1st white */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && /* 2nd white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&         /* 3rd white */
                 inClose[i] > inClose[i - 1] &&
                 inClose[i - 1] > inClose[i - 2] &&                      /* consecutive higher closes */
                 inOpen[i - 1] > inOpen[i - 2] &&                        /* 2nd opens within/near 1st real body */
                 inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inOpen[i] > inOpen[i - 1] &&                            /* 3rd opens within/near 2nd real body */
                 inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long real body */
                 (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[2] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && ((inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[0] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[1] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0))))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal[0] / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) /* 1st: short upper shadow ( 2 far smaller than 1 && 3 not longer than 2 ) advance blocked with the 2nd, 3rd must not carry on the advance 3 far smaller than 2 advance blocked with the 3rd ( 3 smaller than 2 && 2 smaller than 1 && (3 or 2 not short upper shadow) ) advance blocked with progressively smaller real bodies and some upper shadows ( 3 smaller than 2 && 3 long upper shadow ) advance blocked with 3rd candle's long upper shadow and smaller body */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowShortPeriodTotal[totIdx] = ShadowShortPeriodTotal[totIdx] + (((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowLongPeriodTotal[totIdx] = ShadowLongPeriodTotal[totIdx] + (((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) - Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             i += 1;
             ShadowShortTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAdvanceBlockUnguarded( int startIdx,
                                                int endIdx,
                                                double inOpen[],
                                                double inHigh[],
                                                double inLow[],
                                                double inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double[] ShadowShortPeriodTotal = new double[3];
          double[] ShadowLongPeriodTotal = new double[2];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlAdvanceBlockLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowShortPeriodTotal[2] = 0;
          ShadowShortPeriodTotal[1] = 0;
          ShadowShortPeriodTotal[0] = 0;
          ShadowShortTrailingIdx = startIdx - ShadowShort_avgPeriod;
          ShadowLongPeriodTotal[1] = 0;
          ShadowLongPeriodTotal[0] = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowShortTrailingIdx;
          while( i < startIdx ) {
             ShadowShortPeriodTotal[2] = ShadowShortPeriodTotal[2] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowShortPeriodTotal[1] = ShadowShortPeriodTotal[1] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowShortPeriodTotal[0] = ShadowShortPeriodTotal[0] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal[1] = ShadowLongPeriodTotal[1] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowLongPeriodTotal[0] = ShadowLongPeriodTotal[0] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[2] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && ((inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[0] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[1] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0))))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal[0] / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowShortPeriodTotal[totIdx] = ShadowShortPeriodTotal[totIdx] + (((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowLongPeriodTotal[totIdx] = ShadowLongPeriodTotal[totIdx] + (((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) - Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             i += 1;
             ShadowShortTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAdvanceBlock( int startIdx,
                                       int endIdx,
                                       float inOpen[],
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double[] ShadowShortPeriodTotal = new double[3];
          double[] ShadowLongPeriodTotal = new double[2];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlAdvanceBlockLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowShortPeriodTotal[2] = 0;
          ShadowShortPeriodTotal[1] = 0;
          ShadowShortPeriodTotal[0] = 0;
          ShadowShortTrailingIdx = startIdx - ShadowShort_avgPeriod;
          ShadowLongPeriodTotal[1] = 0;
          ShadowLongPeriodTotal[0] = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowShortTrailingIdx;
          while( i < startIdx ) {
             ShadowShortPeriodTotal[2] = ShadowShortPeriodTotal[2] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowShortPeriodTotal[1] = ShadowShortPeriodTotal[1] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowShortPeriodTotal[0] = ShadowShortPeriodTotal[0] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal[1] = ShadowLongPeriodTotal[1] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowLongPeriodTotal[0] = ShadowLongPeriodTotal[0] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[2] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && ((inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[0] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[1] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0))))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal[0] / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowShortPeriodTotal[totIdx] = ShadowShortPeriodTotal[totIdx] + (((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowLongPeriodTotal[totIdx] = ShadowLongPeriodTotal[totIdx] + (((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) - Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             i += 1;
             ShadowShortTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlAdvanceBlockUnguarded( int startIdx,
                                                int endIdx,
                                                float inOpen[],
                                                float inHigh[],
                                                float inLow[],
                                                float inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double[] ShadowShortPeriodTotal = new double[3];
          double[] ShadowLongPeriodTotal = new double[2];
          double[] NearPeriodTotal = new double[3];
          double[] FarPeriodTotal = new double[3];
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowShortTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int FarTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Far_rangeType = this.candleSettings[CandleSettingType.Far.ordinal()].rangeType.ordinal();
          int Far_avgPeriod = this.candleSettings[CandleSettingType.Far.ordinal()].avgPeriod;
          double Far_factor = this.candleSettings[CandleSettingType.Far.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlAdvanceBlockLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowShortPeriodTotal[2] = 0;
          ShadowShortPeriodTotal[1] = 0;
          ShadowShortPeriodTotal[0] = 0;
          ShadowShortTrailingIdx = startIdx - ShadowShort_avgPeriod;
          ShadowLongPeriodTotal[1] = 0;
          ShadowLongPeriodTotal[0] = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          FarPeriodTotal[2] = 0;
          FarPeriodTotal[1] = 0;
          FarPeriodTotal[0] = 0;
          FarTrailingIdx = startIdx - Far_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowShortTrailingIdx;
          while( i < startIdx ) {
             ShadowShortPeriodTotal[2] = ShadowShortPeriodTotal[2] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowShortPeriodTotal[1] = ShadowShortPeriodTotal[1] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowShortPeriodTotal[0] = ShadowShortPeriodTotal[0] + ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal[1] = ShadowLongPeriodTotal[1] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowLongPeriodTotal[0] = ShadowLongPeriodTotal[0] + ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = FarTrailingIdx;
          while( i < startIdx ) {
             FarPeriodTotal[2] = FarPeriodTotal[2] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             FarPeriodTotal[1] = FarPeriodTotal[1] + ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[2] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[2] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Far_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Far_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Far_factor * (((Far_avgPeriod != 0) ? (FarPeriodTotal[1] / Far_avgPeriod) : ((Far_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Far_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Far_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Far_rangeType == 2) ? 2.0 : 1.0)))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < Math.abs(inClose[i - 2] - inOpen[i - 2]) && ((inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[0] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowShortPeriodTotal[1] / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0))))) || Math.abs(inClose[i] - inOpen[i]) < Math.abs(inClose[i - 1] - inOpen[i - 1]) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal[0] / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowShortPeriodTotal[totIdx] = ShadowShortPeriodTotal[totIdx] + (((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowShortTrailingIdx - totIdx] - inLow[ShadowShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowShortTrailingIdx - totIdx] - inOpen[ShadowShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                ShadowLongPeriodTotal[totIdx] = ShadowLongPeriodTotal[totIdx] + (((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx - totIdx] - inLow[ShadowLongTrailingIdx - totIdx]) - Math.abs(inClose[ShadowLongTrailingIdx - totIdx] - inOpen[ShadowLongTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                FarPeriodTotal[totIdx] = FarPeriodTotal[totIdx] + (((Far_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Far_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Far_rangeType == 0) ? (Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : ((Far_rangeType == 1) ? (inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) : ((Far_rangeType == 2) ? ((inHigh[FarTrailingIdx - totIdx] - inLow[FarTrailingIdx - totIdx]) - Math.abs(inClose[FarTrailingIdx - totIdx] - inOpen[FarTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 2] - inLow[BodyLongTrailingIdx - 2]) - Math.abs(inClose[BodyLongTrailingIdx - 2] - inOpen[BodyLongTrailingIdx - 2])) : 0.0)));
             i += 1;
             ShadowShortTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
             FarTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010605 AC   Creation
     */

       public int cdlBeltHoldLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(BodyLong_avgPeriod, ShadowVeryShort_avgPeriod) ;

       }
       public RetCode cdlBeltHold( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlBeltHoldLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - long white (black) real body
           * - no or very short lower (upper) shadow
           * The meaning of "long" and "very short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white (bullish), negative (-1 to -100) when black (bearish)
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long body */
                 (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) /* white body and very short lower shadow black body and very short upper shadow */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBeltHoldUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlBeltHoldLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBeltHold( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlBeltHoldLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBeltHoldUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlBeltHoldLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlBreakawayLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return BodyLong_avgPeriod + 4 ;

       }
       public RetCode cdlBreakaway( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlBreakawayLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black (white)
           * - second candle: black (white) day whose body gaps down (up)
           * - third candle: black or white day with lower (higher) high and lower (higher) low than prior candle's
           * - fourth candle: black (white) day with lower (higher) high and lower (higher) low than prior candle's
           * - fifth candle: white (black) day that closes inside the gap, erasing the prior 3 days
           * The meaning of "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that breakaway is significant in a trend opposite to the last candle, while this
           * function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && /* 1st, 2nd, 4th same color, 5th opposite */
                 ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) &&
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) &&
                 Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st long */
                 (((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 3], inClose[i - 3]) < Math.min(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] < inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] < inLow[i - 2] && inClose[i] > inOpen[i - 3] && inClose[i] < inClose[i - 4] || ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] > inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] > inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && inClose[i] < inOpen[i - 3] && inClose[i] > inClose[i - 4]) ) /* when 1st is black: 2nd gaps down 3rd has lower high and low than 2nd 4th has lower high and low than 3rd 5th closes inside the gap when 1st is white: 2nd gaps up 3rd has higher high and low than 2nd 4th has higher high and low than 3rd 5th closes inside the gap */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBreakawayUnguarded( int startIdx,
                                             int endIdx,
                                             double inOpen[],
                                             double inHigh[],
                                             double inLow[],
                                             double inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlBreakawayLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 3], inClose[i - 3]) < Math.min(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] < inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] < inLow[i - 2] && inClose[i] > inOpen[i - 3] && inClose[i] < inClose[i - 4] || ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] > inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] > inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && inClose[i] < inOpen[i - 3] && inClose[i] > inClose[i - 4]) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBreakaway( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlBreakawayLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 3], inClose[i - 3]) < Math.min(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] < inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] < inLow[i - 2] && inClose[i] > inOpen[i - 3] && inClose[i] < inClose[i - 4] || ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] > inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] > inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && inClose[i] < inOpen[i - 3] && inClose[i] > inClose[i - 4]) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlBreakawayUnguarded( int startIdx,
                                             int endIdx,
                                             float inOpen[],
                                             float inHigh[],
                                             float inLow[],
                                             float inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlBreakawayLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 3], inClose[i - 3]) < Math.min(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] < inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] < inLow[i - 2] && inClose[i] > inOpen[i - 3] && inClose[i] < inClose[i - 4] || ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && inHigh[i - 2] > inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] > inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && inClose[i] < inOpen[i - 3] && inClose[i] > inClose[i - 4]) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  022005 AC   Creation
     */

       public int cdlClosingMarubozuLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(BodyLong_avgPeriod, ShadowVeryShort_avgPeriod) ;

       }
       public RetCode cdlClosingMarubozu( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlClosingMarubozuLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - long white (black) real body
           * - no or very short upper (lower) shadow
           * The meaning of "long" and "very short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white (bullish), negative (-1 to -100) when black (bearish)
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long body */
                 (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) /* white body and very short lower shadow black body and very short upper shadow */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlClosingMarubozuUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlClosingMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlClosingMarubozu( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlClosingMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlClosingMarubozuUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlClosingMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  022705 AC   Creation
     */

       public int cdlConcealBabysWallLookback( )
       {
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return ShadowVeryShort_avgPeriod + 3 ;

       }
       public RetCode cdlConcealBabysWall( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlConcealBabysWallLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[3] = 0;
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[3] = ShadowVeryShortPeriodTotal[3] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: black marubozu (very short shadows)
           * - second candle: black marubozu (very short shadows)
           * - third candle: black candle that opens gapping down but has an upper shadow that extends into the prior body
           * - fourth candle: black candle that completely engulfs the third candle, including the shadows
           * The meanings of "very short shadow" are specified with TA_SetCandleSettings;
           * outInteger is positive (1 to 100): concealing baby swallow is always bullish;
           * the user should consider that concealing baby swallow is significant when it appears in downtrend, while
           * this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && /* 1st black */
                 ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd black */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 3rd black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 4th black */
                 (((inClose[i - 3] >= inOpen[i - 3]) ? inOpen[i - 3] : inClose[i - 3]) - inLow[i - 3]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: marubozu */
                 (inHigh[i - 3] - ((inClose[i - 3] >= inOpen[i - 3]) ? inClose[i - 3] : inOpen[i - 3])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: marubozu */
                 (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && /* 3rd: opens gapping down */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* and HAS an upper shadow */
                 inHigh[i - 1] > inClose[i - 2] &&                           /* that extends into the prior body */
                 inHigh[i] > inHigh[i - 1] &&
                 inLow[i] < inLow[i - 1] )                                   /* 4th: engulfs the 3rd including the shadows */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlConcealBabysWallUnguarded( int startIdx,
                                                    int endIdx,
                                                    double inOpen[],
                                                    double inHigh[],
                                                    double inLow[],
                                                    double inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlConcealBabysWallLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[3] = 0;
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[3] = ShadowVeryShortPeriodTotal[3] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 3] >= inOpen[i - 3]) ? inOpen[i - 3] : inClose[i - 3]) - inLow[i - 3]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 3] - ((inClose[i - 3] >= inOpen[i - 3]) ? inClose[i - 3] : inOpen[i - 3])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inHigh[i - 1] > inClose[i - 2] && inHigh[i] > inHigh[i - 1] && inLow[i] < inLow[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlConcealBabysWall( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlConcealBabysWallLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[3] = 0;
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[3] = ShadowVeryShortPeriodTotal[3] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 3] >= inOpen[i - 3]) ? inOpen[i - 3] : inClose[i - 3]) - inLow[i - 3]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 3] - ((inClose[i - 3] >= inOpen[i - 3]) ? inClose[i - 3] : inOpen[i - 3])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inHigh[i - 1] > inClose[i - 2] && inHigh[i] > inHigh[i - 1] && inLow[i] < inLow[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlConcealBabysWallUnguarded( int startIdx,
                                                    int endIdx,
                                                    float inOpen[],
                                                    float inHigh[],
                                                    float inLow[],
                                                    float inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[4];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlConcealBabysWallLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[3] = 0;
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[3] = ShadowVeryShortPeriodTotal[3] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 3] >= inOpen[i - 3]) ? inOpen[i - 3] : inClose[i - 3]) - inLow[i - 3]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 3] - ((inClose[i - 3] >= inOpen[i - 3]) ? inClose[i - 3] : inOpen[i - 3])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[3] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 2] - ((inClose[i - 2] >= inOpen[i - 2]) ? inClose[i - 2] : inOpen[i - 2])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inHigh[i - 1] > inClose[i - 2] && inHigh[i] > inHigh[i - 1] && inLow[i] < inLow[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010605 AC   Creation
     */

       public int cdlCounterAttackLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Math.max(Equal_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlCounterAttack( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlCounterAttackLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black (white)
           * - second candle: long white (black) with close equal to the prior close
           * The meaning of "equal" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that counterattack is significant in a trend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && /* opposite candles */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st long */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd long */
                 inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* equal closes */
                 inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlCounterAttackUnguarded( int startIdx,
                                                 int endIdx,
                                                 double inOpen[],
                                                 double inHigh[],
                                                 double inLow[],
                                                 double inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlCounterAttackLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlCounterAttack( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlCounterAttackLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlCounterAttackUnguarded( int startIdx,
                                                 int endIdx,
                                                 float inOpen[],
                                                 float inHigh[],
                                                 float inLow[],
                                                 float inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlCounterAttackLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120904 AC   Creation
     */

       public int cdlDarkCloudCoverLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return BodyLong_avgPeriod + 1 ;

       }
       public RetCode cdlDarkCloudCover( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         double optInPenetration,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlDarkCloudCoverLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white candle
           * - second candle: black candle that opens above previous day high and closes within previous day real body;
           * Greg Morris wants the close to be below the midpoint of the previous real body
           * The meaning of "long" is specified with TA_SetCandleSettings, the penetration of the first real body is specified
           * with optInPenetration
           * outInteger is negative (-1 to -100): dark cloud cover is always bearish
           * the user should consider that a dark cloud cover is significant when it appears in an uptrend, while
           * this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && /* 1st: white */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&     /* 2nd: black */
                 inOpen[i] > inHigh[i - 1] &&                            /* open above prior high */
                 inClose[i] > inOpen[i - 1] &&                           /* close within prior body */
                 inClose[i] < inClose[i - 1] - Math.abs(inClose[i - 1] - inOpen[i - 1]) * optInPenetration )
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDarkCloudCoverUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  double optInPenetration,
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlDarkCloudCoverLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inHigh[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] - Math.abs(inClose[i - 1] - inOpen[i - 1]) * optInPenetration ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDarkCloudCover( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         double optInPenetration,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlDarkCloudCoverLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inHigh[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] - Math.abs(inClose[i - 1] - inOpen[i - 1]) * optInPenetration ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDarkCloudCoverUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  double optInPenetration,
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlDarkCloudCoverLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inHigh[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] - Math.abs(inClose[i - 1] - inOpen[i - 1]) * optInPenetration ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlDojiLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          return BodyDoji_avgPeriod ;

       }
       public RetCode cdlDoji( int startIdx,
                               int endIdx,
                               double inOpen[],
                               double inHigh[],
                               double inLow[],
                               double inClose[],
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlDojiLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - open quite equal to close
           * How much can be the maximum distance between open and close is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: doji shows uncertainty and it is
           * neither bullish nor bearish when considered alone
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDojiUnguarded( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          lookbackTotal = cdlDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDoji( int startIdx,
                               int endIdx,
                               float inOpen[],
                               float inHigh[],
                               float inLow[],
                               float inClose[],
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDojiUnguarded( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          lookbackTotal = cdlDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  100204 AC   Creation
     */

       public int cdlDojiStarLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return Math.max(BodyDoji_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlDojiStar( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlDojiStarLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long real body
           * - second candle: star (open gapping up in an uptrend or down in a downtrend) with a doji
           * The meaning of "doji" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * it's defined bullish when the long candle is white and the star gaps up, bearish when the long candle
           * is black and the star gaps down; the user should consider that a doji star is bullish when it appears
           * in an uptrend and it's bearish when it appears in a downtrend, so to determine the bullishness or
           * bearishness of the pattern the trend must be analyzed
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long real body */
                 Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: doji */
                 (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1]))) ) /* that gaps up if 1st is white or down if 1st is black */
             {
                outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDojiStarUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlDojiStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1]))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDojiStar( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlDojiStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1]))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDojiStarUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlDojiStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1]))) ) {
                outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlDragonflyDojiLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(BodyDoji_avgPeriod, ShadowVeryShort_avgPeriod) ;

       }
       public RetCode cdlDragonflyDoji( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlDragonflyDojiLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - doji body
           * - open and close at the high of the day = no or very short upper shadow
           * - lower shadow (to distinguish from other dojis, here lower shadow should not be very short)
           * The meaning of "doji" and "very short" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: dragonfly doji must be considered
           * relatively to the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDragonflyDojiUnguarded( int startIdx,
                                                 int endIdx,
                                                 double inOpen[],
                                                 double inHigh[],
                                                 double inLow[],
                                                 double inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlDragonflyDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDragonflyDoji( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlDragonflyDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlDragonflyDojiUnguarded( int startIdx,
                                                 int endIdx,
                                                 float inOpen[],
                                                 float inHigh[],
                                                 float inLow[],
                                                 float inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlDragonflyDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102404 AC   Creation
     *  040309 AC   Increased flexibility to allow real bodies matching
     *              on one end (Greg Morris - "Candlestick charting explained")
     */

       public int cdlEngulfingLookback( )
       {
          return 2 ;

       }
       public RetCode cdlEngulfing( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlEngulfingLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first: black (white) real body
           * - second: white (black) real body that engulfs the prior real body
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish:
           * - 100 is returned when the second candle's real body begins before and ends after the first candle's real body
           * - 80 is returned when the two real bodies match on one end (Greg Morris contemplate this case in his book
           *   "Candlestick charting explained")
           * The user should consider that an engulfing must appear in a downtrend if bullish or in an uptrend if bearish,
           * while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inClose[i] >= inOpen[i - 1] && inOpen[i] < inClose[i - 1] || inClose[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1]) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inOpen[i] >= inClose[i - 1] && inClose[i] < inOpen[i - 1] || inOpen[i] > inClose[i - 1] && inClose[i] <= inOpen[i - 1]) ) {
                /* white engulfs black */
                /* black engulfs white */
                if( inOpen[i] != inClose[i - 1] && inClose[i] != inOpen[i - 1] ) {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
                } else {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 80;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEngulfingUnguarded( int startIdx,
                                             int endIdx,
                                             double inOpen[],
                                             double inHigh[],
                                             double inLow[],
                                             double inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdlEngulfingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inClose[i] >= inOpen[i - 1] && inOpen[i] < inClose[i - 1] || inClose[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1]) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inOpen[i] >= inClose[i - 1] && inClose[i] < inOpen[i - 1] || inOpen[i] > inClose[i - 1] && inClose[i] <= inOpen[i - 1]) ) {
                if( inOpen[i] != inClose[i - 1] && inClose[i] != inOpen[i - 1] ) {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
                } else {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 80;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEngulfing( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlEngulfingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inClose[i] >= inOpen[i - 1] && inOpen[i] < inClose[i - 1] || inClose[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1]) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inOpen[i] >= inClose[i - 1] && inClose[i] < inOpen[i - 1] || inOpen[i] > inClose[i - 1] && inClose[i] <= inOpen[i - 1]) ) {
                if( inOpen[i] != inClose[i - 1] && inClose[i] != inOpen[i - 1] ) {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
                } else {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 80;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEngulfingUnguarded( int startIdx,
                                             int endIdx,
                                             float inOpen[],
                                             float inHigh[],
                                             float inLow[],
                                             float inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdlEngulfingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inClose[i] >= inOpen[i - 1] && inOpen[i] < inClose[i - 1] || inClose[i] > inOpen[i - 1] && inOpen[i] <= inClose[i - 1]) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inOpen[i] >= inClose[i - 1] && inClose[i] < inOpen[i - 1] || inOpen[i] > inClose[i - 1] && inClose[i] <= inOpen[i - 1]) ) {
                if( inOpen[i] != inClose[i - 1] && inClose[i] != inOpen[i - 1] ) {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
                } else {
                   outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 80;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  100304 AC   Creation
     */

       public int cdlEveningDojiStarLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(Math.max(BodyDoji_avgPeriod, BodyLong_avgPeriod), BodyShort_avgPeriod) + 2 ;

       }
       public RetCode cdlEveningDojiStar( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          double optInPenetration,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlEveningDojiStarLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white real body
           * - second candle: doji gapping up
           * - third candle: black real body that moves well within the first candle's real body
           * The meaning of "doji" and "long" is specified with TA_SetCandleSettings
           * The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
           * not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
           * it to be relatively long
           * outInteger is negative (-1 to -100): evening star is always bearish;
           * the user should consider that an evening star is significant when it appears in an uptrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && /* white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&     /* black real body */
                 (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && /* gapping up */
                 inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && /* closing well within 1st rb */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: doji */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd: longer than short */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningDojiStarUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   double optInPenetration,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlEveningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningDojiStar( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          double optInPenetration,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlEveningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningDojiStarUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   double optInPenetration,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlEveningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  100304 AC   Creation
     */

       public int cdlEveningStarLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdlEveningStar( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      double optInPenetration,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlEveningStarLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white real body
           * - second candle: star (short real body gapping up)
           * - third candle: black real body that moves well within the first candle's real body
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
           * not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
           * it to be relatively long
           * outInteger is negative (-1 to -100): evening star is always bearish;
           * the user should consider that an evening star is significant when it appears in an uptrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && /* white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&     /* black real body */
                 (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && /* gapping up */
                 inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && /* closing well within 1st rb */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: short */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd: longer than short */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningStarUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               double optInPenetration,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlEveningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningStar( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      double optInPenetration,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlEveningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlEveningStarUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               double optInPenetration,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlEveningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && inClose[i] < inClose[i - 2] - Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  020605 AC   Creation
     */

       public int cdlGapSideSideWhiteLookback( )
       {
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          return Math.max(Near_avgPeriod, Equal_avgPeriod) + 2 ;

       }
       public RetCode cdlGapSideSideWhite( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double NearPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlGapSideSideWhiteLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          NearPeriodTotal = 0;
          EqualPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - upside or downside gap (between the bodies)
           * - first candle after the window: white candlestick
           * - second candle after the window: white candlestick with similar size (near the same) and about the same
           *   open (equal) of the previous candle
           * - the second candle does not close the window
           * The meaning of "near" and "equal" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) or negative (-1 to -100): the user should consider that upside
           * or downside gap side-by-side white lines is significant when it appears in a trend, while this function
           * does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 2], inClose[i - 2])) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 2], inClose[i - 2]))) && /* upside or downside gap between the 1st candle and both the next 2 candles */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && /* 2nd: white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&         /* 3rd: white */
                 Math.abs(inClose[i] - inOpen[i]) >= Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && /* same size 2 and 3 */
                 Math.abs(inClose[i] - inOpen[i]) <= Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* same open 2 and 3 */
                 inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) ? 100 : 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGapSideSideWhiteUnguarded( int startIdx,
                                                    int endIdx,
                                                    double inOpen[],
                                                    double inHigh[],
                                                    double inLow[],
                                                    double inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double NearPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlGapSideSideWhiteLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          EqualPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 2], inClose[i - 2])) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 2], inClose[i - 2]))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) >= Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) ? 100 : 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGapSideSideWhite( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double NearPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlGapSideSideWhiteLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          EqualPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 2], inClose[i - 2])) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 2], inClose[i - 2]))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) >= Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) ? 100 : 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGapSideSideWhiteUnguarded( int startIdx,
                                                    int endIdx,
                                                    float inOpen[],
                                                    float inHigh[],
                                                    float inLow[],
                                                    float inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double NearPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlGapSideSideWhiteLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          EqualPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 2], inClose[i - 2])) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 2], inClose[i - 2]))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) >= Math.abs(inClose[i - 1] - inOpen[i - 1]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= Math.abs(inClose[i - 1] - inOpen[i - 1]) + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) ? 100 : 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlGravestoneDojiLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(BodyDoji_avgPeriod, ShadowVeryShort_avgPeriod) ;

       }
       public RetCode cdlGravestoneDoji( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlGravestoneDojiLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - doji body
           * - open and close at the low of the day = no or very short lower shadow
           * - upper shadow (to distinguish from other dojis, here upper shadow should not be very short)
           * The meaning of "doji" and "very short" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: gravestone doji must be considered
           * relatively to the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGravestoneDojiUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlGravestoneDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGravestoneDoji( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlGravestoneDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlGravestoneDojiUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlGravestoneDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102304 AC   Creation
     */

       public int cdlHammerLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(Math.max(BodyShort_avgPeriod, ShadowLong_avgPeriod), ShadowVeryShort_avgPeriod), Near_avgPeriod) + 1 ;

       }
       public RetCode cdlHammer( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHammerLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - small real body
           * - long lower shadow
           * - no, or very short, upper shadow
           * - body below or near the lows of the previous candle
           * The meaning of "short", "long" and "near the lows" is specified with TA_SetCandleSettings;
           * outInteger is positive (1 to 100): hammer is always bullish;
           * the user should consider that a hammer must appear in a downtrend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* small rb */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long lower shadow */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short upper shadow */
                 Math.min(inClose[i], inOpen[i]) <= inLow[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) /* rb near the prior candle's lows */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHammerUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) <= inLow[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHammer( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) <= inLow[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHammerUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) <= inLow[i - 1] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102304 AC   Creation
     */

       public int cdlHangingManLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(Math.max(BodyShort_avgPeriod, ShadowLong_avgPeriod), ShadowVeryShort_avgPeriod), Near_avgPeriod) + 1 ;

       }
       public RetCode cdlHangingMan( int startIdx,
                                     int endIdx,
                                     double inOpen[],
                                     double inHigh[],
                                     double inLow[],
                                     double inClose[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHangingManLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - small real body
           * - long lower shadow
           * - no, or very short, upper shadow
           * - body above or near the highs of the previous candle
           * The meaning of "short", "long" and "near the highs" is specified with TA_SetCandleSettings;
           * outInteger is negative (-1 to -100): hanging man is always bearish;
           * the user should consider that a hanging man must appear in an uptrend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* small rb */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long lower shadow */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short upper shadow */
                 Math.min(inClose[i], inOpen[i]) >= inHigh[i - 1] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) /* rb near the prior candle's highs */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHangingManUnguarded( int startIdx,
                                              int endIdx,
                                              double inOpen[],
                                              double inHigh[],
                                              double inLow[],
                                              double inClose[],
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlHangingManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) >= inHigh[i - 1] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHangingMan( int startIdx,
                                     int endIdx,
                                     float inOpen[],
                                     float inHigh[],
                                     float inLow[],
                                     float inClose[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHangingManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) >= inHigh[i - 1] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHangingManUnguarded( int startIdx,
                                              int endIdx,
                                              float inOpen[],
                                              float inHigh[],
                                              float inLow[],
                                              float inClose[],
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlHangingManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 1 - Near_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx - 1 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.min(inClose[i], inOpen[i]) >= inHigh[i - 1] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102404 AC   Creation
     *  040309 AC   Increased flexibility to allow real bodies matching
     *              on one end (Greg Morris - "Candlestick charting explained")
     */

       public int cdlHaramiLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlHarami( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHaramiLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white (black) real body
           * - second candle: short real body totally engulfed by the first
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish:
           * - 100 is returned when the first candle's real body begins before and ends after the second candle's real body
           * - 80 is returned when the two real bodies match on one end (Greg Morris contemplate this case in his book
           *   "Candlestick charting explained")
           * The user should consider that a harami is significant when it appears in a downtrend if bullish or
           * in an uptrend when bearish, while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                /* 1st: long */
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   /* 2nd: short */
                   /* 2nd is engulfed by 1st */
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                      /* 2nd is engulfed by 1st
                       * (one end of real body can match;
                       * engulfing guaranteed by "long" and "short")
                       */
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHaramiUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlHaramiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHarami( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHaramiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHaramiUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlHaramiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  102404 AC   Creation
     *  040309 AC   Increased flexibility to allow real bodies matching
     *              on one end (Greg Morris - "Candlestick charting explained")
     */

       public int cdlHaramiCrossLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return Math.max(BodyDoji_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlHaramiCross( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHaramiCrossLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white (black) real body
           * - second candle: doji totally engulfed by the first
           * The meaning of "doji" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that a harami cross is significant when it appears in a downtrend if bullish or
           * in an uptrend when bearish, while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                /* 1st: long */
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   /* 2nd: doji */
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && /* 2nd is engulfed by 1st */
                       Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) )
                   {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && /* 2nd is engulfed by 1st */
                       Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) /* (one end of real body can match; */
                   {
                      /* engulfing guaranteed by "long" and "doji") */
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHaramiCrossUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlHaramiCrossLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHaramiCross( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHaramiCrossLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHaramiCrossUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlHaramiCrossLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 1 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                   if( Math.max(inClose[i], inOpen[i]) < Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) > Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 100;
                   } else if( Math.max(inClose[i], inOpen[i]) <= Math.max(inClose[i - 1], inOpen[i - 1]) && Math.min(inClose[i], inOpen[i]) >= Math.min(inClose[i - 1], inOpen[i - 1]) ) {
                      outInteger[outIdx++] = (0 - ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1)) * 80;
                   } else {
                      outInteger[outIdx++] = 0;
                   }
                } else {
                   outInteger[outIdx++] = 0;
                }
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  072404 AC   Creation
     */

       public int cdlHignWaveLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, ShadowVeryLong_avgPeriod) ;

       }
       public RetCode cdlHignWave( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHignWaveLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - short real body
           * - very long upper and lower shadow
           * The meaning of "short" and "very long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white or negative (-1 to -100) when black;
           * it does not mean bullish or bearish
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHignWaveUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          lookbackTotal = cdlHignWaveLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHignWave( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHignWaveLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHignWaveUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          lookbackTotal = cdlHignWaveLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120305 AC   Creation
     */

       public int cdlHikkakeLookback( )
       {
          return 5 ;

       }
       public RetCode cdlHikkake( int startIdx,
                                  int endIdx,
                                  double inOpen[],
                                  double inHigh[],
                                  double inLow[],
                                  double inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHikkakeLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             /* copy here the pattern recognition code below */
             if( inHigh[i - 1] < inHigh[i - 2] &&
                 inLow[i - 1] > inLow[i - 2] &&   /* 1st + 2nd: lower high and higher low */
                 (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) /* (bull) 3rd: lower high and lower low (bear) 3rd: higher high and higher low */
             {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 &&
                 (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) /* search for confirmation if hikkake was no more than 3 bars ago close higher than the high of 2nd close lower than the low of 2nd */
             {
                patternIdx = 0;
             }
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first and second candle: inside bar (2nd has lower high and higher low than 1st)
           * - third candle: lower high and lower low than 2nd (higher high and higher low than 2nd)
           * outInteger[hikkakebar] is positive (1 to 100) or negative (-1 to -100) meaning bullish or bearish hikkake
           * Confirmation could come in the next 3 days with:
           * - a day that closes higher than the high (lower than the low) of the 2nd candle
           * outInteger[confirmationbar] is equal to 100 + the bullish hikkake result or -100 - the bearish hikkake result
           * Note: if confirmation and a new hikkake come at the same bar, only the new hikkake is reported (the new hikkake
           * overwrites the confirmation of the old hikkake)
           */
          outIdx = 0;
          do {
             if( inHigh[i - 1] < inHigh[i - 2] &&
                 inLow[i - 1] > inLow[i - 2] &&   /* 1st + 2nd: lower high and higher low */
                 (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) /* (bull) 3rd: lower high and lower low (bear) 3rd: higher high and higher low */
             {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 &&
                 (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) /* search for confirmation if hikkake was no more than 3 bars ago close higher than the high of 2nd close lower than the low of 2nd */
             {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkakeUnguarded( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          lookbackTotal = cdlHikkakeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkake( int startIdx,
                                  int endIdx,
                                  float inOpen[],
                                  float inHigh[],
                                  float inLow[],
                                  float inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHikkakeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkakeUnguarded( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          lookbackTotal = cdlHikkakeLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1]) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  122605 AC   Creation
     */

       public int cdlHikkakeModLookback( )
       {
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          return Math.max(1, Near_avgPeriod) + 5 ;

       }
       public RetCode cdlHikkakeMod( int startIdx,
                                     int endIdx,
                                     double inOpen[],
                                     double inHigh[],
                                     double inLow[],
                                     double inClose[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHikkakeModLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 3 - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx - 3 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             /* copy here the pattern recognition code below */
             if( inHigh[i - 2] < inHigh[i - 3] &&
                 inLow[i - 2] > inLow[i - 3] &&   /* 2nd: lower high and higher low than 1st */
                 inHigh[i - 1] < inHigh[i - 2] &&
                 inLow[i - 1] > inLow[i - 2] &&   /* 3rd: lower high and higher low than 2nd */
                 (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) /* (bull) 4th: lower high and lower low (bull) 2nd: close near the low (bear) 4th: higher high and higher low (bull) 2nd: close near the top */
             {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 &&
                 (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) /* search for confirmation if modified hikkake was no more than 3 bars ago close higher than the high of 3rd close lower than the low of 3rd */
             {
                patternIdx = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle
           * - second candle: candle with range less than first candle and close near the bottom (near the top)
           * - third candle: lower high and higher low than 2nd
           * - fourth candle: lower high and lower low (higher high and higher low) than 3rd
           * outInteger[hikkake bar] is positive (1 to 100) or negative (-1 to -100) meaning bullish or bearish hikkake
           * Confirmation could come in the next 3 days with:
           * - a day that closes higher than the high (lower than the low) of the 3rd candle
           * outInteger[confirmationbar] is equal to 100 + the bullish hikkake result or -100 - the bearish hikkake result
           * Note: if confirmation and a new hikkake come at the same bar, only the new hikkake is reported (the new hikkake
           * overwrites the confirmation of the old hikkake);
           * the user should consider that modified hikkake is a reversal pattern, while hikkake could be both a reversal
           * or a continuation pattern, so bullish (bearish) modified hikkake is significant when appearing in a downtrend
           * (uptrend)
           */
          outIdx = 0;
          do {
             if( inHigh[i - 2] < inHigh[i - 3] &&
                 inLow[i - 2] > inLow[i - 3] &&   /* 2nd: lower high and higher low than 1st */
                 inHigh[i - 1] < inHigh[i - 2] &&
                 inLow[i - 1] > inLow[i - 2] &&   /* 3rd: lower high and higher low than 2nd */
                 (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) /* (bull) 4th: lower high and lower low (bull) 2nd: close near the low (bear) 4th: higher high and higher low (bull) 2nd: close near the top */
             {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 &&
                 (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) /* search for confirmation if modified hikkake was no more than 3 bars ago close higher than the high of 3rd close lower than the low of 3rd */
             {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkakeModUnguarded( int startIdx,
                                              int endIdx,
                                              double inOpen[],
                                              double inHigh[],
                                              double inLow[],
                                              double inClose[],
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlHikkakeModLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 3 - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx - 3 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkakeMod( int startIdx,
                                     int endIdx,
                                     float inOpen[],
                                     float inHigh[],
                                     float inLow[],
                                     float inClose[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHikkakeModLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 3 - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx - 3 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHikkakeModUnguarded( int startIdx,
                                              int endIdx,
                                              float inOpen[],
                                              float inHigh[],
                                              float inLow[],
                                              float inClose[],
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int patternIdx = 0;
          int patternResult = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlHikkakeModLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - 3 - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx - 3 ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          patternIdx = 0;
          patternResult = 0;
          i = startIdx - 3;
          while( i < startIdx ) {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                patternIdx = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( inHigh[i - 2] < inHigh[i - 3] && inLow[i - 2] > inLow[i - 3] && inHigh[i - 1] < inHigh[i - 2] && inLow[i - 1] > inLow[i - 2] && (inHigh[i] < inHigh[i - 1] && inLow[i] < inLow[i - 1] && inClose[i - 2] <= inLow[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || inHigh[i] > inHigh[i - 1] && inLow[i] > inLow[i - 1] && inClose[i - 2] >= inHigh[i - 2] - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                patternResult = 100 * ((inHigh[i] < inHigh[i - 1]) ? 1 : 0 - 1);
                patternIdx = i;
                outInteger[outIdx++] = patternResult;
             } else if( i <= patternIdx + 3 && (patternResult > 0 && inClose[i] > inHigh[patternIdx - 1] || patternResult < 0 && inClose[i] < inLow[patternIdx - 1]) ) {
                outInteger[outIdx++] = patternResult + 100 * ((patternResult > 0) ? 1 : 0 - 1);
                patternIdx = 0;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 2] - inLow[NearTrailingIdx - 2]) - Math.abs(inClose[NearTrailingIdx - 2] - inOpen[NearTrailingIdx - 2])) : 0.0)));
             NearTrailingIdx += 1;
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  032005 AC   Creation
     */

       public int cdlHomingPigeonLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlHomingPigeon( int startIdx,
                                       int endIdx,
                                       double inOpen[],
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlHomingPigeonLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: short black real body completely inside the previous day's body
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100): homing pigeon is always bullish;
           * the user should consider that homing pigeon is significant when it appears in a downtrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 1st black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 2nd black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st long */
                 Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd short */
                 inOpen[i] < inOpen[i - 1] &&                                /* 2nd engulfed by 1st */
                 inClose[i] > inClose[i - 1] )
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHomingPigeonUnguarded( int startIdx,
                                                int endIdx,
                                                double inOpen[],
                                                double inHigh[],
                                                double inLow[],
                                                double inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlHomingPigeonLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHomingPigeon( int startIdx,
                                       int endIdx,
                                       float inOpen[],
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlHomingPigeonLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlHomingPigeonUnguarded( int startIdx,
                                                int endIdx,
                                                float inOpen[],
                                                float inHigh[],
                                                float inLow[],
                                                float inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlHomingPigeonLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  103104 AC   Creation
     */

       public int cdlIdentical3CrowsLookback( )
       {
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(ShadowVeryShort_avgPeriod, Equal_avgPeriod) + 2 ;

       }
       public RetCode cdlIdentical3Crows( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] EqualPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlIdentical3CrowsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          EqualPeriodTotal[2] = 0;
          EqualPeriodTotal[1] = 0;
          EqualPeriodTotal[0] = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal[2] = EqualPeriodTotal[2] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             EqualPeriodTotal[1] = EqualPeriodTotal[1] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three consecutive and declining black candlesticks
           * - each candle must have no or very short lower shadow
           * - each candle after the first must open at or very close to the prior candle's close
           * The meaning of "very short" is specified with TA_SetCandleSettings;
           * the meaning of "very close" is specified with TA_SetCandleSettings (Equal);
           * outInteger is negative (-1 to -100): identical three crows is always bearish;
           * the user should consider that identical 3 crows is significant when it appears after a mature advance or at high levels,
           * while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* 1st black */
                 (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short lower shadow */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd black */
                 (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short lower shadow */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 3rd black */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short lower shadow */
                 inClose[i - 2] > inClose[i - 1] &&                          /* three declining */
                 inClose[i - 1] > inClose[i] &&
                 inOpen[i - 1] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd black opens very close to 1st close */
                 inOpen[i - 1] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) &&
                 inOpen[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* 3rd black opens very close to 2nd close */
                 inOpen[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                EqualPeriodTotal[totIdx] = EqualPeriodTotal[totIdx] + (((Equal_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) - Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlIdentical3CrowsUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] EqualPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlIdentical3CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          EqualPeriodTotal[2] = 0;
          EqualPeriodTotal[1] = 0;
          EqualPeriodTotal[0] = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal[2] = EqualPeriodTotal[2] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             EqualPeriodTotal[1] = EqualPeriodTotal[1] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && inOpen[i - 1] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                EqualPeriodTotal[totIdx] = EqualPeriodTotal[totIdx] + (((Equal_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) - Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlIdentical3Crows( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] EqualPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlIdentical3CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          EqualPeriodTotal[2] = 0;
          EqualPeriodTotal[1] = 0;
          EqualPeriodTotal[0] = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal[2] = EqualPeriodTotal[2] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             EqualPeriodTotal[1] = EqualPeriodTotal[1] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && inOpen[i - 1] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                EqualPeriodTotal[totIdx] = EqualPeriodTotal[totIdx] + (((Equal_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) - Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlIdentical3CrowsUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[3];
          double[] EqualPeriodTotal = new double[3];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlIdentical3CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[2] = 0;
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          EqualPeriodTotal[2] = 0;
          EqualPeriodTotal[1] = 0;
          EqualPeriodTotal[0] = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[2] = ShadowVeryShortPeriodTotal[2] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal[2] = EqualPeriodTotal[2] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             EqualPeriodTotal[1] = EqualPeriodTotal[1] + ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 2] >= inOpen[i - 2]) ? inOpen[i - 2] : inClose[i - 2]) - inLow[i - 2]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[2] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i - 2] > inClose[i - 1] && inClose[i - 1] > inClose[i] && inOpen[i - 1] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[2] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal[1] / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 0; totIdx -= 1 ) {
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                EqualPeriodTotal[totIdx] = EqualPeriodTotal[totIdx] + (((Equal_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - totIdx] - inLow[EqualTrailingIdx - totIdx]) - Math.abs(inClose[EqualTrailingIdx - totIdx] - inOpen[EqualTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdlInNeckLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Math.max(Equal_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlInNeck( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlInNeckLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: white candle with open below previous day low and close slightly into previous day body
           * The meaning of "equal" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): in-neck is always bearish
           * the user should consider that in-neck is significant when it appears in a downtrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 1st: black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* 2nd: white */
                 inOpen[i] < inLow[i - 1] &&                                 /* open below prior low */
                 inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* close slightly into prior body */
                 inClose[i] >= inClose[i - 1] )
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInNeckUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlInNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInNeck( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlInNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInNeckUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlInNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  103004 AC   Creation
     */

       public int cdlInvertedHammerLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(BodyShort_avgPeriod, ShadowLong_avgPeriod), ShadowVeryShort_avgPeriod) + 1 ;

       }
       public RetCode cdlInvertedHammer( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlInvertedHammerLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - small real body
           * - long upper shadow
           * - no, or very short, lower shadow
           * - gap down
           * The meaning of "short", "very short" and "long" is specified with TA_SetCandleSettings;
           * outInteger is positive (1 to 100): inverted hammer is always bullish;
           * the user should consider that an inverted hammer must appear in a downtrend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1])) && /* gap down */
                 Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* small rb */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long upper shadow */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                /* very short lower shadow */
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInvertedHammerUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlInvertedHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInvertedHammer( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlInvertedHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlInvertedHammerUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlInvertedHammerLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.max(inOpen[i], inClose[i]) < Math.min(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010705 AC   Creation
     */

       public int cdlKickingLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(ShadowVeryShort_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlKicking( int startIdx,
                                  int endIdx,
                                  double inOpen[],
                                  double inHigh[],
                                  double inLow[],
                                  double inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlKickingLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: marubozu
           * - second candle: opposite color marubozu
           * - gap between the two candles: upside gap if black then white, downside gap if white then black
           * The meaning of "long body" and "very short shadow" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && /* opposite candles */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st marubozu */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd marubozu */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) /* gap */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKickingUnguarded( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlKickingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKicking( int startIdx,
                                  int endIdx,
                                  float inOpen[],
                                  float inHigh[],
                                  float inLow[],
                                  float inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlKickingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKickingUnguarded( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlKickingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlKickingByLengthLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(ShadowVeryShort_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlKickingByLength( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlKickingByLengthLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: marubozu
           * - second candle: opposite color marubozu
           * - gap between the two candles: upside gap if black then white, downside gap if white then black
           * The meaning of "long body" and "very short shadow" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish; the longer of the two
           * marubozu determines the bullishness or bearishness of this pattern
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && /* opposite candles */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st marubozu */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd marubozu */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) /* gap */
             {
                outInteger[outIdx++] = ((inClose[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1] >= inOpen[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKickingByLengthUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlKickingByLengthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1] >= inOpen[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKickingByLength( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlKickingByLengthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1] >= inOpen[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlKickingByLengthUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double[] ShadowVeryShortPeriodTotal = new double[2];
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlKickingByLengthLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal[1] = 0;
          ShadowVeryShortPeriodTotal[0] = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal[1] = ShadowVeryShortPeriodTotal[1] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             ShadowVeryShortPeriodTotal[0] = ShadowVeryShortPeriodTotal[0] + ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? inOpen[i - 1] : inClose[i - 1]) - inLow[i - 1]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[1] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal[0] / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inLow[i] > inHigh[i - 1]) || ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && (inHigh[i] < inLow[i - 1])) ) {
                outInteger[outIdx++] = ((inClose[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1] >= inOpen[(Math.abs(inClose[i] - inOpen[i]) > Math.abs(inClose[i - 1] - inOpen[i - 1])) ? i : i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                ShadowVeryShortPeriodTotal[totIdx] = ShadowVeryShortPeriodTotal[totIdx] + (((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - totIdx] - inLow[ShadowVeryShortTrailingIdx - totIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - totIdx] - inOpen[ShadowVeryShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  032005 AC   Creation
     *  041305 MF   Minor modification for a compiler warning
     */

       public int cdlLadderBottomLookback( )
       {
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return ShadowVeryShort_avgPeriod + 4 ;

       }
       public RetCode cdlLadderBottom( int startIdx,
                                       int endIdx,
                                       double inOpen[],
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlLadderBottomLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three black candlesticks with consecutively lower opens and closes
           * - fourth candle: black candle with an upper shadow (it's supposed to be not very short)
           * - fifth candle: white candle that opens above prior candle's body and closes above prior candle's high
           * The meaning of "very short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100): ladder bottom is always bullish;
           * the user should consider that ladder bottom is significant when it appears in a downtrend,
           * while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 &&
                 ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 &&
                 ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* 3 black candlesticks */
                 inOpen[i - 4] > inOpen[i - 3] &&
                 inOpen[i - 3] > inOpen[i - 2] &&                            /* with consecutively lower opens */
                 inClose[i - 4] > inClose[i - 3] &&
                 inClose[i - 3] > inClose[i - 2] &&                          /* and closes */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 4th: black with an upper shadow */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* 5th: white */
                 inOpen[i] > inOpen[i - 1] &&                                /* that opens above prior candle's body */
                 inClose[i] > inHigh[i - 1] )                                /* and closes above prior candle's high */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLadderBottomUnguarded( int startIdx,
                                                int endIdx,
                                                double inOpen[],
                                                double inHigh[],
                                                double inLow[],
                                                double inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlLadderBottomLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 4] > inOpen[i - 3] && inOpen[i - 3] > inOpen[i - 2] && inClose[i - 4] > inClose[i - 3] && inClose[i - 3] > inClose[i - 2] && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] > inOpen[i - 1] && inClose[i] > inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLadderBottom( int startIdx,
                                       int endIdx,
                                       float inOpen[],
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlLadderBottomLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 4] > inOpen[i - 3] && inOpen[i - 3] > inOpen[i - 2] && inClose[i - 4] > inClose[i - 3] && inClose[i - 3] > inClose[i - 2] && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] > inOpen[i - 1] && inClose[i] > inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLadderBottomUnguarded( int startIdx,
                                                int endIdx,
                                                float inOpen[],
                                                float inHigh[],
                                                float inLow[],
                                                float inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlLadderBottomLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i - 4] > inOpen[i - 3] && inOpen[i - 3] > inOpen[i - 2] && inClose[i - 4] > inClose[i - 3] && inClose[i - 3] > inClose[i - 2] && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) > ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] > inOpen[i - 1] && inClose[i] > inHigh[i - 1] ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlLongLeggedDojiLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          return Math.max(BodyDoji_avgPeriod, ShadowLong_avgPeriod) ;

       }
       public RetCode cdlLongLeggedDoji( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlLongLeggedDojiLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - doji body
           * - one or two long shadows
           * The meaning of "doji" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: long legged doji shows uncertainty
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && ((((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLeggedDojiUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          lookbackTotal = cdlLongLeggedDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && ((((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLeggedDoji( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlLongLeggedDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && ((((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLeggedDojiUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          lookbackTotal = cdlLongLeggedDojiLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && ((((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) || (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  071704 AC   Creation
     */

       public int cdlLongLineLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          return Math.max(BodyLong_avgPeriod, ShadowShort_avgPeriod) ;

       }
       public RetCode cdlLongLine( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlLongLineLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - long real body
           * - short upper and lower shadow
           * The meaning of "long" and "short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white (bullish), negative (-1 to -100) when black (bearish)
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLineUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlLongLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLine( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlLongLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlLongLineUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlLongLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010605 AC   Creation
     */

       public int cdlMarubozuLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(BodyLong_avgPeriod, ShadowVeryShort_avgPeriod) ;

       }
       public RetCode cdlMarubozu( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlMarubozuLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - long real body
           * - no or very short upper and lower shadow
           * The meaning of "long" and "very short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white (bullish), negative (-1 to -100) when black (bearish)
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMarubozuUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMarubozu( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMarubozuUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double BodyLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlMarubozuLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  032605 AC   Creation
     */

       public int cdlMatchingLowLookback( )
       {
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Equal_avgPeriod + 1 ;

       }
       public RetCode cdlMatchingLow( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlMatchingLowLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: black candle
           * - second candle: black candle with the close equal to the previous close
           * The meaning of "equal" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100): matching low is always bullish;
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* first black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* second black */
                 inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st and 2nd same close */
                 inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatchingLowUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlMatchingLowLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatchingLow( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlMatchingLowLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatchingLowUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlMatchingLowLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inClose[i] <= inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  022005 AC   Creation
     */

       public int cdlMatHoldLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 4 ;

       }
       public RetCode cdlMatHold( int startIdx,
                                  int endIdx,
                                  double inOpen[],
                                  double inHigh[],
                                  double inLow[],
                                  double inClose[],
                                  double optInPenetration,
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlMatHoldLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white candle
           * - upside gap between the first and the second bodies
           * - second candle: small black candle
           * - third and fourth candles: falling small real body candlesticks (commonly black) that hold within the long
           *   white candle's body and are higher than the reaction days of the rising three methods
           * - fifth candle: white candle that opens above the previous small candle's close and closes higher than the
           *   high of the highest reaction day
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings;
           * "hold within" means "a part of the real body must be within";
           * optInPenetration is the maximum percentage of the first white body the reaction days can penetrate (it is
           * to specify how much the reaction days should be "higher than the reaction days of the rising three methods")
           * outInteger is positive (1 to 100): mat hold is always bullish
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 &&     /* white, black, 2 black or white, white */
                 ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 &&
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&
                 (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && /* upside gap 1st to 2nd */
                 Math.min(inOpen[i - 2], inClose[i - 2]) < inClose[i - 4] && /* 3rd to 4th hold within 1st: a part of the real body must be within 1st real body */
                 Math.min(inOpen[i - 1], inClose[i - 1]) < inClose[i - 4] &&
                 Math.min(inOpen[i - 2], inClose[i - 2]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && /* reaction days penetrate first body less than optInPenetration percent */
                 Math.min(inOpen[i - 1], inClose[i - 1]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration &&
                 Math.max(inClose[i - 2], inOpen[i - 2]) < inOpen[i - 3] &&  /* 2nd to 4th are falling */
                 Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) &&
                 inOpen[i] > inClose[i - 1] &&                               /* 5th opens above the prior close */
                 inClose[i] > Math.max(Math.max(inHigh[i - 3], inHigh[i - 2]), inHigh[i - 1]) && /* 5th closes above the highest high of the reaction days */
                 Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st long, then 3 small */
                 Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatHoldUnguarded( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           double optInPenetration,
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMatHoldLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && Math.min(inOpen[i - 2], inClose[i - 2]) < inClose[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inClose[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.min(inOpen[i - 1], inClose[i - 1]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.max(inClose[i - 2], inOpen[i - 2]) < inOpen[i - 3] && Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && inOpen[i] > inClose[i - 1] && inClose[i] > Math.max(Math.max(inHigh[i - 3], inHigh[i - 2]), inHigh[i - 1]) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatHold( int startIdx,
                                  int endIdx,
                                  float inOpen[],
                                  float inHigh[],
                                  float inLow[],
                                  float inClose[],
                                  double optInPenetration,
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 5e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlMatHoldLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && Math.min(inOpen[i - 2], inClose[i - 2]) < inClose[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inClose[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.min(inOpen[i - 1], inClose[i - 1]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.max(inClose[i - 2], inOpen[i - 2]) < inOpen[i - 3] && Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && inOpen[i] > inClose[i - 1] && inClose[i] > Math.max(Math.max(inHigh[i - 3], inHigh[i - 2]), inHigh[i - 1]) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMatHoldUnguarded( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           double optInPenetration,
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMatHoldLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 1 && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 3], inClose[i - 3]) > Math.max(inOpen[i - 4], inClose[i - 4])) && Math.min(inOpen[i - 2], inClose[i - 2]) < inClose[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inClose[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.min(inOpen[i - 1], inClose[i - 1]) > inClose[i - 4] - Math.abs(inClose[i - 4] - inOpen[i - 4]) * optInPenetration && Math.max(inClose[i - 2], inOpen[i - 2]) < inOpen[i - 3] && Math.max(inClose[i - 1], inOpen[i - 1]) < Math.max(inClose[i - 2], inOpen[i - 2]) && inOpen[i] > inClose[i - 1] && inClose[i] > Math.max(Math.max(inHigh[i - 3], inHigh[i - 2]), inHigh[i - 1]) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  100304 AC   Creation
     */

       public int cdlMorningDojiStarLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(Math.max(BodyDoji_avgPeriod, BodyLong_avgPeriod), BodyShort_avgPeriod) + 2 ;

       }
       public RetCode cdlMorningDojiStar( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          double optInPenetration,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlMorningDojiStarLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black real body
           * - second candle: doji gapping down
           * - third candle: white real body that moves well within the first candle's real body
           * The meaning of "doji" and "long" is specified with TA_SetCandleSettings
           * The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
           * not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
           * it to be relatively long
           * outInteger is positive (1 to 100): morning doji star is always bullish;
           * the user should consider that a morning star is significant when it appears in a downtrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* white real body */
                 (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && /* gapping down */
                 inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && /* closing well within 1st rb */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: doji */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd: longer than short */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningDojiStarUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   double optInPenetration,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMorningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningDojiStar( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          double optInPenetration,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlMorningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningDojiStarUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   double optInPenetration,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMorningDojiStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyDojiPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyDojiTrailingIdx = startIdx - 1 - BodyDoji_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyDojiTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyDojiTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  100304 AC   Creation
     */

       public int cdlMorningStarLookback( double optInPenetration )
       {
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return -1;
          }
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdlMorningStar( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      double optInPenetration,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlMorningStarLookback(optInPenetration);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black real body
           * - second candle: star (Short real body gapping down)
           * - third candle: white real body that moves well within the first candle's real body
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
           * not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
           * it to be relatively long
           * outInteger is positive (1 to 100): morning star is always bullish;
           * the user should consider that a morning star is significant when it appears in a downtrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* white real body */
                 (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && /* gapping down */
                 inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && /* closing well within 1st rb */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: short */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd: longer than short */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningStarUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               double optInPenetration,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMorningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningStar( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      double optInPenetration,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInPenetration == -4e37 ) {
             optInPenetration = 3e-1;
          } else if( optInPenetration < 0e0 || optInPenetration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = cdlMorningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlMorningStarUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               double optInPenetration,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double BodyShortPeriodTotal2 = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlMorningStarLookback(optInPenetration);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyShortPeriodTotal2 = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i + 1] - inOpen[i + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i + 1] - inLow[i + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i + 1] - inLow[i + 1]) - Math.abs(inClose[i + 1] - inOpen[i + 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && inClose[i] > inClose[i - 2] + Math.abs(inClose[i - 2] - inOpen[i - 2]) * optInPenetration && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal2 / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal2 += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx + 1] - inLow[BodyShortTrailingIdx + 1]) - Math.abs(inClose[BodyShortTrailingIdx + 1] - inOpen[BodyShortTrailingIdx + 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121104 AC   Creation
     */

       public int cdlOnNeckLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Math.max(Equal_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlOnNeck( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlOnNeckLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: white candle with open below previous day low and close equal to previous day low
           * The meaning of "equal" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): on-neck is always bearish
           * the user should consider that on-neck is significant when it appears in a downtrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 1st: black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* 2nd: white */
                 inOpen[i] < inLow[i - 1] &&                                 /* open below prior low */
                 inClose[i] <= inLow[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* close equal to prior low */
                 inClose[i] >= inLow[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlOnNeckUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlOnNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inLow[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inLow[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlOnNeck( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlOnNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inLow[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inLow[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlOnNeckUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlOnNeckLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] <= inLow[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inLow[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120904 AC   Creation
     */

       public int cdlPiercingLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          return BodyLong_avgPeriod + 1 ;

       }
       public RetCode cdlPiercing( int startIdx,
                                   int endIdx,
                                   double inOpen[],
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlPiercingLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: long white candle with open below previous day low and close at least at 50% of previous day
           * real body
           * The meaning of "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100): piercing pattern is always bullish
           * the user should consider that a piercing pattern is significant when it appears in a downtrend, while
           * this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 1st: black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* 2nd: white */
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 inOpen[i] < inLow[i - 1] &&                                 /* open below prior low */
                 inClose[i] < inOpen[i - 1] &&                               /* close within prior body */
                 inClose[i] > inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) /* above midpoint */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlPiercingUnguarded( int startIdx,
                                            int endIdx,
                                            double inOpen[],
                                            double inHigh[],
                                            double inLow[],
                                            double inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlPiercingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inLow[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlPiercing( int startIdx,
                                   int endIdx,
                                   float inOpen[],
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlPiercingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inLow[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlPiercingUnguarded( int startIdx,
                                            int endIdx,
                                            float inOpen[],
                                            float inHigh[],
                                            float inLow[],
                                            float inClose[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[2];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          lookbackTotal = cdlPiercingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             BodyLongPeriodTotal[0] = BodyLongPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] < inLow[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 1; totIdx >= 0; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
             }
             i += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlRickshawManLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          return Math.max(Math.max(BodyDoji_avgPeriod, ShadowLong_avgPeriod), Near_avgPeriod) ;

       }
       public RetCode cdlRickshawMan( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlRickshawManLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - doji body
           * - two long shadows
           * - body near the midpoint of the high-low range
           * The meaning of "doji" and "near" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: rickshaw man shows uncertainty
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* doji */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long shadow */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long shadow */
                 Math.min(inOpen[i], inClose[i]) <= inLow[i] + (inHigh[i] - inLow[i]) / 2 + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.max(inOpen[i], inClose[i]) >= inLow[i] + (inHigh[i] - inLow[i]) / 2 - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) /* body near midpoint */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRickshawManUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          lookbackTotal = cdlRickshawManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i], inClose[i]) <= inLow[i] + (inHigh[i] - inLow[i]) / 2 + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.max(inOpen[i], inClose[i]) >= inLow[i] + (inHigh[i] - inLow[i]) / 2 - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRickshawMan( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlRickshawManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i], inClose[i]) <= inLow[i] + (inHigh[i] - inLow[i]) / 2 + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.max(inOpen[i], inClose[i]) >= inLow[i] + (inHigh[i] - inLow[i]) / 2 - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRickshawManUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          lookbackTotal = cdlRickshawManLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i], inClose[i]) <= inLow[i] + (inHigh[i] - inLow[i]) / 2 + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.max(inOpen[i], inClose[i]) >= inLow[i] + (inHigh[i] - inLow[i]) / 2 - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((Near_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((Near_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx] - inLow[NearTrailingIdx]) - Math.abs(inClose[NearTrailingIdx] - inOpen[NearTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  020605 AC   Creation
     */

       public int cdlRiseFall3MethodsLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 4 ;

       }
       public RetCode cdlRiseFall3Methods( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlRiseFall3MethodsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long white (black) candlestick
           * - then: group of falling (rising) small real body candlesticks (commonly black (white)) that hold within
           *   the prior long candle's range: ideally they should be three but two or more than three are ok too
           * - final candle: long white (black) candle that opens above (below) the previous small candle's close
           *   and closes above (below) the first long candle's close
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings; here only patterns with 3 small candles
           * are considered;
           * outInteger is positive (1 to 100) or negative (-1 to -100)
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && /* white, 3 black, white  ||  black, 3 white, black */
                 ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) &&
                 ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) &&
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) &&
                 Math.min(inOpen[i - 3], inClose[i - 3]) < inHigh[i - 4] && /* 2nd to 4th hold within 1st: a part of the real body must be within 1st range */
                 Math.max(inOpen[i - 3], inClose[i - 3]) > inLow[i - 4] &&
                 Math.min(inOpen[i - 2], inClose[i - 2]) < inHigh[i - 4] &&
                 Math.max(inOpen[i - 2], inClose[i - 2]) > inLow[i - 4] &&
                 Math.min(inOpen[i - 1], inClose[i - 1]) < inHigh[i - 4] &&
                 Math.max(inOpen[i - 1], inClose[i - 1]) > inLow[i - 4] &&
                 inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 3] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && /* 2nd to 4th are falling (rising) */
                 inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) &&
                 inOpen[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && /* 5th opens above (below) the prior close */
                 inClose[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 4] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && /* 5th closes above (below) the 1st close */
                 Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st long, then 3 small, 5th long */
                 Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 100 * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1);
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0))));
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRiseFall3MethodsUnguarded( int startIdx,
                                                    int endIdx,
                                                    double inOpen[],
                                                    double inHigh[],
                                                    double inLow[],
                                                    double inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlRiseFall3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.min(inOpen[i - 3], inClose[i - 3]) < inHigh[i - 4] && Math.max(inOpen[i - 3], inClose[i - 3]) > inLow[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) < inHigh[i - 4] && Math.max(inOpen[i - 2], inClose[i - 2]) > inLow[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inHigh[i - 4] && Math.max(inOpen[i - 1], inClose[i - 1]) > inLow[i - 4] && inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 3] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inOpen[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 4] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100 * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1);
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0))));
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRiseFall3Methods( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlRiseFall3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.min(inOpen[i - 3], inClose[i - 3]) < inHigh[i - 4] && Math.max(inOpen[i - 3], inClose[i - 3]) > inLow[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) < inHigh[i - 4] && Math.max(inOpen[i - 2], inClose[i - 2]) > inLow[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inHigh[i - 4] && Math.max(inOpen[i - 1], inClose[i - 1]) > inLow[i - 4] && inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 3] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inOpen[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 4] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100 * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1);
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0))));
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlRiseFall3MethodsUnguarded( int startIdx,
                                                    int endIdx,
                                                    float inOpen[],
                                                    float inHigh[],
                                                    float inLow[],
                                                    float inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          double[] BodyPeriodTotal = new double[5];
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlRiseFall3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal[4] = 0;
          BodyPeriodTotal[3] = 0;
          BodyPeriodTotal[2] = 0;
          BodyPeriodTotal[1] = 0;
          BodyPeriodTotal[0] = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[3] = BodyPeriodTotal[3] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)));
             BodyPeriodTotal[2] = BodyPeriodTotal[2] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyPeriodTotal[1] = BodyPeriodTotal[1] + ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)));
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) == 0 - ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) && ((inClose[i - 3] >= inOpen[i - 3]) ? 1 : 0 - 1) == ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) && ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && Math.min(inOpen[i - 3], inClose[i - 3]) < inHigh[i - 4] && Math.max(inOpen[i - 3], inClose[i - 3]) > inLow[i - 4] && Math.min(inOpen[i - 2], inClose[i - 2]) < inHigh[i - 4] && Math.max(inOpen[i - 2], inClose[i - 2]) > inLow[i - 4] && Math.min(inOpen[i - 1], inClose[i - 1]) < inHigh[i - 4] && Math.max(inOpen[i - 1], inClose[i - 1]) > inLow[i - 4] && inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 3] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) < inClose[i - 2] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inOpen[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 1] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && inClose[i] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) > inClose[i - 4] * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1) && Math.abs(inClose[i - 4] - inOpen[i - 4]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[4] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 3] - inOpen[i - 3]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[3] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 3] - inOpen[i - 3])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 3] - inLow[i - 3]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 3] - inLow[i - 3]) - Math.abs(inClose[i - 3] - inOpen[i - 3])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 2] - inOpen[i - 2]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[2] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal[1] / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyPeriodTotal[0] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100 * ((inClose[i - 4] >= inOpen[i - 4]) ? 1 : 0 - 1);
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal[4] = BodyPeriodTotal[4] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 4] - inOpen[i - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 4] - inLow[i - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 4] - inLow[i - 4]) - Math.abs(inClose[i - 4] - inOpen[i - 4])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 4] - inLow[BodyLongTrailingIdx - 4]) - Math.abs(inClose[BodyLongTrailingIdx - 4] - inOpen[BodyLongTrailingIdx - 4])) : 0.0))));
             for( totIdx = 3; totIdx >= 1; totIdx -= 1 ) {
                BodyPeriodTotal[totIdx] = BodyPeriodTotal[totIdx] + (((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx - totIdx] - inLow[BodyShortTrailingIdx - totIdx]) - Math.abs(inClose[BodyShortTrailingIdx - totIdx] - inOpen[BodyShortTrailingIdx - totIdx])) : 0.0))));
             }
             BodyPeriodTotal[0] = BodyPeriodTotal[0] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0))));
             i += 1;
             BodyShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlSeperatingLinesLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(ShadowVeryShort_avgPeriod, BodyLong_avgPeriod), Equal_avgPeriod) + 1 ;

       }
       public RetCode cdlSeperatingLines( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlSeperatingLinesLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: black (white) candle
           * - second candle: bullish (bearish) belt hold with the same open as the prior candle
           * The meaning of "long body" and "very short shadow" of the belt hold is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that separating lines is significant when coming in a trend and the belt hold has
           * the same direction of the trend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && /* opposite candles */
                 inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* same open */
                 inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* belt hold: long body */
                 (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) /* with no lower shadow if bullish with no upper shadow if bearish */
             {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSeperatingLinesUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlSeperatingLinesLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSeperatingLines( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlSeperatingLinesLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSeperatingLinesUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double ShadowVeryShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlSeperatingLinesLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] <= inOpen[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inOpen[i - 1] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) || ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0))))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             i += 1;
             ShadowVeryShortTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  103004 AC   Creation
     */

       public int cdlShootingStarLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(BodyShort_avgPeriod, ShadowLong_avgPeriod), ShadowVeryShort_avgPeriod) + 1 ;

       }
       public RetCode cdlShootingStar( int startIdx,
                                       int endIdx,
                                       double inOpen[],
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlShootingStarLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - small real body
           * - long upper shadow
           * - no, or very short, lower shadow
           * - gap up from prior real body
           * The meaning of "short", "very short" and "long" is specified with TA_SetCandleSettings;
           * outInteger is negative (-1 to -100): shooting star is always bearish;
           * the user should consider that a shooting star must appear in an uptrend, while this function does not consider it
           */
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) && /* gap up */
                 Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* small rb */
                 (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long upper shadow */
                 (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                /* very short lower shadow */
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShootingStarUnguarded( int startIdx,
                                                int endIdx,
                                                double inOpen[],
                                                double inHigh[],
                                                double inLow[],
                                                double inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlShootingStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShootingStar( int startIdx,
                                       int endIdx,
                                       float inOpen[],
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlShootingStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShootingStarUnguarded( int startIdx,
                                                int endIdx,
                                                float inOpen[],
                                                float inHigh[],
                                                float inLow[],
                                                float inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowLongPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowLongTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowLong_rangeType = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].rangeType.ordinal();
          int ShadowLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].avgPeriod;
          double ShadowLong_factor = this.candleSettings[CandleSettingType.ShadowLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlShootingStarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowLongPeriodTotal = 0;
          ShadowLongTrailingIdx = startIdx - ShadowLong_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowLongTrailingIdx;
          while( i < startIdx ) {
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i], inClose[i]) > Math.max(inOpen[i - 1], inClose[i - 1])) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > ((ShadowLong_factor * (((ShadowLong_avgPeriod != 0) ? (ShadowLongPeriodTotal / ShadowLong_avgPeriod) : ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowLong_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowLongPeriodTotal += ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowLong_rangeType == 0) ? (Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : ((ShadowLong_rangeType == 1) ? (inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) : ((ShadowLong_rangeType == 2) ? ((inHigh[ShadowLongTrailingIdx] - inLow[ShadowLongTrailingIdx]) - Math.abs(inClose[ShadowLongTrailingIdx] - inOpen[ShadowLongTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowLongTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  072404 AC   Creation
     */

       public int cdlShortLineLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, ShadowShort_avgPeriod) ;

       }
       public RetCode cdlShortLine( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlShortLineLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - short real body
           * - short upper and lower shadow
           * The meaning of "short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white, negative (-1 to -100) when black;
           * it does not mean bullish or bearish
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShortLineUnguarded( int startIdx,
                                             int endIdx,
                                             double inOpen[],
                                             double inHigh[],
                                             double inLow[],
                                             double inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlShortLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShortLine( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlShortLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlShortLineUnguarded( int startIdx,
                                             int endIdx,
                                             float inOpen[],
                                             float inHigh[],
                                             float inLow[],
                                             float inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          double ShadowPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int ShadowTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int ShadowShort_rangeType = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].rangeType.ordinal();
          int ShadowShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].avgPeriod;
          double ShadowShort_factor = this.candleSettings[CandleSettingType.ShadowShort.ordinal()].factor;
          lookbackTotal = cdlShortLineLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowPeriodTotal = 0;
          ShadowTrailingIdx = startIdx - ShadowShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowTrailingIdx;
          while( i < startIdx ) {
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) < ((ShadowShort_factor * (((ShadowShort_avgPeriod != 0) ? (ShadowPeriodTotal / ShadowShort_avgPeriod) : ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             ShadowPeriodTotal += ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowShort_rangeType == 0) ? (Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : ((ShadowShort_rangeType == 1) ? (inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) : ((ShadowShort_rangeType == 2) ? ((inHigh[ShadowTrailingIdx] - inLow[ShadowTrailingIdx]) - Math.abs(inClose[ShadowTrailingIdx] - inOpen[ShadowTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
             ShadowTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  071804 AC   Creation
     */

       public int cdlSpinningTopLookback( )
       {
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return BodyShort_avgPeriod ;

       }
       public RetCode cdlSpinningTop( int startIdx,
                                      int endIdx,
                                      double inOpen[],
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlSpinningTopLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - small real body
           * - shadows longer than the real body
           * The meaning of "short" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when white or negative (-1 to -100) when black;
           * it does not mean bullish or bearish
           */
          outIdx = 0;
          do {
             if( (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > Math.abs(inClose[i] - inOpen[i]) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > Math.abs(inClose[i] - inOpen[i]) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSpinningTopUnguarded( int startIdx,
                                               int endIdx,
                                               double inOpen[],
                                               double inHigh[],
                                               double inLow[],
                                               double inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlSpinningTopLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > Math.abs(inClose[i] - inOpen[i]) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > Math.abs(inClose[i] - inOpen[i]) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSpinningTop( int startIdx,
                                      int endIdx,
                                      float inOpen[],
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlSpinningTopLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > Math.abs(inClose[i] - inOpen[i]) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > Math.abs(inClose[i] - inOpen[i]) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlSpinningTopUnguarded( int startIdx,
                                               int endIdx,
                                               float inOpen[],
                                               float inHigh[],
                                               float inLow[],
                                               float inClose[],
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlSpinningTopLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx ) {
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) > Math.abs(inClose[i] - inOpen[i]) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > Math.abs(inClose[i] - inOpen[i]) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120804 AC   Creation
     */

       public int cdlStalledPatternLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(BodyLong_avgPeriod, BodyShort_avgPeriod), Math.max(ShadowVeryShort_avgPeriod, Near_avgPeriod)) + 2 ;

       }
       public RetCode cdlStalledPattern( int startIdx,
                                         int endIdx,
                                         double inOpen[],
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlStalledPatternLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal[2] = 0;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[2] = BodyLongPeriodTotal[2] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - three white candlesticks with consecutively higher closes
           * - first candle: long white
           * - second candle: long white with no or very short upper shadow opening within or near the previous white real body
           * and closing higher than the prior candle
           * - third candle: small white that gaps away or "rides on the shoulder" of the prior long real body (= it's at
           * the upper end of the prior real body)
           * The meanings of "long", "very short", "short", "near" are specified with TA_SetCandleSettings;
           * outInteger is negative (-1 to -100): stalled pattern is always bearish;
           * the user should consider that stalled pattern is significant when it appears in uptrend, while this function
           * does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && /* 1st white */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && /* 2nd white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&         /* 3rd white */
                 inClose[i] > inClose[i - 1] &&
                 inClose[i - 1] > inClose[i - 2] &&                      /* consecutive higher closes */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[2] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long real body */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: long real body */
                 (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && /* very short upper shadow */
                 inOpen[i - 1] > inOpen[i - 2] &&                        /* opens within/near 1st real body */
                 inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) &&
                 Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* 3rd: small real body */
                 inOpen[i] >= inClose[i - 1] - Math.abs(inClose[i] - inOpen[i]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) /* rides on the shoulder of 2nd real body */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStalledPatternUnguarded( int startIdx,
                                                  int endIdx,
                                                  double inOpen[],
                                                  double inHigh[],
                                                  double inLow[],
                                                  double inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlStalledPatternLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[2] = 0;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[2] = BodyLongPeriodTotal[2] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[2] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - Math.abs(inClose[i] - inOpen[i]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStalledPattern( int startIdx,
                                         int endIdx,
                                         float inOpen[],
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlStalledPatternLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[2] = 0;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[2] = BodyLongPeriodTotal[2] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[2] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - Math.abs(inClose[i] - inOpen[i]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStalledPatternUnguarded( int startIdx,
                                                  int endIdx,
                                                  float inOpen[],
                                                  float inHigh[],
                                                  float inLow[],
                                                  float inClose[],
                                                  MInteger outBegIdx,
                                                  MInteger outNBElement,
                                                  int outInteger[] )
       {
          double[] BodyLongPeriodTotal = new double[3];
          double[] NearPeriodTotal = new double[3];
          double BodyShortPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int totIdx = 0;
          int BodyLongTrailingIdx = 0;
          int BodyShortTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlStalledPatternLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal[2] = 0;
          BodyLongPeriodTotal[1] = 0;
          BodyLongPeriodTotal[0] = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          BodyShortPeriodTotal = 0;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          NearPeriodTotal[2] = 0;
          NearPeriodTotal[1] = 0;
          NearPeriodTotal[0] = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal[2] = BodyLongPeriodTotal[2] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             BodyLongPeriodTotal[1] = BodyLongPeriodTotal[1] + ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal[2] = NearPeriodTotal[2] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             NearPeriodTotal[1] = NearPeriodTotal[1] + ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i] > inClose[i - 1] && inClose[i - 1] > inClose[i - 2] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[2] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal[1] / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i - 1] - ((inClose[i - 1] >= inOpen[i - 1]) ? inClose[i - 1] : inOpen[i - 1])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i - 1] > inOpen[i - 2] && inOpen[i - 1] <= inClose[i - 2] + ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[2] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Near_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Near_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && inOpen[i] >= inClose[i - 1] - Math.abs(inClose[i] - inOpen[i]) - ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal[1] / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             for( totIdx = 2; totIdx >= 1; totIdx -= 1 ) {
                BodyLongPeriodTotal[totIdx] = BodyLongPeriodTotal[totIdx] + (((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - totIdx] - inLow[BodyLongTrailingIdx - totIdx]) - Math.abs(inClose[BodyLongTrailingIdx - totIdx] - inOpen[BodyLongTrailingIdx - totIdx])) : 0.0))));
                NearPeriodTotal[totIdx] = NearPeriodTotal[totIdx] + (((Near_rangeType == 0) ? (Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : ((Near_rangeType == 1) ? (inHigh[i - totIdx] - inLow[i - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[i - totIdx] - inLow[i - totIdx]) - Math.abs(inClose[i - totIdx] - inOpen[i - totIdx])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - totIdx] - inLow[NearTrailingIdx - totIdx]) - Math.abs(inClose[NearTrailingIdx - totIdx] - inOpen[NearTrailingIdx - totIdx])) : 0.0))));
             }
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx - 1] - inLow[ShadowVeryShortTrailingIdx - 1]) - Math.abs(inClose[ShadowVeryShortTrailingIdx - 1] - inOpen[ShadowVeryShortTrailingIdx - 1])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  032005 AC   Creation
     */

       public int cdlStickSandwichLookback( )
       {
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Equal_avgPeriod + 2 ;

       }
       public RetCode cdlStickSandwich( int startIdx,
                                        int endIdx,
                                        double inOpen[],
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlStickSandwichLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: black candle
           * - second candle: white candle that trades only above the prior close (low > prior close)
           * - third candle: black candle with the close equal to the first candle's close
           * The meaning of "equal" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100): stick sandwich is always bullish;
           * the user should consider that stick sandwich is significant when coming in a downtrend,
           * while this function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* first black */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 &&     /* second white */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* third black */
                 inLow[i - 1] > inClose[i - 2] &&                            /* 2nd low > prior close */
                 inClose[i] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st and 3rd same close */
                 inClose[i] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) - Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStickSandwichUnguarded( int startIdx,
                                                 int endIdx,
                                                 double inOpen[],
                                                 double inHigh[],
                                                 double inLow[],
                                                 double inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlStickSandwichLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inLow[i - 1] > inClose[i - 2] && inClose[i] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) - Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStickSandwich( int startIdx,
                                        int endIdx,
                                        float inOpen[],
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlStickSandwichLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inLow[i - 1] > inClose[i - 2] && inClose[i] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) - Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlStickSandwichUnguarded( int startIdx,
                                                 int endIdx,
                                                 float inOpen[],
                                                 float inHigh[],
                                                 float inLow[],
                                                 float inClose[],
                                                 MInteger outBegIdx,
                                                 MInteger outNBElement,
                                                 int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int lookbackTotal = 0;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlStickSandwichLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inLow[i - 1] > inClose[i - 2] && inClose[i] <= inClose[i - 2] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] >= inClose[i - 2] - ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((Equal_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((Equal_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 2] - inLow[EqualTrailingIdx - 2]) - Math.abs(inClose[EqualTrailingIdx - 2] - inOpen[EqualTrailingIdx - 2])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011505 AC   Creation
     */

       public int cdlTakuriLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          return Math.max(Math.max(BodyDoji_avgPeriod, ShadowVeryShort_avgPeriod), ShadowVeryLong_avgPeriod) ;

       }
       public RetCode cdlTakuri( int startIdx,
                                 int endIdx,
                                 double inOpen[],
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double ShadowVeryLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int ShadowVeryLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlTakuriLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          ShadowVeryLongPeriodTotal = 0;
          ShadowVeryLongTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryLongTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           *
           * Must have:
           * - doji body
           * - open and close at the high of the day = no or very short upper shadow
           * - very long lower shadow
           * The meaning of "doji", "very short" and "very long" is specified with TA_SetCandleSettings
           * outInteger is always positive (1 to 100) but this does not mean it is bullish: takuri must be considered
           * relatively to the trend
           */
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowVeryLongPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) - Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             ShadowVeryLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTakuriUnguarded( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double ShadowVeryLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int ShadowVeryLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlTakuriLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          ShadowVeryLongPeriodTotal = 0;
          ShadowVeryLongTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryLongTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowVeryLongPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) - Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             ShadowVeryLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTakuri( int startIdx,
                                 int endIdx,
                                 float inOpen[],
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double ShadowVeryLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int ShadowVeryLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlTakuriLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          ShadowVeryLongPeriodTotal = 0;
          ShadowVeryLongTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryLongTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowVeryLongPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) - Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             ShadowVeryLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTakuriUnguarded( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyDojiPeriodTotal = 0;
          double ShadowVeryShortPeriodTotal = 0;
          double ShadowVeryLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyDojiTrailingIdx = 0;
          int ShadowVeryShortTrailingIdx = 0;
          int ShadowVeryLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          int ShadowVeryLong_rangeType = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].rangeType.ordinal();
          int ShadowVeryLong_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].avgPeriod;
          double ShadowVeryLong_factor = this.candleSettings[CandleSettingType.ShadowVeryLong.ordinal()].factor;
          int ShadowVeryShort_rangeType = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].rangeType.ordinal();
          int ShadowVeryShort_avgPeriod = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].avgPeriod;
          double ShadowVeryShort_factor = this.candleSettings[CandleSettingType.ShadowVeryShort.ordinal()].factor;
          lookbackTotal = cdlTakuriLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyDojiPeriodTotal = 0;
          BodyDojiTrailingIdx = startIdx - BodyDoji_avgPeriod;
          ShadowVeryShortPeriodTotal = 0;
          ShadowVeryShortTrailingIdx = startIdx - ShadowVeryShort_avgPeriod;
          ShadowVeryLongPeriodTotal = 0;
          ShadowVeryLongTrailingIdx = startIdx - ShadowVeryLong_avgPeriod;
          i = BodyDojiTrailingIdx;
          while( i < startIdx ) {
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryShortTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = ShadowVeryLongTrailingIdx;
          while( i < startIdx ) {
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          outIdx = 0;
          do {
             if( Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyDojiPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && (inHigh[i] - ((inClose[i] >= inOpen[i]) ? inClose[i] : inOpen[i])) < ((ShadowVeryShort_factor * (((ShadowVeryShort_avgPeriod != 0) ? (ShadowVeryShortPeriodTotal / ShadowVeryShort_avgPeriod) : ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryShort_rangeType == 2) ? 2.0 : 1.0)))) && (((inClose[i] >= inOpen[i]) ? inOpen[i] : inClose[i]) - inLow[i]) > ((ShadowVeryLong_factor * (((ShadowVeryLong_avgPeriod != 0) ? (ShadowVeryLongPeriodTotal / ShadowVeryLong_avgPeriod) : ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((ShadowVeryLong_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyDojiPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx]) - Math.abs(inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx])) : 0.0)));
             ShadowVeryShortPeriodTotal += ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryShort_rangeType == 0) ? (Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : ((ShadowVeryShort_rangeType == 1) ? (inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) : ((ShadowVeryShort_rangeType == 2) ? ((inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx]) - Math.abs(inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx])) : 0.0)));
             ShadowVeryLongPeriodTotal += ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((ShadowVeryLong_rangeType == 0) ? (Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : ((ShadowVeryLong_rangeType == 1) ? (inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) : ((ShadowVeryLong_rangeType == 2) ? ((inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx]) - Math.abs(inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx])) : 0.0)));
             i += 1;
             BodyDojiTrailingIdx += 1;
             ShadowVeryShortTrailingIdx += 1;
             ShadowVeryLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011605 AC   Creation
     */

       public int cdlTasukiGapLookback( )
       {
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          return Near_avgPeriod + 2 ;

       }
       public RetCode cdlTasukiGap( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlTasukiGapLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - upside (downside) gap
           * - first candle after the window: white (black) candlestick
           * - second candle: black (white) candlestick that opens within the previous real body and closes under (above)
           *   the previous real body inside the gap
           * - the size of two real bodies should be near the same
           * The meaning of "near" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that tasuki gap is significant when it appears in a trend, while this function does
           * not consider it
           */
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inClose[i - 1] && inOpen[i] > inOpen[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > Math.max(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < Math.min(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                /* upside gap */
                /* 1st: white */
                /* 2nd: black */
                /* that opens within the white rb */
                /* and closes under the white rb */
                /* inside the gap */
                /* size of 2 rb near the same */
                /* downside gap */
                /* 1st: black */
                /* 2nd: white */
                /* that opens within the black rb */
                /* and closes above the black rb */
                /* inside the gap */
                /* size of 2 rb near the same */
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTasukiGapUnguarded( int startIdx,
                                             int endIdx,
                                             double inOpen[],
                                             double inHigh[],
                                             double inLow[],
                                             double inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlTasukiGapLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inClose[i - 1] && inOpen[i] > inOpen[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > Math.max(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < Math.min(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTasukiGap( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlTasukiGapLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inClose[i - 1] && inOpen[i] > inOpen[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > Math.max(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < Math.min(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTasukiGapUnguarded( int startIdx,
                                             int endIdx,
                                             float inOpen[],
                                             float inHigh[],
                                             float inLow[],
                                             float inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double NearPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int NearTrailingIdx = 0;
          int lookbackTotal = 0;
          int Near_rangeType = this.candleSettings[CandleSettingType.Near.ordinal()].rangeType.ordinal();
          int Near_avgPeriod = this.candleSettings[CandleSettingType.Near.ordinal()].avgPeriod;
          double Near_factor = this.candleSettings[CandleSettingType.Near.ordinal()].factor;
          lookbackTotal = cdlTasukiGapLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          NearPeriodTotal = 0;
          NearTrailingIdx = startIdx - Near_avgPeriod;
          i = NearTrailingIdx;
          while( i < startIdx ) {
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] < inClose[i - 1] && inOpen[i] > inOpen[i - 1] && inClose[i] < inOpen[i - 1] && inClose[i] > Math.max(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) || (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inOpen[i - 1] && inOpen[i] > inClose[i - 1] && inClose[i] > inOpen[i - 1] && inClose[i] < Math.min(inClose[i - 2], inOpen[i - 2]) && Math.abs(Math.abs(inClose[i - 1] - inOpen[i - 1]) - Math.abs(inClose[i] - inOpen[i])) < ((Near_factor * (((Near_avgPeriod != 0) ? (NearPeriodTotal / Near_avgPeriod) : ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Near_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             NearPeriodTotal += ((Near_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Near_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Near_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Near_rangeType == 0) ? (Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : ((Near_rangeType == 1) ? (inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) : ((Near_rangeType == 2) ? ((inHigh[NearTrailingIdx - 1] - inLow[NearTrailingIdx - 1]) - Math.abs(inClose[NearTrailingIdx - 1] - inOpen[NearTrailingIdx - 1])) : 0.0)));
             i += 1;
             NearTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  121204 AC   Creation
     */

       public int cdlThrustingLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          return Math.max(Equal_avgPeriod, BodyLong_avgPeriod) + 1 ;

       }
       public RetCode cdlThrusting( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlThrustingLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: white candle with open below previous day low and close into previous day body under the midpoint;
           * to differentiate it from in-neck the close should not be equal to the black candle's close
           * The meaning of "equal" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): thrusting pattern is always bearish
           * the user should consider that the thrusting pattern is significant when it appears in a downtrend and it could be
           * even bullish "when coming in an uptrend or occurring twice within several days" (Steve Nison says), while this
           * function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 1st: black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* 2nd: white */
                 inOpen[i] < inLow[i - 1] &&                                 /* open below prior low */
                 inClose[i] > inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && /* close into prior body */
                 inClose[i] <= inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) /* under the midpoint */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlThrustingUnguarded( int startIdx,
                                             int endIdx,
                                             double inOpen[],
                                             double inHigh[],
                                             double inLow[],
                                             double inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlThrustingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] > inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlThrusting( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlThrustingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] > inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlThrustingUnguarded( int startIdx,
                                             int endIdx,
                                             float inOpen[],
                                             float inHigh[],
                                             float inLow[],
                                             float inClose[],
                                             MInteger outBegIdx,
                                             MInteger outNBElement,
                                             int outInteger[] )
       {
          double EqualPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int EqualTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int Equal_rangeType = this.candleSettings[CandleSettingType.Equal.ordinal()].rangeType.ordinal();
          int Equal_avgPeriod = this.candleSettings[CandleSettingType.Equal.ordinal()].avgPeriod;
          double Equal_factor = this.candleSettings[CandleSettingType.Equal.ordinal()].factor;
          lookbackTotal = cdlThrustingLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          EqualPeriodTotal = 0;
          EqualTrailingIdx = startIdx - Equal_avgPeriod;
          BodyLongPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - BodyLong_avgPeriod;
          i = EqualTrailingIdx;
          while( i < startIdx ) {
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = BodyLongTrailingIdx;
          while( i < startIdx ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inOpen[i] < inLow[i - 1] && inClose[i] > inClose[i - 1] + ((Equal_factor * (((Equal_avgPeriod != 0) ? (EqualPeriodTotal / Equal_avgPeriod) : ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((Equal_rangeType == 2) ? 2.0 : 1.0)))) && inClose[i] <= inClose[i - 1] + Math.abs(inClose[i - 1] - inOpen[i - 1]) * 0.5 ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             EqualPeriodTotal += ((Equal_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((Equal_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((Equal_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((Equal_rangeType == 0) ? (Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : ((Equal_rangeType == 1) ? (inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) : ((Equal_rangeType == 2) ? ((inHigh[EqualTrailingIdx - 1] - inLow[EqualTrailingIdx - 1]) - Math.abs(inClose[EqualTrailingIdx - 1] - inOpen[EqualTrailingIdx - 1])) : 0.0)));
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx - 1] - inLow[BodyLongTrailingIdx - 1]) - Math.abs(inClose[BodyLongTrailingIdx - 1] - inOpen[BodyLongTrailingIdx - 1])) : 0.0)));
             i += 1;
             EqualTrailingIdx += 1;
             BodyLongTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *  CSB      Christopher Barnhouse
     *
     * Change history:
     *
     *  MMDDYY BY      Description
     *  -------------------------------------------------------------------
     *  100204 AC      Creation
     *  051005 CSB,AC  Fix #1199526 for out-of-bound write in output.
     */

       public int cdlTristarLookback( )
       {
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          return BodyDoji_avgPeriod + 2 ;

       }
       public RetCode cdlTristar( int startIdx,
                                  int endIdx,
                                  double inOpen[],
                                  double inHigh[],
                                  double inLow[],
                                  double inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlTristarLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - 2 - BodyDoji_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - 3 consecutive doji days
           * - the second doji is a star
           * The meaning of "doji" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish
           */
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: doji */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && /* 2nd: doji */
                 Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) )
             {
                /* 3rd: doji */
                outInteger[outIdx] = 0;
                if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && /* 2nd gaps up */
                    Math.max(inOpen[i], inClose[i]) < Math.max(inOpen[i - 1], inClose[i - 1]) ) /* 3rd is not higher than 2nd */
                {
                   outInteger[outIdx] = 0 - 100;
                }
                if( (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && /* 2nd gaps down */
                    Math.min(inOpen[i], inClose[i]) > Math.min(inOpen[i - 1], inClose[i - 1]) ) /* 3rd is not lower than 2nd */
                {
                   outInteger[outIdx] = 100;
                }
                outIdx += 1;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTristarUnguarded( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          lookbackTotal = cdlTristarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - 2 - BodyDoji_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx] = 0;
                if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && Math.max(inOpen[i], inClose[i]) < Math.max(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 0 - 100;
                }
                if( (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && Math.min(inOpen[i], inClose[i]) > Math.min(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 100;
                }
                outIdx += 1;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTristar( int startIdx,
                                  int endIdx,
                                  float inOpen[],
                                  float inHigh[],
                                  float inLow[],
                                  float inClose[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlTristarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - 2 - BodyDoji_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx] = 0;
                if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && Math.max(inOpen[i], inClose[i]) < Math.max(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 0 - 100;
                }
                if( (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && Math.min(inOpen[i], inClose[i]) > Math.min(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 100;
                }
                outIdx += 1;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlTristarUnguarded( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          double BodyPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyDoji_rangeType = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].rangeType.ordinal();
          int BodyDoji_avgPeriod = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].avgPeriod;
          double BodyDoji_factor = this.candleSettings[CandleSettingType.BodyDoji.ordinal()].factor;
          lookbackTotal = cdlTristarLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyPeriodTotal = 0;
          BodyTrailingIdx = startIdx - 2 - BodyDoji_avgPeriod;
          i = BodyTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyDoji_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( Math.abs(inClose[i - 2] - inOpen[i - 2]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) <= ((BodyDoji_factor * (((BodyDoji_avgPeriod != 0) ? (BodyPeriodTotal / BodyDoji_avgPeriod) : ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyDoji_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx] = 0;
                if( (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && Math.max(inOpen[i], inClose[i]) < Math.max(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 0 - 100;
                }
                if( (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2])) && Math.min(inOpen[i], inClose[i]) > Math.min(inOpen[i - 1], inClose[i - 1]) ) {
                   outInteger[outIdx] = 100;
                }
                outIdx += 1;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyPeriodTotal += ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyDoji_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyDoji_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyDoji_rangeType == 0) ? (Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : ((BodyDoji_rangeType == 1) ? (inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) : ((BodyDoji_rangeType == 2) ? ((inHigh[BodyTrailingIdx] - inLow[BodyTrailingIdx]) - Math.abs(inClose[BodyTrailingIdx] - inOpen[BodyTrailingIdx])) : 0.0)));
             i += 1;
             BodyTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  022005 AC   Creation
     */

       public int cdlUnique3RiverLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdlUnique3River( int startIdx,
                                       int endIdx,
                                       double inOpen[],
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlUnique3RiverLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: long black candle
           * - second candle: black harami candle with a lower low than the first candle's low
           * - third candle: small white candle with open not lower than the second candle's low, better if its open and
           *   close are under the second candle's close
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * outInteger is positive (1 to 100): unique 3 river is always bullish and should appear in a downtrend
           * to be significant, while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && /* black */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd: black */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 &&             /* white */
                 inClose[i - 1] > inClose[i - 2] &&
                 inOpen[i - 1] <= inOpen[i - 2] &&                           /* harami */
                 inLow[i - 1] < inLow[i - 2] &&                              /* lower low */
                 inOpen[i] > inLow[i - 1] &&                                 /* open not lower */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* 1st: long */
                 Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) /* 3rd: short */
             {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUnique3RiverUnguarded( int startIdx,
                                                int endIdx,
                                                double inOpen[],
                                                double inHigh[],
                                                double inLow[],
                                                double inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlUnique3RiverLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inOpen[i - 2] && inLow[i - 1] < inLow[i - 2] && inOpen[i] > inLow[i - 1] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUnique3River( int startIdx,
                                       int endIdx,
                                       float inOpen[],
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlUnique3RiverLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inOpen[i - 2] && inLow[i - 1] < inLow[i - 2] && inOpen[i] > inLow[i - 1] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUnique3RiverUnguarded( int startIdx,
                                                int endIdx,
                                                float inOpen[],
                                                float inHigh[],
                                                float inLow[],
                                                float inClose[],
                                                MInteger outBegIdx,
                                                MInteger outNBElement,
                                                int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlUnique3RiverLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 1 && inClose[i - 1] > inClose[i - 2] && inOpen[i - 1] <= inOpen[i - 2] && inLow[i - 1] < inLow[i - 2] && inOpen[i] > inLow[i - 1] && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && Math.abs(inClose[i] - inOpen[i]) < ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) ) {
                outInteger[outIdx++] = 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  110104 AC   Creation
     */

       public int cdlUpsideGap2CrowsLookback( )
       {
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          return Math.max(BodyShort_avgPeriod, BodyLong_avgPeriod) + 2 ;

       }
       public RetCode cdlUpsideGap2Crows( int startIdx,
                                          int endIdx,
                                          double inOpen[],
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlUpsideGap2CrowsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: white candle, usually long
           * - second candle: small black real body
           * - gap between the first and the second candle's real bodies
           * - third candle: black candle with a real body that engulfs the preceding candle
           *   and closes above the white candle's close
           * The meaning of "short" and "long" is specified with TA_SetCandleSettings
           * outInteger is negative (-1 to -100): upside gap two crows is always bearish;
           * the user should consider that an upside gap two crows is significant when it appears in an uptrend,
           * while this function does not consider the trend
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 &&     /* 1st: white */
                 Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && /* long */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && /* 2nd: black */
                 Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && /* short */
                 (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && /* gapping up */
                 ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 &&         /* 3rd: black */
                 inOpen[i] > inOpen[i - 1] &&
                 inClose[i] < inClose[i - 1] &&                              /* 3rd: engulfing prior rb */
                 inClose[i] > inClose[i - 2] )                               /* closing above 1st */
             {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUpsideGap2CrowsUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inOpen[],
                                                   double inHigh[],
                                                   double inLow[],
                                                   double inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlUpsideGap2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] && inClose[i] > inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUpsideGap2Crows( int startIdx,
                                          int endIdx,
                                          float inOpen[],
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlUpsideGap2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] && inClose[i] > inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlUpsideGap2CrowsUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inOpen[],
                                                   float inHigh[],
                                                   float inLow[],
                                                   float inClose[],
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   int outInteger[] )
       {
          double BodyShortPeriodTotal = 0;
          double BodyLongPeriodTotal = 0;
          int i = 0;
          int outIdx = 0;
          int BodyShortTrailingIdx = 0;
          int BodyLongTrailingIdx = 0;
          int lookbackTotal = 0;
          int BodyLong_rangeType = this.candleSettings[CandleSettingType.BodyLong.ordinal()].rangeType.ordinal();
          int BodyLong_avgPeriod = this.candleSettings[CandleSettingType.BodyLong.ordinal()].avgPeriod;
          double BodyLong_factor = this.candleSettings[CandleSettingType.BodyLong.ordinal()].factor;
          int BodyShort_rangeType = this.candleSettings[CandleSettingType.BodyShort.ordinal()].rangeType.ordinal();
          int BodyShort_avgPeriod = this.candleSettings[CandleSettingType.BodyShort.ordinal()].avgPeriod;
          double BodyShort_factor = this.candleSettings[CandleSettingType.BodyShort.ordinal()].factor;
          lookbackTotal = cdlUpsideGap2CrowsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          BodyLongPeriodTotal = 0;
          BodyShortPeriodTotal = 0;
          BodyLongTrailingIdx = startIdx - 2 - BodyLong_avgPeriod;
          BodyShortTrailingIdx = startIdx - 1 - BodyShort_avgPeriod;
          i = BodyLongTrailingIdx;
          while( i < startIdx - 2 ) {
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyLong_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyLong_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = BodyShortTrailingIdx;
          while( i < startIdx - 1 ) {
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i] - inOpen[i])) : ((BodyShort_rangeType == 1) ? (inHigh[i] - inLow[i]) : ((BodyShort_rangeType == 2) ? ((inHigh[i] - inLow[i]) - Math.abs(inClose[i] - inOpen[i])) : 0.0)));
             i += 1;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && Math.abs(inClose[i - 2] - inOpen[i - 2]) > ((BodyLong_factor * (((BodyLong_avgPeriod != 0) ? (BodyLongPeriodTotal / BodyLong_avgPeriod) : ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0)))) / ((BodyLong_rangeType == 2) ? 2.0 : 1.0)))) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - 1 && Math.abs(inClose[i - 1] - inOpen[i - 1]) <= ((BodyShort_factor * (((BodyShort_avgPeriod != 0) ? (BodyShortPeriodTotal / BodyShort_avgPeriod) : ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0)))) / ((BodyShort_rangeType == 2) ? 2.0 : 1.0)))) && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) && ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) == 0 - 1 && inOpen[i] > inOpen[i - 1] && inClose[i] < inClose[i - 1] && inClose[i] > inClose[i - 2] ) {
                outInteger[outIdx++] = 0 - 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             BodyLongPeriodTotal += ((BodyLong_rangeType == 0) ? (Math.abs(inClose[i - 2] - inOpen[i - 2])) : ((BodyLong_rangeType == 1) ? (inHigh[i - 2] - inLow[i - 2]) : ((BodyLong_rangeType == 2) ? ((inHigh[i - 2] - inLow[i - 2]) - Math.abs(inClose[i - 2] - inOpen[i - 2])) : 0.0))) - ((BodyLong_rangeType == 0) ? (Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : ((BodyLong_rangeType == 1) ? (inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) : ((BodyLong_rangeType == 2) ? ((inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx]) - Math.abs(inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx])) : 0.0)));
             BodyShortPeriodTotal += ((BodyShort_rangeType == 0) ? (Math.abs(inClose[i - 1] - inOpen[i - 1])) : ((BodyShort_rangeType == 1) ? (inHigh[i - 1] - inLow[i - 1]) : ((BodyShort_rangeType == 2) ? ((inHigh[i - 1] - inLow[i - 1]) - Math.abs(inClose[i - 1] - inOpen[i - 1])) : 0.0))) - ((BodyShort_rangeType == 0) ? (Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : ((BodyShort_rangeType == 1) ? (inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) : ((BodyShort_rangeType == 2) ? ((inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx]) - Math.abs(inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx])) : 0.0)));
             i += 1;
             BodyLongTrailingIdx += 1;
             BodyShortTrailingIdx += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  011605 AC   Creation
     */

       public int cdlXSideGap3MethodsLookback( )
       {
          return 2 ;

       }
       public RetCode cdlXSideGap3Methods( int startIdx,
                                           int endIdx,
                                           double inOpen[],
                                           double inHigh[],
                                           double inLow[],
                                           double inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = cdlXSideGap3MethodsLookback();
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          i = startIdx;
          /* Proceed with the calculation for the requested range.
           * Must have:
           * - first candle: white (black) candle
           * - second candle: white (black) candle
           * - upside (downside) gap between the first and the second real bodies
           * - third candle: black (white) candle that opens within the second real body and closes within the first real body
           * outInteger is positive (1 to 100) when bullish or negative (-1 to -100) when bearish;
           * the user should consider that up/downside gap 3 methods is significant when it appears in a trend, while this
           * function does not consider it
           */
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && /* 1st and 2nd of same color */
                 ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && /* 3rd opposite color */
                 inOpen[i] < Math.max(inClose[i - 1], inOpen[i - 1]) &&  /* 3rd opens within 2nd rb */
                 inOpen[i] > Math.min(inClose[i - 1], inOpen[i - 1]) &&
                 inClose[i] < Math.max(inClose[i - 2], inOpen[i - 2]) && /* 3rd closes within 1st rb */
                 inClose[i] > Math.min(inClose[i - 2], inOpen[i - 2]) &&
                 (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2]))) ) /* when 1st is white upside gap when 1st is black downside gap */
             {
                outInteger[outIdx++] = ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             /* add the current range and subtract the first range: this is done after the pattern recognition
              * when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
              */
             i += 1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlXSideGap3MethodsUnguarded( int startIdx,
                                                    int endIdx,
                                                    double inOpen[],
                                                    double inHigh[],
                                                    double inLow[],
                                                    double inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdlXSideGap3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] < Math.max(inClose[i - 1], inOpen[i - 1]) && inOpen[i] > Math.min(inClose[i - 1], inOpen[i - 1]) && inClose[i] < Math.max(inClose[i - 2], inOpen[i - 2]) && inClose[i] > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2]))) ) {
                outInteger[outIdx++] = ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlXSideGap3Methods( int startIdx,
                                           int endIdx,
                                           float inOpen[],
                                           float inHigh[],
                                           float inLow[],
                                           float inClose[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          lookbackTotal = cdlXSideGap3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] < Math.max(inClose[i - 1], inOpen[i - 1]) && inOpen[i] > Math.min(inClose[i - 1], inOpen[i - 1]) && inClose[i] < Math.max(inClose[i - 2], inOpen[i - 2]) && inClose[i] > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2]))) ) {
                outInteger[outIdx++] = ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cdlXSideGap3MethodsUnguarded( int startIdx,
                                                    int endIdx,
                                                    float inOpen[],
                                                    float inHigh[],
                                                    float inLow[],
                                                    float inClose[],
                                                    MInteger outBegIdx,
                                                    MInteger outNBElement,
                                                    int outInteger[] )
       {
          int i = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = cdlXSideGap3MethodsLookback();
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          i = startIdx;
          outIdx = 0;
          do {
             if( ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) && ((inClose[i - 1] >= inOpen[i - 1]) ? 1 : 0 - 1) == 0 - ((inClose[i] >= inOpen[i]) ? 1 : 0 - 1) && inOpen[i] < Math.max(inClose[i - 1], inOpen[i - 1]) && inOpen[i] > Math.min(inClose[i - 1], inOpen[i - 1]) && inClose[i] < Math.max(inClose[i - 2], inOpen[i - 2]) && inClose[i] > Math.min(inClose[i - 2], inOpen[i - 2]) && (((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 1 && (Math.min(inOpen[i - 1], inClose[i - 1]) > Math.max(inOpen[i - 2], inClose[i - 2])) || ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) == 0 - 1 && (Math.max(inOpen[i - 1], inClose[i - 1]) < Math.min(inOpen[i - 2], inClose[i - 2]))) ) {
                outInteger[outIdx++] = ((inClose[i - 2] >= inOpen[i - 2]) ? 1 : 0 - 1) * 100;
             } else {
                outInteger[outIdx++] = 0;
             }
             i += 1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int ceilLookback( )
       {
          return 0 ;

       }
       public RetCode ceil( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.ceil(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ceilUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.ceil(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ceil( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.ceil(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ceilUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.ceil(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  BT       Barry Tsung
     *
     * Change history:
     *
     *  MMDDYY BY      Description
     *  -------------------------------------------------------------------
     *  112605 MF      Initial version.
     *  021806 MF,BT   Fix #1434450 reported by BT.
     */

       public int cmoLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          int retValue;
          retValue = optInTimePeriod + this.unstablePeriod[FuncUnstId.Cmo.ordinal()];
          if( this.compatibility == Compatibility.Metastock ) {
             retValue -= 1;
          }
          return retValue ;

       }
       public RetCode cmo( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          double tempValue3 = 0;
          double tempValue4 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* CMO calculation is mostly identical to RSI.
           *
           * The only difference is in the last step of calculation:
           *
           *   RSI = gain / (gain+loss)
           *   CMO = (gain-loss) / (gain+loss)
           *
           * See the RSI function for potentially some more info
           * on this algo.
           */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = cmoLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          /* Trap special case where the period is '1'.
           * In that case, just copy the input into the
           * output for the requested range (as-is !)
           */
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = endIdx - startIdx + 1;
             outNBElement.value = i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          /* Accumulate Wilder's "Average Gain" and "Average Loss"
           * among the initial period.
           */
          today = startIdx - lookbackTotal;
          prevValue = inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Cmo.ordinal()];
          /* If there is no unstable period,
           * calculate the 'additional' initial
           * price bar who is particuliar to
           * metastock.
           * If there is an unstable period,
           * no need to calculate since this
           * first value will be surely skip.
           */
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             /* Preserve prevValue because it may get
              * overwritten by the output.
              * (because output ptr could be the same as input ptr).
              */
             savePrevValue = prevValue;
             /* No unstable period, so must calculate first output
              * particular to Metastock.
              * (Metastock re-use the first price bar, so there
              *  is no loss/gain at first. Beats me why they
              *  are doing all this).
              */
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = inReal[today++];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / optInTimePeriod;
             tempValue2 = prevGain / optInTimePeriod;
             tempValue3 = tempValue2 - tempValue1;
             tempValue4 = tempValue1 + tempValue2;
             /* Write the output. */
             if( !((-0.00000000000001 < tempValue4) && (tempValue4 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100 * (tempValue3 / tempValue4);
             } else {
                outReal[outIdx++] = 0.0;
             }
             /* Are we done? */
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             /* Start over for the next price bar. */
             today -= optInTimePeriod;
             prevValue = savePrevValue;
          }
          /* Remaining of the processing is identical
           * for both Classic calculation and Metastock.
           */
          prevGain = 0.0;
          prevLoss = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          /* Subsequent prevLoss and prevGain are smoothed
           * using the previous values (Wilder's approach).
           *  1) Multiply the previous by 'period-1'.
           *  2) Add today value.
           *  3) Divide by 'period'.
           */
          prevLoss /= optInTimePeriod;
          prevGain /= optInTimePeriod;
          /* Often documentation present the RSI calculation as follow:
           *    RSI = 100 - (100 / 1 + (prevGain/prevLoss))
           *
           * The following is equivalent:
           *    RSI = 100 * (prevGain/(prevGain+prevLoss))
           *
           * The second equation is used here for speed optimization.
           */
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          } else {
             /* Skip the unstable period. Do the processing
              * but do not write it in the output.
              */
             while( today < startIdx ) {
                tempValue1 = inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= optInTimePeriod - 1;
                prevGain *= optInTimePeriod - 1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= optInTimePeriod;
                prevGain /= optInTimePeriod;
                today += 1;
             }
          }
          /* Unstable period skipped... now continue
           * processing if needed.
           */
          while( today <= endIdx ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= optInTimePeriod - 1;
             prevGain *= optInTimePeriod - 1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= optInTimePeriod;
             prevGain /= optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode cmoUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          double tempValue3 = 0;
          double tempValue4 = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = cmoLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = endIdx - startIdx + 1;
             outNBElement.value = i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Cmo.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = inReal[today++];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / optInTimePeriod;
             tempValue2 = prevGain / optInTimePeriod;
             tempValue3 = tempValue2 - tempValue1;
             tempValue4 = tempValue1 + tempValue2;
             if( !((-0.00000000000001 < tempValue4) && (tempValue4 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100 * (tempValue3 / tempValue4);
             } else {
                outReal[outIdx++] = 0.0;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today -= optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= optInTimePeriod;
          prevGain /= optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= optInTimePeriod - 1;
                prevGain *= optInTimePeriod - 1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= optInTimePeriod;
                prevGain /= optInTimePeriod;
                today += 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= optInTimePeriod - 1;
             prevGain *= optInTimePeriod - 1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= optInTimePeriod;
             prevGain /= optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode cmo( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          double tempValue3 = 0;
          double tempValue4 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = cmoLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = endIdx - startIdx + 1;
             outNBElement.value = i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Cmo.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = inReal[today++];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / optInTimePeriod;
             tempValue2 = prevGain / optInTimePeriod;
             tempValue3 = tempValue2 - tempValue1;
             tempValue4 = tempValue1 + tempValue2;
             if( !((-0.00000000000001 < tempValue4) && (tempValue4 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100 * (tempValue3 / tempValue4);
             } else {
                outReal[outIdx++] = 0.0;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today -= optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= optInTimePeriod;
          prevGain /= optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= optInTimePeriod - 1;
                prevGain *= optInTimePeriod - 1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= optInTimePeriod;
                prevGain /= optInTimePeriod;
                today += 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= optInTimePeriod - 1;
             prevGain *= optInTimePeriod - 1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= optInTimePeriod;
             prevGain /= optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode cmoUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          double tempValue3 = 0;
          double tempValue4 = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = cmoLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = endIdx - startIdx + 1;
             outNBElement.value = i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Cmo.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = inReal[today++];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / optInTimePeriod;
             tempValue2 = prevGain / optInTimePeriod;
             tempValue3 = tempValue2 - tempValue1;
             tempValue4 = tempValue1 + tempValue2;
             if( !((-0.00000000000001 < tempValue4) && (tempValue4 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100 * (tempValue3 / tempValue4);
             } else {
                outReal[outIdx++] = 0.0;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today -= optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= optInTimePeriod;
          prevGain /= optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= optInTimePeriod - 1;
                prevGain *= optInTimePeriod - 1;
                if( tempValue2 < 0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= optInTimePeriod;
                prevGain /= optInTimePeriod;
                today += 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = inReal[today++];
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= optInTimePeriod - 1;
             prevGain *= optInTimePeriod - 1;
             if( tempValue2 < 0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= optInTimePeriod;
             prevGain /= optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx++] = 100.0 * ((prevGain - prevLoss) / tempValue1);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  101003 MF   Initial Coding
     *  062804 MF   Resolve div by zero bug on limit case.
     */

       public int correlLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode correl( int startIdx,
                              int endIdx,
                              double inReal0[],
                              double inReal1[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          double sumXY = 0;
          double sumX = 0;
          double sumY = 0;
          double sumX2 = 0;
          double sumY2 = 0;
          double x = 0;
          double y = 0;
          double trailingX = 0;
          double trailingY = 0;
          double tempReal = 0;
          int lookbackTotal = 0;
          int today = 0;
          int trailingIdx = 0;
          int outIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Move up the start index if there is not
           * enough initial data.
           */
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingIdx = startIdx - lookbackTotal;
          /* Calculate the initial values. */
          sumY2 = 0.0;
          sumX2 = sumY2;
          sumY = sumX2;
          sumX = sumY;
          sumXY = sumX;
          for( today = trailingIdx; today <= startIdx; today += 1 ) {
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
          }
          /* Write the first output.
           * Save first the trailing values since the input
           * and output might be the same array,
           */
          trailingX = inReal0[trailingIdx];
          trailingY = inReal1[trailingIdx++];
          tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
          if( !(tempReal < 0.00000000000001) ) {
             outReal[0] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
          } else {
             outReal[0] = 0.0;
          }
          /* Tight loop to do subsequent values. */
          outIdx = 1;
          while( today <= endIdx ) {
             /* Remove trailing values */
             sumX -= trailingX;
             sumX2 -= trailingX * trailingX;
             sumXY -= trailingX * trailingY;
             sumY -= trailingY;
             sumY2 -= trailingY * trailingY;
             /* Add new values */
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today++];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
             /* Output new coefficient.
              * Save first the trailing values since the input
              * and output might be the same array,
              */
             trailingX = inReal0[trailingIdx];
             trailingY = inReal1[trailingIdx++];
             tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
             if( !(tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode correlUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal0[],
                                       double inReal1[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          double sumXY = 0;
          double sumX = 0;
          double sumY = 0;
          double sumX2 = 0;
          double sumY2 = 0;
          double x = 0;
          double y = 0;
          double trailingX = 0;
          double trailingY = 0;
          double tempReal = 0;
          int lookbackTotal = 0;
          int today = 0;
          int trailingIdx = 0;
          int outIdx = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingIdx = startIdx - lookbackTotal;
          sumY2 = 0.0;
          sumX2 = sumY2;
          sumY = sumX2;
          sumX = sumY;
          sumXY = sumX;
          for( today = trailingIdx; today <= startIdx; today += 1 ) {
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
          }
          trailingX = inReal0[trailingIdx];
          trailingY = inReal1[trailingIdx++];
          tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
          if( !(tempReal < 0.00000000000001) ) {
             outReal[0] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today <= endIdx ) {
             sumX -= trailingX;
             sumX2 -= trailingX * trailingX;
             sumXY -= trailingX * trailingY;
             sumY -= trailingY;
             sumY2 -= trailingY * trailingY;
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today++];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
             trailingX = inReal0[trailingIdx];
             trailingY = inReal1[trailingIdx++];
             tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
             if( !(tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode correl( int startIdx,
                              int endIdx,
                              float inReal0[],
                              float inReal1[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          double sumXY = 0;
          double sumX = 0;
          double sumY = 0;
          double sumX2 = 0;
          double sumY2 = 0;
          double x = 0;
          double y = 0;
          double trailingX = 0;
          double trailingY = 0;
          double tempReal = 0;
          int lookbackTotal = 0;
          int today = 0;
          int trailingIdx = 0;
          int outIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingIdx = startIdx - lookbackTotal;
          sumY2 = 0.0;
          sumX2 = sumY2;
          sumY = sumX2;
          sumX = sumY;
          sumXY = sumX;
          for( today = trailingIdx; today <= startIdx; today += 1 ) {
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
          }
          trailingX = inReal0[trailingIdx];
          trailingY = inReal1[trailingIdx++];
          tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
          if( !(tempReal < 0.00000000000001) ) {
             outReal[0] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today <= endIdx ) {
             sumX -= trailingX;
             sumX2 -= trailingX * trailingX;
             sumXY -= trailingX * trailingY;
             sumY -= trailingY;
             sumY2 -= trailingY * trailingY;
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today++];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
             trailingX = inReal0[trailingIdx];
             trailingY = inReal1[trailingIdx++];
             tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
             if( !(tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode correlUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal0[],
                                       float inReal1[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          double sumXY = 0;
          double sumX = 0;
          double sumY = 0;
          double sumX2 = 0;
          double sumY2 = 0;
          double x = 0;
          double y = 0;
          double trailingX = 0;
          double trailingY = 0;
          double tempReal = 0;
          int lookbackTotal = 0;
          int today = 0;
          int trailingIdx = 0;
          int outIdx = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingIdx = startIdx - lookbackTotal;
          sumY2 = 0.0;
          sumX2 = sumY2;
          sumY = sumX2;
          sumX = sumY;
          sumXY = sumX;
          for( today = trailingIdx; today <= startIdx; today += 1 ) {
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
          }
          trailingX = inReal0[trailingIdx];
          trailingY = inReal1[trailingIdx++];
          tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
          if( !(tempReal < 0.00000000000001) ) {
             outReal[0] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today <= endIdx ) {
             sumX -= trailingX;
             sumX2 -= trailingX * trailingX;
             sumXY -= trailingX * trailingY;
             sumY -= trailingY;
             sumY2 -= trailingY * trailingY;
             x = inReal0[today];
             sumX += x;
             sumX2 += x * x;
             y = inReal1[today++];
             sumXY += x * y;
             sumY += y;
             sumY2 += y * y;
             trailingX = inReal0[trailingIdx];
             trailingY = inReal1[trailingIdx++];
             tempReal = (sumX2 - sumX * sumX / optInTimePeriod) * (sumY2 - sumY * sumY / optInTimePeriod);
             if( !(tempReal < 0.00000000000001) ) {
                outReal[outIdx++] = (sumXY - sumX * sumY / optInTimePeriod) / Math.sqrt(tempReal);
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int cosLookback( )
       {
          return 0 ;

       }
       public RetCode cos( int startIdx,
                           int endIdx,
                           double inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cosUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cos( int startIdx,
                           int endIdx,
                           float inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cosUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cos(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int coshLookback( )
       {
          return 0 ;

       }
       public RetCode cosh( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cosh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode coshUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cosh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode cosh( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cosh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode coshUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.cosh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010102 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int demaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          /* Get lookback for one EMA.
           * Multiply by two (because double smoothing).
           */
          return emaLookback(optInTimePeriod) * 2 ;

       }
       public RetCode dema( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int firstEMAIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* For an explanation of this function, please read
           *
           * Stocks & Commodities V. 12:1 (11-19):
           *   Smoothing Data With Faster Moving Averages
           * Stocks & Commodities V. 12:2 (72-80):
           *   Smoothing Data With Less Lag
           *
           * Both magazine articles written by Patrick G. Mulloy
           *
           * Essentially, a DEMA of time serie 't' is:
           *   EMA2 = EMA(EMA(t,period),period)
           *   DEMA = 2*EMA(t,period)- EMA2
           *
           * DEMA offers a moving average with less lags then the
           * traditional EMA.
           *
           * Do not confuse a DEMA with the EMA2. Both are called
           * "Double EMA" in the litterature, but EMA2 is a simple
           * EMA of an EMA, while DEMA is a compostie of a single
           * EMA with EMA2.
           *
           * TEMA is very similar (and from the same author).
           */
          /* Will change only on success. */
          outNBElement.value = 0;
          outBegIdx.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 2;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          /* Allocate a temporary buffer for the firstEMA.
           *
           * When possible, re-use the outputBuffer for temp
           * calculation.
           */
          if( inReal == outReal ) {
             firstEMA = outReal;
          } else {
             tempInt = lookbackTotal + (endIdx - startIdx) + 1;
             firstEMA = new double[(int)(tempInt * 1)];
          }
          /* Calculate the first EMA */
          retCode = emaUnguarded(startIdx - lookbackEMA, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          /* Verify for failure or if not enough data after
           * calculating the first EMA.
           */
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          /* Allocate a temporary buffer for storing the EMA of the EMA. */
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          /* Return empty output on failure or if not enough data after
           * calculating the second EMA.
           */
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          /* Iterate through the second EMA and write the DEMA into
           * the output.
           */
          firstEMAIdx = secondEMABegIdx.value;
          outIdx = 0;
          while( outIdx < secondEMANbElement.value ) {
             outReal[outIdx] = 2.0 * firstEMA[firstEMAIdx++] - secondEMA[outIdx];
             outIdx += 1;
          }
          if( firstEMA != outReal ) {
          }
          /* Succeed. Indicate where the output starts relative to
           * the caller input.
           */
          outBegIdx.value = firstEMABegIdx.value + secondEMABegIdx.value;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode demaUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int firstEMAIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          RetCode retCode;
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 2;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( inReal == outReal ) {
             firstEMA = outReal;
          } else {
             tempInt = lookbackTotal + (endIdx - startIdx) + 1;
             firstEMA = new double[(int)(tempInt * 1)];
          }
          retCode = emaUnguarded(startIdx - lookbackEMA, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          firstEMAIdx = secondEMABegIdx.value;
          outIdx = 0;
          while( outIdx < secondEMANbElement.value ) {
             outReal[outIdx] = 2.0 * firstEMA[firstEMAIdx++] - secondEMA[outIdx];
             outIdx += 1;
          }
          if( firstEMA != outReal ) {
          }
          outBegIdx.value = firstEMABegIdx.value + secondEMABegIdx.value;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode dema( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int firstEMAIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 2;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( false ) {
             firstEMA = outReal;
          } else {
             tempInt = lookbackTotal + (endIdx - startIdx) + 1;
             firstEMA = new double[(int)(tempInt * 1)];
          }
          retCode = emaUnguarded(startIdx - lookbackEMA, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          firstEMAIdx = secondEMABegIdx.value;
          outIdx = 0;
          while( outIdx < secondEMANbElement.value ) {
             outReal[outIdx] = 2.0 * firstEMA[firstEMAIdx++] - secondEMA[outIdx];
             outIdx += 1;
          }
          if( firstEMA != outReal ) {
          }
          outBegIdx.value = firstEMABegIdx.value + secondEMABegIdx.value;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode demaUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int firstEMAIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          RetCode retCode;
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 2;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( false ) {
             firstEMA = outReal;
          } else {
             tempInt = lookbackTotal + (endIdx - startIdx) + 1;
             firstEMA = new double[(int)(tempInt * 1)];
          }
          retCode = emaUnguarded(startIdx - lookbackEMA, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             if( firstEMA != outReal ) {
             }
             return retCode ;
          }
          firstEMAIdx = secondEMABegIdx.value;
          outIdx = 0;
          while( outIdx < secondEMANbElement.value ) {
             outReal[outIdx] = 2.0 * firstEMA[firstEMAIdx++] - secondEMA[outIdx];
             outIdx += 1;
          }
          if( firstEMA != outReal ) {
          }
          outBegIdx.value = firstEMABegIdx.value + secondEMABegIdx.value;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int divLookback( )
       {
          return 0 ;

       }
       public RetCode div( int startIdx,
                           int endIdx,
                           double inReal0[],
                           double inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] / inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode divUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal0[],
                                    double inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] / inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode div( int startIdx,
                           int endIdx,
                           float inReal0[],
                           float inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] / inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode divUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal0[],
                                    float inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] / inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel
     *  MIF      Mirek Fontan (mira@fontan.cz)
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  082303 MF   Fix #792298. Remove rounding. Bug reported by AM.
     *  062704 MF   Fix #965557. Div by zero bug reported by MIF.
     */

       public int dxLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + this.unstablePeriod[FuncUnstId.Dx.ordinal()] ;
          } else {
             return 2 ;
          }

       }
       public RetCode dx( int startIdx,
                          int endIdx,
                          double inHigh[],
                          double inLow[],
                          double inClose[],
                          int optInTimePeriod,
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM=0
           * B|  | -DM=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a -DM14, sum the -DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous -DM14
           *  Today's -DM14 = Previous -DM14 -  -------------- + Today's -DM1
           *                                         14
           *
           * Calculation of a -DI14 is as follow:
           *
           *               -DM14
           *     -DI14 =  --------
           *                TR14
           *
           * Calculation of the TR14 is:
           *
           *                                   Previous TR14
           *    Today's TR14 = Previous TR14 - -------------- + Today's TR1
           *                                         14
           *
           *    The first TR14 is the summation of the first 14 TR1. See the
           *    TA_TRANGE function on how to calculate the true range.
           *
           * Calculation of the DX14 is:
           *
           *    diffDI = ABS( (-DI14) - (+DI14) )
           *    sumDI  = (-DI14) + (+DI14)
           *
           *    DX14 = 100 * (diffDI / sumDI)
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          /* Original implementation from Wilder's book was doing some integer
           * rounding in its calculations.
           *
           * This was understandable in the context that at the time the book
           * was written, most user were doing the calculation by hand.
           *
           * For a computer, rounding is unnecessary (and even problematic when inputs
           * are close to 1).
           *
           * TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
           * you can comment out the following #undef/#define and rebuild the library.
           */
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Dx.ordinal()];
          } else {
             lookbackTotal = 2;
          }
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Process the initial DM and TR */
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          /* Skip the unstable period. Note that this loop must be executed
           * at least ONCE to calculate the first DI.
           */
          i = this.unstablePeriod[FuncUnstId.Dx.ordinal()] + 1;
          while( i-- != 0 ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             /* Calculate the prevTR */
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          /* Write the first DX output */
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             minusDI = (100.0 * (prevMinusDM / prevTR));
             plusDI = (100.0 * (prevPlusDM / prevTR));
             tempReal = minusDI + plusDI;
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                outReal[0] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
             } else {
                outReal[0] = 0.0;
             }
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             /* Calculate the prevMinusDM and prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             /* Calculate the prevTR */
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             /* Calculate the DX. The value is rounded (see Wilder book). */
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                /* This loop is just to accumulate the initial DX */
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   outReal[outIdx] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                } else {
                   outReal[outIdx] = outReal[outIdx - 1];
                }
             } else {
                outReal[outIdx] = outReal[outIdx - 1];
             }
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode dxUnguarded( int startIdx,
                                   int endIdx,
                                   double inHigh[],
                                   double inLow[],
                                   double inClose[],
                                   int optInTimePeriod,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Dx.ordinal()];
          } else {
             lookbackTotal = 2;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.Dx.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             minusDI = (100.0 * (prevMinusDM / prevTR));
             plusDI = (100.0 * (prevPlusDM / prevTR));
             tempReal = minusDI + plusDI;
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                outReal[0] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
             } else {
                outReal[0] = 0.0;
             }
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   outReal[outIdx] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                } else {
                   outReal[outIdx] = outReal[outIdx - 1];
                }
             } else {
                outReal[outIdx] = outReal[outIdx - 1];
             }
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode dx( int startIdx,
                          int endIdx,
                          float inHigh[],
                          float inLow[],
                          float inClose[],
                          int optInTimePeriod,
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Dx.ordinal()];
          } else {
             lookbackTotal = 2;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.Dx.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             minusDI = (100.0 * (prevMinusDM / prevTR));
             plusDI = (100.0 * (prevPlusDM / prevTR));
             tempReal = minusDI + plusDI;
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                outReal[0] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
             } else {
                outReal[0] = 0.0;
             }
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   outReal[outIdx] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                } else {
                   outReal[outIdx] = outReal[outIdx - 1];
                }
             } else {
                outReal[outIdx] = outReal[outIdx - 1];
             }
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode dxUnguarded( int startIdx,
                                   int endIdx,
                                   float inHigh[],
                                   float inLow[],
                                   float inClose[],
                                   int optInTimePeriod,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          double minusDI = 0;
          double plusDI = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Dx.ordinal()];
          } else {
             lookbackTotal = 2;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_0;
             double range_0 = prevHigh - prevLow;
             double tmp_0 = Math.abs(prevHigh - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             tmp_0 = Math.abs(prevLow - prevClose);
             if( tmp_0 > range_0 ) {
                range_0 = tmp_0;
             }
             _true_range_0 = range_0;
             tempReal = _true_range_0;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.Dx.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             minusDI = (100.0 * (prevMinusDM / prevTR));
             plusDI = (100.0 * (prevPlusDM / prevTR));
             tempReal = minusDI + plusDI;
             if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                outReal[0] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
             } else {
                outReal[0] = 0.0;
             }
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             prevMinusDM -= prevMinusDM / optInTimePeriod;
             prevPlusDM -= prevPlusDM / optInTimePeriod;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             } else if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                   outReal[outIdx] = (100.0 * (Math.abs(minusDI - plusDI) / tempReal));
                } else {
                   outReal[outIdx] = outReal[outIdx - 1];
                }
             } else {
                outReal[outIdx] = outReal[outIdx - 1];
             }
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int emaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 + this.unstablePeriod[FuncUnstId.Ema.ordinal()] ;

       }
       public RetCode emaPrivate( int startIdx,
                                  int endIdx,
                                  double inReal[],
                                  int optInTimePeriod,
                                  double optInK_1,
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  double outReal[] )
       {
          double tempReal = 0;
          double prevMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          /* Internal implementation can be called from any other TA function.
           *
           * Faster because there is no parameter check, but it is a double
           * edge sword.
           *
           * The optInK_1 and optInTimePeriod are usually tightly coupled:
           *
           *    optInK_1  = 2 / (optInTimePeriod + 1).
           *
           * These values are going to be related by this equation 99.9% of the
           * time... but there is some exception, this is why both must be provided.
           */
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = emaLookback(optInTimePeriod);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Do the EMA calculation using tight loops. */
          /* The first EMA is calculated differently. It
           * then become the seed for subsequent EMA.
           *
           * The algorithm for this seed vary widely.
           * Only 3 are implemented here:
           *
           * TA_MA_CLASSIC:
           *    Use a simple MA of the first 'period'.
           *    This is the approach most widely documented.
           *
           * TA_MA_METASTOCK:
           *    Use first price bar value as a seed
           *    from the begining of all the available
           *    data.
           *
           * TA_MA_TRADESTATION:
           *    Use 4th price bar as a seed, except when
           *    period is 1 who use 2th price bar or something
           *    like that... (not an obvious one...).
           */
          if( this.compatibility == Compatibility.Default ) {
             today = startIdx - lookbackTotal;
             i = optInTimePeriod;
             tempReal = 0.0;
             while( i-- > 0 ) {
                tempReal += inReal[today++];
             }
             prevMA = tempReal / optInTimePeriod;
          } else {
             prevMA = inReal[0];
             today = 1;
          }
          while( today <= startIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
          }
          outReal[0] = prevMA;
          outIdx = 1;
          while( today <= endIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
             outReal[outIdx++] = prevMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode emaPrivate( int startIdx,
                                  int endIdx,
                                  float inReal[],
                                  int optInTimePeriod,
                                  double optInK_1,
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  double outReal[] )
       {
          double tempReal = 0;
          double prevMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = emaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          if( this.compatibility == Compatibility.Default ) {
             today = startIdx - lookbackTotal;
             i = optInTimePeriod;
             tempReal = 0.0;
             while( i-- > 0 ) {
                tempReal += inReal[today++];
             }
             prevMA = tempReal / optInTimePeriod;
          } else {
             prevMA = inReal[0];
             today = 1;
          }
          while( today <= startIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
          }
          outReal[0] = prevMA;
          outIdx = 1;
          while( today <= endIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
             outReal[outIdx++] = prevMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode ema( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double optInK_1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          optInK_1 = 2.0 / (double)(optInTimePeriod + 1);
          /* Simply call the internal implementation of the EMA. */
          return emaPrivate(startIdx, endIdx, inReal, optInTimePeriod, optInK_1, outBegIdx, outNBElement, outReal) ;
       }
       public RetCode emaUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double optInK_1 = 0;
          optInK_1 = 2.0 / (double)(optInTimePeriod + 1);
          return emaPrivate(startIdx, endIdx, inReal, optInTimePeriod, optInK_1, outBegIdx, outNBElement, outReal) ;
       }
       public RetCode ema( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double tempReal = 0;
          double prevMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double optInK_1 = (2.0/(double)((optInTimePeriod+1)));
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = emaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          if( this.compatibility == Compatibility.Default ) {
             today = startIdx - lookbackTotal;
             i = optInTimePeriod;
             tempReal = 0.0;
             while( i-- > 0 ) {
                tempReal += inReal[today++];
             }
             prevMA = tempReal / optInTimePeriod;
          } else {
             prevMA = inReal[0];
             today = 1;
          }
          while( today <= startIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
          }
          outReal[0] = prevMA;
          outIdx = 1;
          while( today <= endIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
             outReal[outIdx++] = prevMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode emaUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double tempReal = 0;
          double prevMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          double optInK_1 = (2.0/(double)((optInTimePeriod+1)));
          lookbackTotal = emaLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          if( this.compatibility == Compatibility.Default ) {
             today = startIdx - lookbackTotal;
             i = optInTimePeriod;
             tempReal = 0.0;
             while( i-- > 0 ) {
                tempReal += inReal[today++];
             }
             prevMA = tempReal / optInTimePeriod;
          } else {
             prevMA = inReal[0];
             today = 1;
          }
          while( today <= startIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
          }
          outReal[0] = prevMA;
          outIdx = 1;
          while( today <= endIdx ) {
             prevMA = (inReal[today++] - prevMA) * optInK_1 + prevMA;
             outReal[outIdx++] = prevMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int expLookback( )
       {
          return 0 ;

       }
       public RetCode exp( int startIdx,
                           int endIdx,
                           double inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.exp(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode expUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.exp(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode exp( int startIdx,
                           int endIdx,
                           float inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.exp(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode expUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.exp(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int floorLookback( )
       {
          return 0 ;

       }
       public RetCode floor( int startIdx,
                             int endIdx,
                             double inReal[],
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.floor(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode floorUnguarded( int startIdx,
                                      int endIdx,
                                      double inReal[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.floor(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode floor( int startIdx,
                             int endIdx,
                             float inReal[],
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.floor(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode floorUnguarded( int startIdx,
                                      int endIdx,
                                      float inReal[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.floor(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htDcPeriodLookback( )
       {
          /* See mama_lookback for an explanation of these */
          return 32 + this.unstablePeriod[FuncUnstId.HtDcPeriod.ordinal()] ;

       }
       public RetCode htDcPeriod( int startIdx,
                                  int endIdx,
                                  double inReal[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variables used for the Hilbert Transormation */
          /* Constant */
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtDcPeriod.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             if( today >= startIdx ) {
                outReal[outIdx++] = smoothPeriod;
             }
             /* Ooof... let's do the next price bar now! */
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPeriodUnguarded( int startIdx,
                                           int endIdx,
                                           double inReal[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtDcPeriod.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             if( today >= startIdx ) {
                outReal[outIdx++] = smoothPeriod;
             }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPeriod( int startIdx,
                                  int endIdx,
                                  float inReal[],
                                  MInteger outBegIdx,
                                  MInteger outNBElement,
                                  double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtDcPeriod.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             if( today >= startIdx ) {
                outReal[outIdx++] = smoothPeriod;
             }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPeriodUnguarded( int startIdx,
                                           int endIdx,
                                           float inReal[],
                                           MInteger outBegIdx,
                                           MInteger outNBElement,
                                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtDcPeriod.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             if( today >= startIdx ) {
                outReal[outIdx++] = smoothPeriod;
             }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htDcPhaseLookback( )
       {
          /* 31 input are skip
           * +32 output are skip to account for misc lookback
           * ---
           *  63 Total Lookback
           *
           * 31 is for being compatible with Tradestation.
           * See mama_lookback for an explanation of the "32".
           */
          return 63 + this.unstablePeriod[FuncUnstId.HtDcPhase.ordinal()] ;

       }
       public RetCode htDcPhase( int startIdx,
                                 int endIdx,
                                 double inReal[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variables used for the Hilbert Transormation */
          /* Varaible used to keep track of the previous
           * smooth price. In the case of this algorithm,
           * we will never need more than 50 values.
           */
          smoothPrice = new double[maxIdx_smoothPrice+1];
          /* Variable used to calculate the dominant cycle phase */
          /* circular buffer already declared */
          /* Constant */
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          constDeg2RadBy360 = tempReal * 8.0;
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtDcPhase.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             /* Remember the smoothedValue into the smoothPrice
              * circular buffer.
              */
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             /* Compute Dominant Cycle Phase */
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             /* idx is used to iterate for up to 50 of the last
              * value of smoothPrice.
              */
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             /* Compensate for one bar lag of the weighted moving average */
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outReal[outIdx++] = DCPhase;
             }
             /* Ooof... let's do the next price bar now! */
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPhaseUnguarded( int startIdx,
                                          int endIdx,
                                          double inReal[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtDcPhase.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outReal[outIdx++] = DCPhase;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPhase( int startIdx,
                                 int endIdx,
                                 float inReal[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtDcPhase.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outReal[outIdx++] = DCPhase;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htDcPhaseUnguarded( int startIdx,
                                          int endIdx,
                                          float inReal[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtDcPhase.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outReal[outIdx++] = DCPhase;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htPhasorLookback( )
       {
          /* See mama_lookback for an explanation of these */
          return 32 + this.unstablePeriod[FuncUnstId.HtPhasor.ordinal()] ;

       }
       public RetCode htPhasor( int startIdx,
                                int endIdx,
                                double inReal[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outInPhase[],
                                double outQuadrature[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variables used for the Hilbert Transormation */
          /* Constant */
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtPhasor.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForEvenPrev3;
                }
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForOddPrev3;
                }
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             /* Ooof... let's do the next price bar now! */
             today += 1;
          }
          /* Default return values */
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htPhasorUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outInPhase[],
                                         double outQuadrature[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtPhasor.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForEvenPrev3;
                }
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForOddPrev3;
                }
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htPhasor( int startIdx,
                                int endIdx,
                                float inReal[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outInPhase[],
                                double outQuadrature[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtPhasor.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForEvenPrev3;
                }
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForOddPrev3;
                }
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htPhasorUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outInPhase[],
                                         double outQuadrature[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.HtPhasor.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForEvenPrev3;
                }
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                if( today >= startIdx ) {
                   outQuadrature[outIdx] = Q1;
                   outInPhase[outIdx++] = I1ForOddPrev3;
                }
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htSineLookback( )
       {
          /* 31 input are skip
           * +32 output are skip to account for misc lookback
           * ---
           *  63 Total Lookback
           *
           * 31 is for being compatible with Tradestation.
           * See mama_lookback for an explanation of the "32".
           */
          return 63 + this.unstablePeriod[FuncUnstId.HtSine.ordinal()] ;

       }
       public RetCode htSine( int startIdx,
                              int endIdx,
                              double inReal[],
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outSine[],
                              double outLeadSine[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variables used for the Hilbert Transormation */
          /* Varaible used to keep track of the previous
           * smooth price. In the case of this algorithm,
           * we will never need more than 50 values.
           */
          smoothPrice = new double[maxIdx_smoothPrice+1];
          /* Variable used to calculate the dominant cycle phase */
          /* circular buffer already declared */
          /* The following could be replaced by constant eventually. */
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtSine.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             /* Remember the smoothedValue into the smoothPrice
              * circular buffer.
              */
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             /* Compute Dominant Cycle Phase */
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             /* idx is used to iterate for up to 50 of the last
              * value of smoothPrice.
              */
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             /* Compensate for one bar lag of the weighted moving average */
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outSine[outIdx] = Math.sin(DCPhase * deg2Rad);
                outLeadSine[outIdx++] = Math.sin((DCPhase + 45) * deg2Rad);
             }
             /* Ooof... let's do the next price bar now! */
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htSineUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outSine[],
                                       double outLeadSine[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtSine.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outSine[outIdx] = Math.sin(DCPhase * deg2Rad);
                outLeadSine[outIdx++] = Math.sin((DCPhase + 45) * deg2Rad);
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htSine( int startIdx,
                              int endIdx,
                              float inReal[],
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outSine[],
                              double outLeadSine[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtSine.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outSine[outIdx] = Math.sin(DCPhase * deg2Rad);
                outLeadSine[outIdx++] = Math.sin((DCPhase + 45) * deg2Rad);
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htSineUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal[],
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outSine[],
                                       double outLeadSine[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtSine.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             if( today >= startIdx ) {
                outSine[outIdx] = Math.sin(DCPhase * deg2Rad);
                outLeadSine[outIdx++] = Math.sin((DCPhase + 45) * deg2Rad);
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htTrendlineLookback( )
       {
          /* 31 input are skip
           * +32 output are skip to account for misc lookback
           * ---
           *  63 Total Lookback
           *
           * 31 is for being compatible with Tradestation.
           * See mama_lookback for an explanation of the "32".
           */
          return 63 + this.unstablePeriod[FuncUnstId.HtTrendline.ordinal()] ;

       }
       public RetCode htTrendline( int startIdx,
                                   int endIdx,
                                   double inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPeriod = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variable to keep track of the last 3 ITrend */
          /* Variables used for the Hilbert Transormation */
          /* Variable used to keep track of the previous
           * smooth price. In the case of this algorithm,
           * we will never need more than 50 values.
           */
          smoothPrice = new double[maxIdx_smoothPrice+1];
          /* Variable used to calculate the dominant cycle phase */
          /* circular buffer already declared */
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          /* Constant */
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendline.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             /* Remember the smoothedValue into the smoothPrice
              * circular buffer.
              */
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             /* Compute Trendline */
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             /* idx is used to iterate for up to 50 of the last
              * value of smoothPrice.
              */
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             tempReal2 = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             if( today >= startIdx ) {
                outReal[outIdx++] = tempReal2;
             }
             /* Ooof... let's do the next price bar now! */
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendlineUnguarded( int startIdx,
                                            int endIdx,
                                            double inReal[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPeriod = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendline.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             tempReal2 = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             if( today >= startIdx ) {
                outReal[outIdx++] = tempReal2;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendline( int startIdx,
                                   int endIdx,
                                   float inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPeriod = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendline.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             tempReal2 = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             if( today >= startIdx ) {
                outReal[outIdx++] = tempReal2;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendlineUnguarded( int startIdx,
                                            int endIdx,
                                            float inReal[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPeriod = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendline.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             tempReal2 = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             if( today >= startIdx ) {
                outReal[outIdx++] = tempReal2;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int htTrendModeLookback( )
       {
          /* 31 input are skip
           * +32 output are skip to account for misc lookback
           * ---
           *  63 Total Lookback
           *
           * 31 is for being compatible with Tradestation.
           * See mama_lookback for an explanation of the "32".
           */
          return 63 + this.unstablePeriod[FuncUnstId.HtTrendMode.ordinal()] ;

       }
       public RetCode htTrendMode( int startIdx,
                                   int endIdx,
                                   double inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          int daysInTrend = 0;
          int trend = 0;
          double prevDCPhase = 0;
          double trendline = 0;
          double prevSine = 0;
          double prevLeadSine = 0;
          double sine = 0;
          double leadSine = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variable to keep track of the last 3 ITrend */
          /* Variables used for the Hilbert Transormation */
          /* Variable used to keep track of the previous
           * smooth price. In the case of this algorithm,
           * we will never need more than 50 values.
           */
          smoothPrice = new double[maxIdx_smoothPrice+1];
          /* Variable used to calculate the dominant cycle phase */
          /* Variable used to calculate the trend mode */
          /* circular buffer already declared */
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          daysInTrend = 0;
          DCPhase = 0.0;
          prevDCPhase = DCPhase;
          sine = 0.0;
          prevSine = sine;
          leadSine = 0.0;
          prevLeadSine = leadSine;
          /* The following could be replaced by constant eventually. */
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendMode.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             /* Remember the smoothedValue into the smoothPrice
              * circular buffer.
              */
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "even" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             /* Compute Dominant Cycle Phase */
             prevDCPhase = DCPhase;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             /* idx is used to iterate for up to 50 of the last
              * value of smoothPrice.
              */
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             /* Compensate for one bar lag of the weighted moving average */
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             prevSine = sine;
             prevLeadSine = leadSine;
             sine = Math.sin(DCPhase * deg2Rad);
             leadSine = Math.sin((DCPhase + 45) * deg2Rad);
             /* Compute Trendline */
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             /* idx is used to iterate for up to 50 of the last
              * value of smoothPrice.
              */
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             trendline = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             /* Compute the trend Mode , and assume trend by default */
             trend = 1;
             /* Measure days in trend from last crossing of the SineWave Indicator lines */
             if( sine > leadSine && prevSine <= prevLeadSine || sine < leadSine && prevSine >= prevLeadSine ) {
                daysInTrend = 0;
                trend = 0;
             }
             daysInTrend += 1;
             if( daysInTrend < 0.5 * smoothPeriod ) {
                trend = 0;
             }
             tempReal = DCPhase - prevDCPhase;
             if( smoothPeriod != 0.0 && (tempReal > 0.67 * 360.0 / smoothPeriod && tempReal < 1.5 * 360.0 / smoothPeriod) ) {
                trend = 0;
             }
             tempReal = smoothPrice[smoothPrice_Idx];
             if( trendline != 0.0 && Math.abs((tempReal - trendline) / trendline) >= 0.015 ) {
                trend = 1;
             }
             if( today >= startIdx ) {
                outInteger[outIdx++] = trend;
             }
             /* Ooof... let's do the next price bar now! */
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendModeUnguarded( int startIdx,
                                            int endIdx,
                                            double inReal[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          int daysInTrend = 0;
          int trend = 0;
          double prevDCPhase = 0;
          double trendline = 0;
          double prevSine = 0;
          double prevLeadSine = 0;
          double sine = 0;
          double leadSine = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          daysInTrend = 0;
          DCPhase = 0.0;
          prevDCPhase = DCPhase;
          sine = 0.0;
          prevSine = sine;
          leadSine = 0.0;
          prevLeadSine = leadSine;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendMode.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             prevDCPhase = DCPhase;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             prevSine = sine;
             prevLeadSine = leadSine;
             sine = Math.sin(DCPhase * deg2Rad);
             leadSine = Math.sin((DCPhase + 45) * deg2Rad);
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             trendline = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             trend = 1;
             if( sine > leadSine && prevSine <= prevLeadSine || sine < leadSine && prevSine >= prevLeadSine ) {
                daysInTrend = 0;
                trend = 0;
             }
             daysInTrend += 1;
             if( daysInTrend < 0.5 * smoothPeriod ) {
                trend = 0;
             }
             tempReal = DCPhase - prevDCPhase;
             if( smoothPeriod != 0.0 && (tempReal > 0.67 * 360.0 / smoothPeriod && tempReal < 1.5 * 360.0 / smoothPeriod) ) {
                trend = 0;
             }
             tempReal = smoothPrice[smoothPrice_Idx];
             if( trendline != 0.0 && Math.abs((tempReal - trendline) / trendline) >= 0.015 ) {
                trend = 1;
             }
             if( today >= startIdx ) {
                outInteger[outIdx++] = trend;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendMode( int startIdx,
                                   int endIdx,
                                   float inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outInteger[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          int daysInTrend = 0;
          int trend = 0;
          double prevDCPhase = 0;
          double trendline = 0;
          double prevSine = 0;
          double prevLeadSine = 0;
          double sine = 0;
          double leadSine = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          daysInTrend = 0;
          DCPhase = 0.0;
          prevDCPhase = DCPhase;
          sine = 0.0;
          prevSine = sine;
          leadSine = 0.0;
          prevLeadSine = leadSine;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendMode.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             prevDCPhase = DCPhase;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             prevSine = sine;
             prevLeadSine = leadSine;
             sine = Math.sin(DCPhase * deg2Rad);
             leadSine = Math.sin((DCPhase + 45) * deg2Rad);
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             trendline = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             trend = 1;
             if( sine > leadSine && prevSine <= prevLeadSine || sine < leadSine && prevSine >= prevLeadSine ) {
                daysInTrend = 0;
                trend = 0;
             }
             daysInTrend += 1;
             if( daysInTrend < 0.5 * smoothPeriod ) {
                trend = 0;
             }
             tempReal = DCPhase - prevDCPhase;
             if( smoothPeriod != 0.0 && (tempReal > 0.67 * 360.0 / smoothPeriod && tempReal < 1.5 * 360.0 / smoothPeriod) ) {
                trend = 0;
             }
             tempReal = smoothPrice[smoothPrice_Idx];
             if( trendline != 0.0 && Math.abs((tempReal - trendline) / trendline) >= 0.015 ) {
                trend = 1;
             }
             if( today >= startIdx ) {
                outInteger[outIdx++] = trend;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode htTrendModeUnguarded( int startIdx,
                                            int endIdx,
                                            float inReal[],
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outInteger[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double iTrend1 = 0;
          double iTrend2 = 0;
          double iTrend3 = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double deg2Rad = 0;
          double constDeg2RadBy360 = 0;
          double todayValue = 0;
          double smoothPeriod = 0;
          double[] smoothPrice;
          int smoothPrice_Idx = 0;
          int maxIdx_smoothPrice = (50)-1;
          int idx = 0;
          int DCPeriodInt = 0;
          double DCPhase = 0;
          double DCPeriod = 0;
          double imagPart = 0;
          double realPart = 0;
          int daysInTrend = 0;
          int trend = 0;
          double prevDCPhase = 0;
          double trendline = 0;
          double prevSine = 0;
          double prevLeadSine = 0;
          double sine = 0;
          double leadSine = 0;
          a = 0.0962;
          b = 0.5769;
          smoothPrice = new double[maxIdx_smoothPrice+1];
          iTrend3 = 0.0;
          iTrend2 = iTrend3;
          iTrend1 = iTrend2;
          daysInTrend = 0;
          DCPhase = 0.0;
          prevDCPhase = DCPhase;
          sine = 0.0;
          prevSine = sine;
          leadSine = 0.0;
          prevLeadSine = leadSine;
          tempReal = Math.atan(1);
          rad2Deg = 45.0 / tempReal;
          deg2Rad = 1.0 / rad2Deg;
          constDeg2RadBy360 = tempReal * 8.0;
          lookbackTotal = 63 + this.unstablePeriod[FuncUnstId.HtTrendMode.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 34;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          smoothPeriod = 0.0;
          for( i = 0; i < 50; i += 1 ) {
             smoothPrice[i] = 0.0;
          }
          DCPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             smoothPrice[smoothPrice_Idx] = smoothedValue;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             smoothPeriod = 0.33 * period + 0.67 * smoothPeriod;
             prevDCPhase = DCPhase;
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             realPart = 0.0;
             imagPart = 0.0;
             idx = smoothPrice_Idx;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal = (double)i * constDeg2RadBy360 / (double)DCPeriodInt;
                tempReal2 = smoothPrice[idx];
                realPart += Math.sin(tempReal) * tempReal2;
                imagPart += Math.cos(tempReal) * tempReal2;
                if( idx == 0 ) {
                   idx = 50 - 1;
                } else {
                   idx -= 1;
                }
             }
             tempReal = Math.abs(imagPart);
             if( tempReal > 0.0 ) {
                DCPhase = Math.atan(realPart / imagPart) * rad2Deg;
             } else if( tempReal <= 0.01 ) {
                if( realPart < 0.0 ) {
                   DCPhase -= 90.0;
                } else if( realPart > 0.0 ) {
                   DCPhase += 90.0;
                }
             }
             DCPhase += 90.0;
             DCPhase += 360.0 / smoothPeriod;
             if( imagPart < 0.0 ) {
                DCPhase += 180.0;
             }
             if( DCPhase > 315.0 ) {
                DCPhase -= 360.0;
             }
             prevSine = sine;
             prevLeadSine = leadSine;
             sine = Math.sin(DCPhase * deg2Rad);
             leadSine = Math.sin((DCPhase + 45) * deg2Rad);
             DCPeriod = smoothPeriod + 0.5;
             DCPeriodInt = (int)DCPeriod;
             idx = today;
             tempReal = 0.0;
             for( i = 0; i < DCPeriodInt; i += 1 ) {
                tempReal += inReal[idx--];
             }
             if( DCPeriodInt > 0 ) {
                tempReal = tempReal / (double)DCPeriodInt;
             }
             trendline = (4.0 * tempReal + 3.0 * iTrend1 + 2.0 * iTrend2 + iTrend3) / 10.0;
             iTrend3 = iTrend2;
             iTrend2 = iTrend1;
             iTrend1 = tempReal;
             trend = 1;
             if( sine > leadSine && prevSine <= prevLeadSine || sine < leadSine && prevSine >= prevLeadSine ) {
                daysInTrend = 0;
                trend = 0;
             }
             daysInTrend += 1;
             if( daysInTrend < 0.5 * smoothPeriod ) {
                trend = 0;
             }
             tempReal = DCPhase - prevDCPhase;
             if( smoothPeriod != 0.0 && (tempReal > 0.67 * 360.0 / smoothPeriod && tempReal < 1.5 * 360.0 / smoothPeriod) ) {
                trend = 0;
             }
             tempReal = smoothPrice[smoothPrice_Idx];
             if( trendline != 0.0 && Math.abs((tempReal - trendline) / trendline) >= 0.015 ) {
                trend = 1;
             }
             if( today >= startIdx ) {
                outInteger[outIdx++] = trend;
             }
             smoothPrice_Idx++;
             if( smoothPrice_Idx > maxIdx_smoothPrice ) { smoothPrice_Idx = 0; }
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AB       Anatoliy Belsky
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  181012 AB    Initial Version
     */

       public int imiLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod + this.unstablePeriod[FuncUnstId.Imi.ordinal()] - 1 ;

       }
       public RetCode imi( int startIdx,
                           int endIdx,
                           double inOpen[],
                           double inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int lookback = 0;
          int outIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outIdx = 0;
          lookback = imiLookback(optInTimePeriod);
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          while( startIdx <= endIdx ) {
             double upsum = 0.0;
             double downsum = 0.0;
             int i;
             for( i = startIdx - lookback; i <= startIdx; i += 1 ) {
                double close = inClose[i];
                double open = inOpen[i];
                if( close > open ) {
                   upsum += close - open;
                } else {
                   downsum += open - close;
                }
                outReal[outIdx] = 100.0 * (upsum / (upsum + downsum));
             }
             startIdx += 1;
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode imiUnguarded( int startIdx,
                                    int endIdx,
                                    double inOpen[],
                                    double inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int lookback = 0;
          int outIdx = 0;
          outIdx = 0;
          lookback = imiLookback(optInTimePeriod);
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          while( startIdx <= endIdx ) {
             double upsum = 0.0;
             double downsum = 0.0;
             int i;
             for( i = startIdx - lookback; i <= startIdx; i += 1 ) {
                double close = inClose[i];
                double open = inOpen[i];
                if( close > open ) {
                   upsum += close - open;
                } else {
                   downsum += open - close;
                }
                outReal[outIdx] = 100.0 * (upsum / (upsum + downsum));
             }
             startIdx += 1;
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode imi( int startIdx,
                           int endIdx,
                           float inOpen[],
                           float inClose[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int lookback = 0;
          int outIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outIdx = 0;
          lookback = imiLookback(optInTimePeriod);
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          while( startIdx <= endIdx ) {
             double upsum = 0.0;
             double downsum = 0.0;
             int i;
             for( i = startIdx - lookback; i <= startIdx; i += 1 ) {
                double close = inClose[i];
                double open = inOpen[i];
                if( close > open ) {
                   upsum += close - open;
                } else {
                   downsum += open - close;
                }
                outReal[outIdx] = 100.0 * (upsum / (upsum + downsum));
             }
             startIdx += 1;
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode imiUnguarded( int startIdx,
                                    int endIdx,
                                    float inOpen[],
                                    float inClose[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int lookback = 0;
          int outIdx = 0;
          outIdx = 0;
          lookback = imiLookback(optInTimePeriod);
          if( startIdx < lookback ) {
             startIdx = lookback;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          while( startIdx <= endIdx ) {
             double upsum = 0.0;
             double downsum = 0.0;
             int i;
             for( i = startIdx - lookback; i <= startIdx; i += 1 ) {
                double close = inClose[i];
                double open = inOpen[i];
                if( close > open ) {
                   upsum += close - open;
                } else {
                   downsum += open - close;
                }
                outReal[outIdx] = 100.0 * (upsum / (upsum + downsum));
             }
             startIdx += 1;
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  120802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  062704 MF     Fix limit case to avoid divid by zero (or by
     *                a value close to zero induce by the imprecision
     *                of floating points).
     *  070226 MF,CC  Allow period of 1: output is a copy of the input,
     *                consistent with TA_MA (issues #48, #59). The natural
     *                KAMA math at period=1 would be a fixed-alpha EMA
     *                (efficiency ratio is always 1), which would disagree
     *                with TA_MA's period-1 copy, so identity is explicit.
     */

       public int kamaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod == 1 ) {
             return this.unstablePeriod[FuncUnstId.Kama.ordinal()] ;
          }
          return optInTimePeriod + this.unstablePeriod[FuncUnstId.Kama.ordinal()] ;

       }
       public RetCode kama( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double constMax = 0;
          double constDiff = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double sumROC1 = 0;
          double periodROC = 0;
          double prevKAMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int trailingIdx = 0;
          double trailingValue = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          constMax = 2.0 / (30.0 + 1.0);
          constDiff = 2.0 / (2.0 + 1.0) - constMax;
          /* Default return values */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* No smoothing at period of 1: the output is a copy of the input
           * (same convention as TA_MA for every MAType). The unstable period
           * still delays the first output for API consistency.
           */
          if( optInTimePeriod == 1 ) {
             lookbackTotal = this.unstablePeriod[FuncUnstId.Kama.ordinal()];
             if( startIdx < lookbackTotal ) {
                startIdx = lookbackTotal;
             }
             if( startIdx > endIdx ) {
                return RetCode.Success ;
             }
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Kama.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Initialize the variables by going through
           * the lookback period.
           */
          sumROC1 = 0.0;
          today = startIdx - lookbackTotal;
          trailingIdx = today;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             tempReal = inReal[today++];
             tempReal -= inReal[today];
             sumROC1 += Math.abs(tempReal);
          }
          /* At this point sumROC1 represent the
           * summation of the 1-day price difference
           * over the (optInTimePeriod-1)
           */
          /* Calculate the first KAMA */
          /* The yesterday price is used here as the previous KAMA. */
          prevKAMA = inReal[today - 1];
          tempReal = inReal[today];
          tempReal2 = inReal[trailingIdx++];
          periodROC = tempReal - tempReal2;
          /* Save the trailing value. Do this because inReal
           * and outReal can be pointers to the same buffer.
           */
          trailingValue = tempReal2;
          /* Calculate the efficiency ratio */
          if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
             tempReal = 1.0;
          } else {
             tempReal = Math.abs(periodROC / sumROC1);
          }
          /* Calculate the smoothing constant */
          tempReal = tempReal * constDiff + constMax;
          tempReal *= tempReal;
          /* Calculate the KAMA like an EMA, using the
           * smoothing constant as the adaptive factor.
           */
          prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          /* 'today' keep track of where the processing is within the
           * input.
           */
          /* Skip the unstable period. Do the whole processing
           * needed for KAMA, but do not write it in the output.
           */
          while( today <= startIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             /* Adjust sumROC1:
              *  - Remove trailing ROC1
              *  - Add new ROC1
              */
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             /* Save the trailing value. Do this because inReal
              * and outReal can be pointers to the same buffer.
              */
             trailingValue = tempReal2;
             /* Calculate the efficiency ratio */
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             /* Calculate the smoothing constant */
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             /* Calculate the KAMA like an EMA, using the
              * smoothing constant as the adaptive factor.
              */
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          }
          /* Write the first value. */
          outReal[0] = prevKAMA;
          outIdx = 1;
          outBegIdx.value = today - 1;
          /* Do the KAMA calculation for the requested range. */
          while( today <= endIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             /* Adjust sumROC1:
              *  - Remove trailing ROC1
              *  - Add new ROC1
              */
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             /* Save the trailing value. Do this because inReal
              * and outReal can be pointers to the same buffer.
              */
             trailingValue = tempReal2;
             /* Calculate the efficiency ratio */
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             /* Calculate the smoothing constant */
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             /* Calculate the KAMA like an EMA, using the
              * smoothing constant as the adaptive factor.
              */
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
             outReal[outIdx++] = prevKAMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode kamaUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double constMax = 0;
          double constDiff = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double sumROC1 = 0;
          double periodROC = 0;
          double prevKAMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int trailingIdx = 0;
          double trailingValue = 0;
          constMax = 2.0 / (30.0 + 1.0);
          constDiff = 2.0 / (2.0 + 1.0) - constMax;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          if( optInTimePeriod == 1 ) {
             lookbackTotal = this.unstablePeriod[FuncUnstId.Kama.ordinal()];
             if( startIdx < lookbackTotal ) {
                startIdx = lookbackTotal;
             }
             if( startIdx > endIdx ) {
                return RetCode.Success ;
             }
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Kama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          sumROC1 = 0.0;
          today = startIdx - lookbackTotal;
          trailingIdx = today;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             tempReal = inReal[today++];
             tempReal -= inReal[today];
             sumROC1 += Math.abs(tempReal);
          }
          prevKAMA = inReal[today - 1];
          tempReal = inReal[today];
          tempReal2 = inReal[trailingIdx++];
          periodROC = tempReal - tempReal2;
          trailingValue = tempReal2;
          if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
             tempReal = 1.0;
          } else {
             tempReal = Math.abs(periodROC / sumROC1);
          }
          tempReal = tempReal * constDiff + constMax;
          tempReal *= tempReal;
          prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          while( today <= startIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          }
          outReal[0] = prevKAMA;
          outIdx = 1;
          outBegIdx.value = today - 1;
          while( today <= endIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
             outReal[outIdx++] = prevKAMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode kama( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double constMax = 0;
          double constDiff = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double sumROC1 = 0;
          double periodROC = 0;
          double prevKAMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int trailingIdx = 0;
          double trailingValue = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          constMax = 2.0 / (30.0 + 1.0);
          constDiff = 2.0 / (2.0 + 1.0) - constMax;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          if( optInTimePeriod == 1 ) {
             lookbackTotal = this.unstablePeriod[FuncUnstId.Kama.ordinal()];
             if( startIdx < lookbackTotal ) {
                startIdx = lookbackTotal;
             }
             if( startIdx > endIdx ) {
                return RetCode.Success ;
             }
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Kama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          sumROC1 = 0.0;
          today = startIdx - lookbackTotal;
          trailingIdx = today;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             tempReal = inReal[today++];
             tempReal -= inReal[today];
             sumROC1 += Math.abs(tempReal);
          }
          prevKAMA = inReal[today - 1];
          tempReal = inReal[today];
          tempReal2 = inReal[trailingIdx++];
          periodROC = tempReal - tempReal2;
          trailingValue = tempReal2;
          if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
             tempReal = 1.0;
          } else {
             tempReal = Math.abs(periodROC / sumROC1);
          }
          tempReal = tempReal * constDiff + constMax;
          tempReal *= tempReal;
          prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          while( today <= startIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          }
          outReal[0] = prevKAMA;
          outIdx = 1;
          outBegIdx.value = today - 1;
          while( today <= endIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
             outReal[outIdx++] = prevKAMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode kamaUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double constMax = 0;
          double constDiff = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double sumROC1 = 0;
          double periodROC = 0;
          double prevKAMA = 0;
          int i = 0;
          int today = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int trailingIdx = 0;
          double trailingValue = 0;
          constMax = 2.0 / (30.0 + 1.0);
          constDiff = 2.0 / (2.0 + 1.0) - constMax;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          if( optInTimePeriod == 1 ) {
             lookbackTotal = this.unstablePeriod[FuncUnstId.Kama.ordinal()];
             if( startIdx < lookbackTotal ) {
                startIdx = lookbackTotal;
             }
             if( startIdx > endIdx ) {
                return RetCode.Success ;
             }
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Kama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          sumROC1 = 0.0;
          today = startIdx - lookbackTotal;
          trailingIdx = today;
          i = optInTimePeriod;
          while( i-- > 0 ) {
             tempReal = inReal[today++];
             tempReal -= inReal[today];
             sumROC1 += Math.abs(tempReal);
          }
          prevKAMA = inReal[today - 1];
          tempReal = inReal[today];
          tempReal2 = inReal[trailingIdx++];
          periodROC = tempReal - tempReal2;
          trailingValue = tempReal2;
          if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
             tempReal = 1.0;
          } else {
             tempReal = Math.abs(periodROC / sumROC1);
          }
          tempReal = tempReal * constDiff + constMax;
          tempReal *= tempReal;
          prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          while( today <= startIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
          }
          outReal[0] = prevKAMA;
          outIdx = 1;
          outBegIdx.value = today - 1;
          while( today <= endIdx ) {
             tempReal = inReal[today];
             tempReal2 = inReal[trailingIdx++];
             periodROC = tempReal - tempReal2;
             sumROC1 -= Math.abs(trailingValue - tempReal2);
             sumROC1 += Math.abs(tempReal - inReal[today - 1]);
             trailingValue = tempReal2;
             if( sumROC1 <= periodROC || ((-0.00000000000001 < sumROC1) && (sumROC1 < 0.00000000000001)) ) {
                tempReal = 1.0;
             } else {
                tempReal = Math.abs(periodROC / sumROC1);
             }
             tempReal = tempReal * constDiff + constMax;
             tempReal *= tempReal;
             prevKAMA = (inReal[today++] - prevKAMA) * tempReal + prevKAMA;
             outReal[outIdx++] = prevKAMA;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  JP       John Price <jp_talib@gcfl.net>
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  070203 JP   Initial.
     */

       public int linearRegLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode linearReg( int startIdx,
                                 int endIdx,
                                 double inReal[],
                                 int optInTimePeriod,
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Linear Regression is a concept also known as the
           * "least squares method" or "best fit." Linear
           * Regression attempts to fit a straight line between
           * several data points in such a way that distance
           * between each data point and the line is minimized.
           *
           * For each point, a straight line over the specified
           * previous bar period is determined in terms
           * of y = b + m*x:
           *
           * TA_LINEARREG          : Returns b+m*(period-1)
           * TA_LINEARREG_SLOPE    : Returns 'm'
           * TA_LINEARREG_ANGLE    : Returns 'm' in degree.
           * TA_LINEARREG_INTERCEPT: Returns 'b'
           * TA_TSF                : Returns b+m*(period)
           */
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = linearRegLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)(optInTimePeriod - 1);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegUnguarded( int startIdx,
                                          int endIdx,
                                          double inReal[],
                                          int optInTimePeriod,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)(optInTimePeriod - 1);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearReg( int startIdx,
                                 int endIdx,
                                 float inReal[],
                                 int optInTimePeriod,
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = linearRegLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)(optInTimePeriod - 1);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegUnguarded( int startIdx,
                                          int endIdx,
                                          float inReal[],
                                          int optInTimePeriod,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)(optInTimePeriod - 1);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  JP       John Price <jp_talib@gcfl.net>
     *  MF       Mario Fortier
     *  AM       Adrian Michel <http://amichel.com>
     *
     * Change history:
     *
     *  MMDDYY BY      Description
     *  -------------------------------------------------------------------
     *  070203 JP      Initial.
     *  072106 MF,AM   Fix #1526632. Add missing atan().
     */

       public int linearRegAngleLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode linearRegAngle( int startIdx,
                                      int endIdx,
                                      double inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Linear Regression is a concept also known as the
           * "least squares method" or "best fit." Linear
           * Regression attempts to fit a straight line between
           * several data points in such a way that distance
           * between each data point and the line is minimized.
           *
           * For each point, a straight line over the specified
           * previous bar period is determined in terms
           * of y = b + m*x:
           *
           * TA_LINEARREG          : Returns b+m*(period-1)
           * TA_LINEARREG_SLOPE    : Returns 'm'
           * TA_LINEARREG_ANGLE    : Returns 'm' in degree.
           * TA_LINEARREG_INTERCEPT: Returns 'b'
           * TA_TSF                : Returns b+m*(period)
           */
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = linearRegAngleLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = Math.atan(m) * (180.0 / 3.141592653589793);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegAngleUnguarded( int startIdx,
                                               int endIdx,
                                               double inReal[],
                                               int optInTimePeriod,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegAngleLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = Math.atan(m) * (180.0 / 3.141592653589793);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegAngle( int startIdx,
                                      int endIdx,
                                      float inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = linearRegAngleLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = Math.atan(m) * (180.0 / 3.141592653589793);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegAngleUnguarded( int startIdx,
                                               int endIdx,
                                               float inReal[],
                                               int optInTimePeriod,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegAngleLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = Math.atan(m) * (180.0 / 3.141592653589793);
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  JP       John Price <jp_talib@gcfl.net>
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  070203 JP   Initial.
     */

       public int linearRegInterceptLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode linearRegIntercept( int startIdx,
                                          int endIdx,
                                          double inReal[],
                                          int optInTimePeriod,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Linear Regression is a concept also known as the
           * "least squares method" or "best fit." Linear
           * Regression attempts to fit a straight line between
           * several data points in such a way that distance
           * between each data point and the line is minimized.
           *
           * For each point, a straight line over the specified
           * previous bar period is determined in terms
           * of y = b + m*x:
           *
           * TA_LINEARREG          : Returns b+m*(period-1)
           * TA_LINEARREG_SLOPE    : Returns 'm'
           * TA_LINEARREG_ANGLE    : Returns 'm' in degree.
           * TA_LINEARREG_INTERCEPT: Returns 'b'
           * TA_TSF                : Returns b+m*(period)
           */
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = linearRegInterceptLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = (SumY - m * SumX) / (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegInterceptUnguarded( int startIdx,
                                                   int endIdx,
                                                   double inReal[],
                                                   int optInTimePeriod,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegInterceptLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = (SumY - m * SumX) / (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegIntercept( int startIdx,
                                          int endIdx,
                                          float inReal[],
                                          int optInTimePeriod,
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = linearRegInterceptLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = (SumY - m * SumX) / (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegInterceptUnguarded( int startIdx,
                                                   int endIdx,
                                                   float inReal[],
                                                   int optInTimePeriod,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegInterceptLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             outReal[outIdx++] = (SumY - m * SumX) / (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  JP       John Price <jp_talib@gcfl.net>
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  070203 JP   Initial.
     */

       public int linearRegSlopeLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode linearRegSlope( int startIdx,
                                      int endIdx,
                                      double inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Linear Regression is a concept also known as the
           * "least squares method" or "best fit." Linear
           * Regression attempts to fit a straight line between
           * several data points in such a way that distance
           * between each data point and the line is minimized.
           *
           * For each point, a straight line over the specified
           * previous bar period is determined in terms
           * of y = b + m*x:
           *
           * TA_LINEARREG          : Returns b+m*(period-1)
           * TA_LINEARREG_SLOPE    : Returns 'm'
           * TA_LINEARREG_ANGLE    : Returns 'm' in degree.
           * TA_LINEARREG_INTERCEPT: Returns 'b'
           * TA_TSF                : Returns b+m*(period)
           */
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = linearRegSlopeLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             outReal[outIdx++] = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegSlopeUnguarded( int startIdx,
                                               int endIdx,
                                               double inReal[],
                                               int optInTimePeriod,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegSlopeLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             outReal[outIdx++] = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegSlope( int startIdx,
                                      int endIdx,
                                      float inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = linearRegSlopeLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             outReal[outIdx++] = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode linearRegSlopeUnguarded( int startIdx,
                                               int endIdx,
                                               float inReal[],
                                               int optInTimePeriod,
                                               MInteger outBegIdx,
                                               MInteger outNBElement,
                                               double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = linearRegSlopeLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             outReal[outIdx++] = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int lnLookback( )
       {
          return 0 ;

       }
       public RetCode ln( int startIdx,
                          int endIdx,
                          double inReal[],
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode lnUnguarded( int startIdx,
                                   int endIdx,
                                   double inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ln( int startIdx,
                          int endIdx,
                          float inReal[],
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode lnUnguarded( int startIdx,
                                   int endIdx,
                                   float inReal[],
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int log10Lookback( )
       {
          return 0 ;

       }
       public RetCode log10( int startIdx,
                             int endIdx,
                             double inReal[],
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log10(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode log10Unguarded( int startIdx,
                                      int endIdx,
                                      double inReal[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log10(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode log10( int startIdx,
                             int endIdx,
                             float inReal[],
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log10(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode log10Unguarded( int startIdx,
                                      int endIdx,
                                      float inReal[],
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.log10(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  022203 MF   Add MAMA
     *  040503 MF   Add T3
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  111603 MF   Allow period of 1. Just copy input into output.
     *  060907 MF   Use TA_SMA/TA_EMA instead of internal implementation.
     */

       public int movingAverageLookback( int optInTimePeriod, MAType optInMAType )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          int retValue;
          if( optInTimePeriod <= 1 ) {
             return 0 ;
          }
          switch( optInMAType )
          {
          case Sma:
             retValue = smaLookback(optInTimePeriod);
             break;
          case Ema:
             retValue = emaLookback(optInTimePeriod);
             break;
          case Wma:
             retValue = wmaLookback(optInTimePeriod);
             break;
          case Dema:
             retValue = demaLookback(optInTimePeriod);
             break;
          case Tema:
             retValue = temaLookback(optInTimePeriod);
             break;
          case Trima:
             retValue = trimaLookback(optInTimePeriod);
             break;
          case Kama:
             retValue = kamaLookback(optInTimePeriod);
             break;
          case Mama:
             retValue = mamaLookback(0.5, 0.05);
             break;
          case T3:
             retValue = t3Lookback(optInTimePeriod, 0.7);
             break;
          default:
             retValue = 0;
             break;
          }
          return retValue ;

       }
       public RetCode movingAverage( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MAType optInMAType,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] dummyBuffer;
          RetCode retCode;
          int nbElement = 0;
          int outIdx = 0;
          int todayIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod == 1 ) {
             nbElement = endIdx - startIdx + 1;
             outNBElement.value = nbElement;
             for( todayIdx = startIdx, outIdx = 0; outIdx < nbElement; outIdx += 1, todayIdx += 1 ) {
                outReal[outIdx] = inReal[todayIdx];
             }
             outBegIdx.value = startIdx;
             return RetCode.Success ;
          }
          /* Simply forward the job to the corresponding TA function. */
          switch( optInMAType )
          {
          case Sma:
             retCode = smaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Ema:
             retCode = emaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Wma:
             retCode = wmaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Dema:
             retCode = demaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Tema:
             retCode = temaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Trima:
             retCode = trimaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Kama:
             retCode = kamaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Mama:
             /* The optInTimePeriod is ignored and the FAMA output of the MAMA
              * is ignored.
              */
             dummyBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
             retCode = mamaUnguarded(startIdx, endIdx, inReal, 0.5, 0.05, outBegIdx, outNBElement, outReal, dummyBuffer);
             break;
          case T3:
             retCode = t3Unguarded(startIdx, endIdx, inReal, optInTimePeriod, 0.7, outBegIdx, outNBElement, outReal);
             break;
          default:
             retCode = RetCode.BadParam;
             break;
          }
          return retCode ;
       }
       public RetCode movingAverageUnguarded( int startIdx,
                                              int endIdx,
                                              double inReal[],
                                              int optInTimePeriod,
                                              MAType optInMAType,
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              double outReal[] )
       {
          double[] dummyBuffer;
          RetCode retCode;
          int nbElement = 0;
          int outIdx = 0;
          int todayIdx = 0;
          if( optInTimePeriod == 1 ) {
             nbElement = endIdx - startIdx + 1;
             outNBElement.value = nbElement;
             for( todayIdx = startIdx, outIdx = 0; outIdx < nbElement; outIdx += 1, todayIdx += 1 ) {
                outReal[outIdx] = inReal[todayIdx];
             }
             outBegIdx.value = startIdx;
             return RetCode.Success ;
          }
          switch( optInMAType )
          {
          case Sma:
             retCode = smaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Ema:
             retCode = emaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Wma:
             retCode = wmaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Dema:
             retCode = demaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Tema:
             retCode = temaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Trima:
             retCode = trimaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Kama:
             retCode = kamaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Mama:
             dummyBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
             retCode = mamaUnguarded(startIdx, endIdx, inReal, 0.5, 0.05, outBegIdx, outNBElement, outReal, dummyBuffer);
             break;
          case T3:
             retCode = t3Unguarded(startIdx, endIdx, inReal, optInTimePeriod, 0.7, outBegIdx, outNBElement, outReal);
             break;
          default:
             retCode = RetCode.BadParam;
             break;
          }
          return retCode ;
       }
       public RetCode movingAverage( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MAType optInMAType,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] dummyBuffer;
          RetCode retCode;
          int nbElement = 0;
          int outIdx = 0;
          int todayIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod == 1 ) {
             nbElement = endIdx - startIdx + 1;
             outNBElement.value = nbElement;
             for( todayIdx = startIdx, outIdx = 0; outIdx < nbElement; outIdx += 1, todayIdx += 1 ) {
                outReal[outIdx] = inReal[todayIdx];
             }
             outBegIdx.value = startIdx;
             return RetCode.Success ;
          }
          switch( optInMAType )
          {
          case Sma:
             retCode = smaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Ema:
             retCode = emaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Wma:
             retCode = wmaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Dema:
             retCode = demaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Tema:
             retCode = temaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Trima:
             retCode = trimaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Kama:
             retCode = kamaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Mama:
             dummyBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
             retCode = mamaUnguarded(startIdx, endIdx, inReal, 0.5, 0.05, outBegIdx, outNBElement, outReal, dummyBuffer);
             break;
          case T3:
             retCode = t3Unguarded(startIdx, endIdx, inReal, optInTimePeriod, 0.7, outBegIdx, outNBElement, outReal);
             break;
          default:
             retCode = RetCode.BadParam;
             break;
          }
          return retCode ;
       }
       public RetCode movingAverageUnguarded( int startIdx,
                                              int endIdx,
                                              float inReal[],
                                              int optInTimePeriod,
                                              MAType optInMAType,
                                              MInteger outBegIdx,
                                              MInteger outNBElement,
                                              double outReal[] )
       {
          double[] dummyBuffer;
          RetCode retCode;
          int nbElement = 0;
          int outIdx = 0;
          int todayIdx = 0;
          if( optInTimePeriod == 1 ) {
             nbElement = endIdx - startIdx + 1;
             outNBElement.value = nbElement;
             for( todayIdx = startIdx, outIdx = 0; outIdx < nbElement; outIdx += 1, todayIdx += 1 ) {
                outReal[outIdx] = inReal[todayIdx];
             }
             outBegIdx.value = startIdx;
             return RetCode.Success ;
          }
          switch( optInMAType )
          {
          case Sma:
             retCode = smaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Ema:
             retCode = emaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Wma:
             retCode = wmaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Dema:
             retCode = demaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Tema:
             retCode = temaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Trima:
             retCode = trimaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Kama:
             retCode = kamaUnguarded(startIdx, endIdx, inReal, optInTimePeriod, outBegIdx, outNBElement, outReal);
             break;
          case Mama:
             dummyBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
             retCode = mamaUnguarded(startIdx, endIdx, inReal, 0.5, 0.05, outBegIdx, outNBElement, outReal, dummyBuffer);
             break;
          case T3:
             retCode = t3Unguarded(startIdx, endIdx, inReal, optInTimePeriod, 0.7, outBegIdx, outNBElement, outReal);
             break;
          default:
             retCode = RetCode.BadParam;
             break;
          }
          return retCode ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JPP      JP Pienaar (j.pienaar@mci.co.za)
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  080403 JPP  Fix #767653 for logic when swapping periods.
     */

       public int macdLookback( int optInFastPeriod, int optInSlowPeriod, int optInSignalPeriod )
       {
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return -1;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return -1;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return -1;
          }
          int tempInteger;
          /* The lookback is driven by the signal line output.
           *
           * (must also account for the initial data consume
           *  by the slow period).
           */
          /* Make sure slow is really slower than
           * the fast period! if not, swap...
           */
          if( optInSlowPeriod < optInFastPeriod ) {
             /* swap */
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          return emaLookback(optInSlowPeriod) + emaLookback(optInSignalPeriod) ;

       }
       public RetCode macd( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInFastPeriod,
                            int optInSlowPeriod,
                            int optInSignalPeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outMACD[],
                            double outMACDSignal[],
                            double outMACDHist[] )
       {
          double[] slowEMABuffer;
          double[] fastEMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          double slowK = 0;
          double fastK = 0;
          double signalK = 0;
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int useFixedK = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* !!! A lot of speed optimization could be done
           * !!! with this function.
           * !!!
           * !!! A better approach would be to use ema
           * !!! just to get the seeding values for the
           * !!! fast and slow EMA. Then process the difference
           * !!! in an allocated buffer until enough data is
           * !!! available for the first signal value.
           * !!! From that point all the processing can
           * !!! be done in a tight loop.
           * !!!
           * !!! That approach will have the following
           * !!! advantage:
           * !!!   1) One mem allocation needed instead of two.
           * !!!   2) The mem allocation size will be only the
           * !!!      signal lookback period instead of the
           * !!!      whole range of data.
           * !!!   3) Processing will be done in a tight loop.
           * !!!      allowing to avoid a lot of memory store-load
           * !!!      operation.
           * !!!   4) The memcpy at the end will be eliminated!
           * !!!
           * !!! If only I had time....
           */
          /* Make sure slow is really slower than
           * the fast period! if not, swap...
           */
          if( optInSlowPeriod < optInFastPeriod ) {
             /* swap */
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          /* Catch special case for fix 26/12 MACD.
           * Use hardcoded k values matching the original algorithm.
           */
          useFixedK = 0;
          if( optInSlowPeriod == 0 ) {
             optInSlowPeriod = 26;
             /* Fix 26 */
             slowK = 0.075;
             useFixedK = 1;
          } else {
             slowK = 2.0 / (double)(optInSlowPeriod + 1);
          }
          if( optInFastPeriod == 0 ) {
             optInFastPeriod = 12;
             /* Fix 12 */
             fastK = 0.15;
             useFixedK = 1;
          } else {
             fastK = 2.0 / (double)(optInFastPeriod + 1);
          }
          signalK = 2.0 / (double)(optInSignalPeriod + 1);
          lookbackSignal = emaLookback(optInSignalPeriod);
          /* Move up the start index if there is not
           * enough initial data.
           */
          lookbackTotal = lookbackSignal;
          lookbackTotal += emaLookback(optInSlowPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Allocate intermediate buffer for fast/slow EMA. */
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastEMABuffer = new double[(int)(tempInteger * 1)];
          slowEMABuffer = new double[(int)(tempInteger * 1)];
          /* Calculate the slow EMA.
           *
           * Move back the startIdx to get enough data
           * for the signal period. That way, once the
           * signal calculation is done, all the output
           * will start at the requested 'startIdx'.
           */
          tempInteger = startIdx - lookbackSignal;
          /* Use ema_private when hardcoded k is needed (MACDFIX path).
           * Use ema() for the normal path — codegen handles double/float routing.
           */
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInSlowPeriod, slowK, outBegIdx1, outNbElement1, slowEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, outBegIdx1, outNbElement1, slowEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the fast EMA. */
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInFastPeriod, fastK, outBegIdx2, outNbElement2, fastEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, outBegIdx2, outNbElement2, fastEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Parano tests. Will be removed eventually. */
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          /* Calculate (fast EMA) - (slow EMA). */
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i];
          }
          /* Copy the result into the output for the caller. */
          System.arraycopy(fastEMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          /* Calculate the signal/trigger line (on double buffer, use ema_private). */
          retCode = emaPrivate(0, outNbElement1.value - 1, fastEMABuffer, optInSignalPeriod, signalK, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the histogram. */
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          /* All done! Indicate the output limits and return success. */
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macdUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInFastPeriod,
                                     int optInSlowPeriod,
                                     int optInSignalPeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outMACD[],
                                     double outMACDSignal[],
                                     double outMACDHist[] )
       {
          double[] slowEMABuffer;
          double[] fastEMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          double slowK = 0;
          double fastK = 0;
          double signalK = 0;
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int useFixedK = 0;
          int i = 0;
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          useFixedK = 0;
          if( optInSlowPeriod == 0 ) {
             optInSlowPeriod = 26;
             slowK = 0.075;
             useFixedK = 1;
          } else {
             slowK = 2.0 / (double)(optInSlowPeriod + 1);
          }
          if( optInFastPeriod == 0 ) {
             optInFastPeriod = 12;
             fastK = 0.15;
             useFixedK = 1;
          } else {
             fastK = 2.0 / (double)(optInFastPeriod + 1);
          }
          signalK = 2.0 / (double)(optInSignalPeriod + 1);
          lookbackSignal = emaLookback(optInSignalPeriod);
          lookbackTotal = lookbackSignal;
          lookbackTotal += emaLookback(optInSlowPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastEMABuffer = new double[(int)(tempInteger * 1)];
          slowEMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInSlowPeriod, slowK, outBegIdx1, outNbElement1, slowEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, outBegIdx1, outNbElement1, slowEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInFastPeriod, fastK, outBegIdx2, outNbElement2, fastEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, outBegIdx2, outNbElement2, fastEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i];
          }
          System.arraycopy(fastEMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = emaPrivate(0, outNbElement1.value - 1, fastEMABuffer, optInSignalPeriod, signalK, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macd( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInFastPeriod,
                            int optInSlowPeriod,
                            int optInSignalPeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outMACD[],
                            double outMACDSignal[],
                            double outMACDHist[] )
       {
          double[] slowEMABuffer;
          double[] fastEMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          double slowK = 0;
          double fastK = 0;
          double signalK = 0;
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int useFixedK = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          useFixedK = 0;
          if( optInSlowPeriod == 0 ) {
             optInSlowPeriod = 26;
             slowK = 0.075;
             useFixedK = 1;
          } else {
             slowK = 2.0 / (double)(optInSlowPeriod + 1);
          }
          if( optInFastPeriod == 0 ) {
             optInFastPeriod = 12;
             fastK = 0.15;
             useFixedK = 1;
          } else {
             fastK = 2.0 / (double)(optInFastPeriod + 1);
          }
          signalK = 2.0 / (double)(optInSignalPeriod + 1);
          lookbackSignal = emaLookback(optInSignalPeriod);
          lookbackTotal = lookbackSignal;
          lookbackTotal += emaLookback(optInSlowPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastEMABuffer = new double[(int)(tempInteger * 1)];
          slowEMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInSlowPeriod, slowK, outBegIdx1, outNbElement1, slowEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, outBegIdx1, outNbElement1, slowEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInFastPeriod, fastK, outBegIdx2, outNbElement2, fastEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, outBegIdx2, outNbElement2, fastEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i];
          }
          System.arraycopy(fastEMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = emaPrivate(0, outNbElement1.value - 1, fastEMABuffer, optInSignalPeriod, signalK, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macdUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInFastPeriod,
                                     int optInSlowPeriod,
                                     int optInSignalPeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outMACD[],
                                     double outMACDSignal[],
                                     double outMACDHist[] )
       {
          double[] slowEMABuffer;
          double[] fastEMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          double slowK = 0;
          double fastK = 0;
          double signalK = 0;
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int useFixedK = 0;
          int i = 0;
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          useFixedK = 0;
          if( optInSlowPeriod == 0 ) {
             optInSlowPeriod = 26;
             slowK = 0.075;
             useFixedK = 1;
          } else {
             slowK = 2.0 / (double)(optInSlowPeriod + 1);
          }
          if( optInFastPeriod == 0 ) {
             optInFastPeriod = 12;
             fastK = 0.15;
             useFixedK = 1;
          } else {
             fastK = 2.0 / (double)(optInFastPeriod + 1);
          }
          signalK = 2.0 / (double)(optInSignalPeriod + 1);
          lookbackSignal = emaLookback(optInSignalPeriod);
          lookbackTotal = lookbackSignal;
          lookbackTotal += emaLookback(optInSlowPeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastEMABuffer = new double[(int)(tempInteger * 1)];
          slowEMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInSlowPeriod, slowK, outBegIdx1, outNbElement1, slowEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, outBegIdx1, outNbElement1, slowEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( (useFixedK) != 0 ) {
             retCode = emaPrivate(tempInteger, endIdx, inReal, optInFastPeriod, fastK, outBegIdx2, outNbElement2, fastEMABuffer);
          } else {
             retCode = emaUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, outBegIdx2, outNbElement2, fastEMABuffer);
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i];
          }
          System.arraycopy(fastEMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = emaPrivate(0, outNbElement1.value - 1, fastEMABuffer, optInSignalPeriod, signalK, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int macdExtLookback( int optInFastPeriod, MAType optInFastMAType, int optInSlowPeriod, MAType optInSlowMAType, int optInSignalPeriod, MAType optInSignalMAType )
       {
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return -1;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return -1;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return -1;
          }
          int tempInteger;
          int lookbackLargest;
          /* Find the MA with the largest lookback */
          lookbackLargest = movingAverageLookback(optInFastPeriod, optInFastMAType);
          tempInteger = movingAverageLookback(optInSlowPeriod, optInSlowMAType);
          if( tempInteger > lookbackLargest ) {
             lookbackLargest = tempInteger;
          }
          /* Add to the largest MA lookback the signal line lookback */
          return lookbackLargest + movingAverageLookback(optInSignalPeriod, optInSignalMAType) ;

       }
       public RetCode macdExt( int startIdx,
                               int endIdx,
                               double inReal[],
                               int optInFastPeriod,
                               MAType optInFastMAType,
                               int optInSlowPeriod,
                               MAType optInSlowMAType,
                               int optInSignalPeriod,
                               MAType optInSignalMAType,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outMACD[],
                               double outMACDSignal[],
                               double outMACDHist[] )
       {
          double[] slowMABuffer;
          double[] fastMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int lookbackLargest = 0;
          int i = 0;
          MAType tempMAType;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Make sure slow is really slower than
           * the fast period! if not, swap...
           */
          if( optInSlowPeriod < optInFastPeriod ) {
             /* swap period */
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
             /* swap type */
             tempMAType = optInSlowMAType;
             optInSlowMAType = optInFastMAType;
             optInFastMAType = tempMAType;
          }
          /* Find the MA with the largest lookback */
          lookbackLargest = movingAverageLookback(optInFastPeriod, optInFastMAType);
          tempInteger = movingAverageLookback(optInSlowPeriod, optInSlowMAType);
          if( tempInteger > lookbackLargest ) {
             lookbackLargest = tempInteger;
          }
          /* Add the lookback needed for the signal line */
          lookbackSignal = movingAverageLookback(optInSignalPeriod, optInSignalMAType);
          lookbackTotal = lookbackSignal + lookbackLargest;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Allocate intermediate buffer for fast/slow MA. */
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastMABuffer = new double[(int)(tempInteger * 1)];
          slowMABuffer = new double[(int)(tempInteger * 1)];
          /* Calculate the slow MA.
           *
           * Move back the startIdx to get enough data
           * for the signal period. That way, once the
           * signal calculation is done, all the output
           * will start at the requested 'startIdx'.
           */
          tempInteger = startIdx - lookbackSignal;
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, optInSlowMAType, outBegIdx1, outNbElement1, slowMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the fast MA. */
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, optInFastMAType, outBegIdx2, outNbElement2, fastMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Parano tests. Will be removed eventually. */
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          /* Calculate (fast MA) - (slow MA). */
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastMABuffer[i] = fastMABuffer[i] - slowMABuffer[i];
          }
          /* Copy the result into the output for the caller. */
          System.arraycopy(fastMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          /* Calculate the signal/trigger line. */
          retCode = movingAverageUnguarded(0, outNbElement1.value - 1, fastMABuffer, optInSignalPeriod, optInSignalMAType, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the histogram. */
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          /* All done! Indicate the output limits and return success. */
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macdExtUnguarded( int startIdx,
                                        int endIdx,
                                        double inReal[],
                                        int optInFastPeriod,
                                        MAType optInFastMAType,
                                        int optInSlowPeriod,
                                        MAType optInSlowMAType,
                                        int optInSignalPeriod,
                                        MAType optInSignalMAType,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outMACD[],
                                        double outMACDSignal[],
                                        double outMACDHist[] )
       {
          double[] slowMABuffer;
          double[] fastMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int lookbackLargest = 0;
          int i = 0;
          MAType tempMAType;
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
             tempMAType = optInSlowMAType;
             optInSlowMAType = optInFastMAType;
             optInFastMAType = tempMAType;
          }
          lookbackLargest = movingAverageLookback(optInFastPeriod, optInFastMAType);
          tempInteger = movingAverageLookback(optInSlowPeriod, optInSlowMAType);
          if( tempInteger > lookbackLargest ) {
             lookbackLargest = tempInteger;
          }
          lookbackSignal = movingAverageLookback(optInSignalPeriod, optInSignalMAType);
          lookbackTotal = lookbackSignal + lookbackLargest;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastMABuffer = new double[(int)(tempInteger * 1)];
          slowMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, optInSlowMAType, outBegIdx1, outNbElement1, slowMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, optInFastMAType, outBegIdx2, outNbElement2, fastMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastMABuffer[i] = fastMABuffer[i] - slowMABuffer[i];
          }
          System.arraycopy(fastMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = movingAverageUnguarded(0, outNbElement1.value - 1, fastMABuffer, optInSignalPeriod, optInSignalMAType, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macdExt( int startIdx,
                               int endIdx,
                               float inReal[],
                               int optInFastPeriod,
                               MAType optInFastMAType,
                               int optInSlowPeriod,
                               MAType optInSlowMAType,
                               int optInSignalPeriod,
                               MAType optInSignalMAType,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outMACD[],
                               double outMACDSignal[],
                               double outMACDHist[] )
       {
          double[] slowMABuffer;
          double[] fastMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int lookbackLargest = 0;
          int i = 0;
          MAType tempMAType;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
             tempMAType = optInSlowMAType;
             optInSlowMAType = optInFastMAType;
             optInFastMAType = tempMAType;
          }
          lookbackLargest = movingAverageLookback(optInFastPeriod, optInFastMAType);
          tempInteger = movingAverageLookback(optInSlowPeriod, optInSlowMAType);
          if( tempInteger > lookbackLargest ) {
             lookbackLargest = tempInteger;
          }
          lookbackSignal = movingAverageLookback(optInSignalPeriod, optInSignalMAType);
          lookbackTotal = lookbackSignal + lookbackLargest;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastMABuffer = new double[(int)(tempInteger * 1)];
          slowMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, optInSlowMAType, outBegIdx1, outNbElement1, slowMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, optInFastMAType, outBegIdx2, outNbElement2, fastMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastMABuffer[i] = fastMABuffer[i] - slowMABuffer[i];
          }
          System.arraycopy(fastMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = movingAverageUnguarded(0, outNbElement1.value - 1, fastMABuffer, optInSignalPeriod, optInSignalMAType, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
       public RetCode macdExtUnguarded( int startIdx,
                                        int endIdx,
                                        float inReal[],
                                        int optInFastPeriod,
                                        MAType optInFastMAType,
                                        int optInSlowPeriod,
                                        MAType optInSlowMAType,
                                        int optInSignalPeriod,
                                        MAType optInSignalMAType,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outMACD[],
                                        double outMACDSignal[],
                                        double outMACDHist[] )
       {
          double[] slowMABuffer;
          double[] fastMABuffer;
          RetCode retCode;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int lookbackTotal = 0;
          int lookbackSignal = 0;
          int lookbackLargest = 0;
          int i = 0;
          MAType tempMAType;
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
             tempMAType = optInSlowMAType;
             optInSlowMAType = optInFastMAType;
             optInFastMAType = tempMAType;
          }
          lookbackLargest = movingAverageLookback(optInFastPeriod, optInFastMAType);
          tempInteger = movingAverageLookback(optInSlowPeriod, optInSlowMAType);
          if( tempInteger > lookbackLargest ) {
             lookbackLargest = tempInteger;
          }
          lookbackSignal = movingAverageLookback(optInSignalPeriod, optInSignalMAType);
          lookbackTotal = lookbackSignal + lookbackLargest;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          tempInteger = endIdx - startIdx + 1 + lookbackSignal;
          fastMABuffer = new double[(int)(tempInteger * 1)];
          slowMABuffer = new double[(int)(tempInteger * 1)];
          tempInteger = startIdx - lookbackSignal;
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInSlowPeriod, optInSlowMAType, outBegIdx1, outNbElement1, slowMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(tempInteger, endIdx, inReal, optInFastPeriod, optInFastMAType, outBegIdx2, outNbElement2, fastMABuffer);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          if( outBegIdx1.value != tempInteger || outBegIdx2.value != tempInteger || outNbElement1.value != outNbElement2.value || outNbElement1.value != endIdx - startIdx + 1 + lookbackSignal ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.BadParam ;
          }
          for( i = 0; i < outNbElement1.value; i += 1 ) {
             fastMABuffer[i] = fastMABuffer[i] - slowMABuffer[i];
          }
          System.arraycopy(fastMABuffer, lookbackSignal, outMACD, 0, (endIdx - startIdx + 1) * 1);
          retCode = movingAverageUnguarded(0, outNbElement1.value - 1, fastMABuffer, optInSignalPeriod, optInSignalMAType, outBegIdx2, outNbElement2, outMACDSignal);
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          for( i = 0; i < outNbElement2.value; i += 1 ) {
             outMACDHist[i] = outMACD[i] - outMACDSignal[i];
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outNbElement2.value;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int macdFixLookback( int optInSignalPeriod )
       {
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return -1;
          }
          /* The lookback is driven by the signal line output.
           *
           * (must also account for the initial data consume
           *  by the fix 26 period EMA).
           */
          return emaLookback(26) + emaLookback(optInSignalPeriod) ;

       }
       public RetCode macdFix( int startIdx,
                               int endIdx,
                               double inReal[],
                               int optInSignalPeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outMACD[],
                               double outMACDSignal[],
                               double outMACDHist[] )
       {
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          return macdUnguarded(startIdx, endIdx, inReal, 0, 0, optInSignalPeriod, outBegIdx, outNBElement, outMACD, outMACDSignal, outMACDHist) ;
          /* 0 indicate fix 12 == 0.15  for optInFastPeriod */
          /* 0 indicate fix 26 == 0.075 for optInSlowPeriod */
       }
       public RetCode macdFixUnguarded( int startIdx,
                                        int endIdx,
                                        double inReal[],
                                        int optInSignalPeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outMACD[],
                                        double outMACDSignal[],
                                        double outMACDHist[] )
       {
          return macdUnguarded(startIdx, endIdx, inReal, 0, 0, optInSignalPeriod, outBegIdx, outNBElement, outMACD, outMACDSignal, outMACDHist) ;
       }
       public RetCode macdFix( int startIdx,
                               int endIdx,
                               float inReal[],
                               int optInSignalPeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outMACD[],
                               double outMACDSignal[],
                               double outMACDHist[] )
       {
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInSignalPeriod == Integer.MIN_VALUE ) {
             optInSignalPeriod = 9;
          } else if( optInSignalPeriod < 1 || optInSignalPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          return macdUnguarded(startIdx, endIdx, inReal, 0, 0, optInSignalPeriod, outBegIdx, outNBElement, outMACD, outMACDSignal, outMACDHist) ;
       }
       public RetCode macdFixUnguarded( int startIdx,
                                        int endIdx,
                                        float inReal[],
                                        int optInSignalPeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outMACD[],
                                        double outMACDSignal[],
                                        double outMACDHist[] )
       {
          return macdUnguarded(startIdx, endIdx, inReal, 0, 0, optInSignalPeriod, outBegIdx, outNBElement, outMACD, outMACDSignal, outMACDHist) ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  023003 MF   Initial Coding of MAMA.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int mamaLookback( double optInFastLimit, double optInSlowLimit )
       {
          if( optInFastLimit == -4e37 ) {
             optInFastLimit = 5e-1;
          } else if( optInFastLimit < 1e-2 || optInFastLimit > 9.9e-1 ) {
             return -1;
          }
          if( optInSlowLimit == -4e37 ) {
             optInSlowLimit = 5e-2;
          } else if( optInSlowLimit < 1e-2 || optInSlowLimit > 9.9e-1 ) {
             return -1;
          }
          /* The two parameters are not a factor to determine
           * the lookback, but are still requested for
           * consistency with all other Lookback functions.
           */
          /* Lookback is a fix amount + the unstable period.
           *
           *
           * The fix lookback is 32 and is establish as follow:
           *
           *         12 price bar to be compatible with the implementation
           *            of TradeStation found in John Ehlers book.
           *          6 price bars for the Detrender
           *          6 price bars for Q1
           *          3 price bars for jI
           *          3 price bars for jQ
           *          1 price bar for Re/Im
           *          1 price bar for the Delta Phase
           *        -------
           *         32 Total
           */
          return 32 + this.unstablePeriod[FuncUnstId.Mama.ordinal()] ;

       }
       public RetCode mama( int startIdx,
                            int endIdx,
                            double inReal[],
                            double optInFastLimit,
                            double optInSlowLimit,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outMAMA[],
                            double outFAMA[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double mama = 0;
          double fama = 0;
          double todayValue = 0;
          double prevPhase = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastLimit == -4e37 ) {
             optInFastLimit = 5e-1;
          } else if( optInFastLimit < 1e-2 || optInFastLimit > 9.9e-1 ) {
             return RetCode.BadParam;
          }
          if( optInSlowLimit == -4e37 ) {
             optInSlowLimit = 5e-2;
          } else if( optInSlowLimit < 1e-2 || optInSlowLimit > 9.9e-1 ) {
             return RetCode.BadParam;
          }
          a = 0.0962;
          b = 0.5769;
          /* Variable used for the price smoother (a weighted moving average). */
          /* Variables used for the Hilbert Transormation */
          /* Constant */
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.Mama.ordinal()];
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          /* Initialize the price smoother, which is simply a weighted
           * moving average of the price.
           * To understand this algorithm, I strongly suggest to understand
           * first how TA_WMA is done.
           */
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          /* Initialization is same as WMA, except loop is unrolled
           * for speed optimization.
           */
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          /* Subsequent WMA value are evaluated by using
           * the DO_PRICE_WMA macro.
           */
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          /* Initialize the circular buffers used by the hilbert
           * transform logic.
           * A buffer is used for odd day and another for even days.
           * This minimize the number of memory access and floating point
           * operations needed (note also that by using static circular buffer,
           * no large dynamic memory allocation is needed for storing
           * intermediate calculation!).
           */
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          fama = 0.0;
          mama = fama;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          prevPhase = 0.0;
          /* The code is speed optimized and is most likely very
           * hard to follow if you do not already know well the
           * original algorithm.
           * To understadn better, it is strongly suggested to look
           * first at the Excel implementation in "test_MAMA.xls" included
           * in this package.
           */
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                /* Do the Hilbert Transforms for even price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                /* The variable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
                /* Put Alpha in tempReal2 */
                if( I1ForEvenPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForEvenPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             } else {
                /* Do the Hilbert Transforms for odd price bar */
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                /* The varaiable I1 is the detrender delayed for
                 * 3 price bars.
                 *
                 * Save the current detrender value for being
                 * used by the "odd" logic later.
                 */
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
                /* Put Alpha in tempReal2 */
                if( I1ForOddPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForOddPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             }
             /* Put Delta Phase into tempReal */
             tempReal = prevPhase - tempReal2;
             prevPhase = tempReal2;
             if( tempReal < 1.0 ) {
                tempReal = 1.0;
             }
             /* Put Alpha into tempReal */
             if( tempReal > 1.0 ) {
                tempReal = optInFastLimit / tempReal;
                if( tempReal < optInSlowLimit ) {
                   tempReal = optInSlowLimit;
                }
             } else {
                tempReal = optInFastLimit;
             }
             /* Calculate MAMA, FAMA */
             mama = tempReal * todayValue + (1 - tempReal) * mama;
             tempReal *= 0.5;
             fama = tempReal * mama + (1 - tempReal) * fama;
             if( today >= startIdx ) {
                outMAMA[outIdx] = mama;
                outFAMA[outIdx++] = fama;
             }
             /* Adjust the period for next price bar */
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             /* Ooof... let's do the next price bar now! */
             today += 1;
          }
          /* Default return values */
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mamaUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     double optInFastLimit,
                                     double optInSlowLimit,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outMAMA[],
                                     double outFAMA[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double mama = 0;
          double fama = 0;
          double todayValue = 0;
          double prevPhase = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.Mama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          fama = 0.0;
          mama = fama;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          prevPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
                if( I1ForEvenPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForEvenPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
                if( I1ForOddPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForOddPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             }
             tempReal = prevPhase - tempReal2;
             prevPhase = tempReal2;
             if( tempReal < 1.0 ) {
                tempReal = 1.0;
             }
             if( tempReal > 1.0 ) {
                tempReal = optInFastLimit / tempReal;
                if( tempReal < optInSlowLimit ) {
                   tempReal = optInSlowLimit;
                }
             } else {
                tempReal = optInFastLimit;
             }
             mama = tempReal * todayValue + (1 - tempReal) * mama;
             tempReal *= 0.5;
             fama = tempReal * mama + (1 - tempReal) * fama;
             if( today >= startIdx ) {
                outMAMA[outIdx] = mama;
                outFAMA[outIdx++] = fama;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mama( int startIdx,
                            int endIdx,
                            float inReal[],
                            double optInFastLimit,
                            double optInSlowLimit,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outMAMA[],
                            double outFAMA[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double mama = 0;
          double fama = 0;
          double todayValue = 0;
          double prevPhase = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastLimit == -4e37 ) {
             optInFastLimit = 5e-1;
          } else if( optInFastLimit < 1e-2 || optInFastLimit > 9.9e-1 ) {
             return RetCode.BadParam;
          }
          if( optInSlowLimit == -4e37 ) {
             optInSlowLimit = 5e-2;
          } else if( optInSlowLimit < 1e-2 || optInSlowLimit > 9.9e-1 ) {
             return RetCode.BadParam;
          }
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.Mama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          fama = 0.0;
          mama = fama;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          prevPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
                if( I1ForEvenPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForEvenPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
                if( I1ForOddPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForOddPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             }
             tempReal = prevPhase - tempReal2;
             prevPhase = tempReal2;
             if( tempReal < 1.0 ) {
                tempReal = 1.0;
             }
             if( tempReal > 1.0 ) {
                tempReal = optInFastLimit / tempReal;
                if( tempReal < optInSlowLimit ) {
                   tempReal = optInSlowLimit;
                }
             } else {
                tempReal = optInFastLimit;
             }
             mama = tempReal * todayValue + (1 - tempReal) * mama;
             tempReal *= 0.5;
             fama = tempReal * mama + (1 - tempReal) * fama;
             if( today >= startIdx ) {
                outMAMA[outIdx] = mama;
                outFAMA[outIdx++] = fama;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mamaUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     double optInFastLimit,
                                     double optInSlowLimit,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outMAMA[],
                                     double outFAMA[] )
       {
          int outIdx = 0;
          int i = 0;
          int lookbackTotal = 0;
          int today = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double adjustedPrevPeriod = 0;
          double period = 0;
          int trailingWMAIdx = 0;
          double periodWMASum = 0;
          double periodWMASub = 0;
          double trailingWMAValue = 0;
          double smoothedValue = 0;
          double a = 0;
          double b = 0;
          double hilbertTempReal = 0;
          int hilbertIdx = 0;
          double[] detrender_Odd = new double[3];
          double[] detrender_Even = new double[3];
          double detrender = 0;
          double prev_detrender_Odd = 0;
          double prev_detrender_Even = 0;
          double prev_detrender_input_Odd = 0;
          double prev_detrender_input_Even = 0;
          double[] Q1_Odd = new double[3];
          double[] Q1_Even = new double[3];
          double Q1 = 0;
          double prev_Q1_Odd = 0;
          double prev_Q1_Even = 0;
          double prev_Q1_input_Odd = 0;
          double prev_Q1_input_Even = 0;
          double[] jI_Odd = new double[3];
          double[] jI_Even = new double[3];
          double jI = 0;
          double prev_jI_Odd = 0;
          double prev_jI_Even = 0;
          double prev_jI_input_Odd = 0;
          double prev_jI_input_Even = 0;
          double[] jQ_Odd = new double[3];
          double[] jQ_Even = new double[3];
          double jQ = 0;
          double prev_jQ_Odd = 0;
          double prev_jQ_Even = 0;
          double prev_jQ_input_Odd = 0;
          double prev_jQ_input_Even = 0;
          double Q2 = 0;
          double I2 = 0;
          double prevQ2 = 0;
          double prevI2 = 0;
          double Re = 0;
          double Im = 0;
          double I1ForOddPrev2 = 0;
          double I1ForOddPrev3 = 0;
          double I1ForEvenPrev2 = 0;
          double I1ForEvenPrev3 = 0;
          double rad2Deg = 0;
          double mama = 0;
          double fama = 0;
          double todayValue = 0;
          double prevPhase = 0;
          a = 0.0962;
          b = 0.5769;
          rad2Deg = 180.0 / (4.0 * Math.atan(1));
          lookbackTotal = 32 + this.unstablePeriod[FuncUnstId.Mama.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          trailingWMAIdx = startIdx - lookbackTotal;
          today = trailingWMAIdx;
          tempReal = inReal[today++];
          periodWMASub = tempReal;
          periodWMASum = tempReal;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 2.0;
          tempReal = inReal[today++];
          periodWMASub += tempReal;
          periodWMASum += tempReal * 3.0;
          trailingWMAValue = 0.0;
          i = 9;
          do {
             tempReal = inReal[today++];
             periodWMASub += tempReal;
             periodWMASub -= trailingWMAValue;
             periodWMASum += tempReal * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
          } while( --i != 0 );
          hilbertIdx = 0;
          detrender_Odd[0] = 0.0;
          detrender_Odd[1] = 0.0;
          detrender_Odd[2] = 0.0;
          detrender_Even[0] = 0.0;
          detrender_Even[1] = 0.0;
          detrender_Even[2] = 0.0;
          detrender = 0.0;
          prev_detrender_Odd = 0.0;
          prev_detrender_Even = 0.0;
          prev_detrender_input_Odd = 0.0;
          prev_detrender_input_Even = 0.0;
          Q1_Odd[0] = 0.0;
          Q1_Odd[1] = 0.0;
          Q1_Odd[2] = 0.0;
          Q1_Even[0] = 0.0;
          Q1_Even[1] = 0.0;
          Q1_Even[2] = 0.0;
          Q1 = 0.0;
          prev_Q1_Odd = 0.0;
          prev_Q1_Even = 0.0;
          prev_Q1_input_Odd = 0.0;
          prev_Q1_input_Even = 0.0;
          jI_Odd[0] = 0.0;
          jI_Odd[1] = 0.0;
          jI_Odd[2] = 0.0;
          jI_Even[0] = 0.0;
          jI_Even[1] = 0.0;
          jI_Even[2] = 0.0;
          jI = 0.0;
          prev_jI_Odd = 0.0;
          prev_jI_Even = 0.0;
          prev_jI_input_Odd = 0.0;
          prev_jI_input_Even = 0.0;
          jQ_Odd[0] = 0.0;
          jQ_Odd[1] = 0.0;
          jQ_Odd[2] = 0.0;
          jQ_Even[0] = 0.0;
          jQ_Even[1] = 0.0;
          jQ_Even[2] = 0.0;
          jQ = 0.0;
          prev_jQ_Odd = 0.0;
          prev_jQ_Even = 0.0;
          prev_jQ_input_Odd = 0.0;
          prev_jQ_input_Even = 0.0;
          period = 0.0;
          outIdx = 0;
          prevQ2 = 0.0;
          prevI2 = prevQ2;
          Im = 0.0;
          Re = Im;
          fama = 0.0;
          mama = fama;
          I1ForEvenPrev3 = 0.0;
          I1ForOddPrev3 = I1ForEvenPrev3;
          I1ForEvenPrev2 = 0.0;
          I1ForOddPrev2 = I1ForEvenPrev2;
          prevPhase = 0.0;
          while( today <= endIdx ) {
             adjustedPrevPeriod = 0.075 * period + 0.54;
             todayValue = inReal[today];
             periodWMASub += todayValue;
             periodWMASub -= trailingWMAValue;
             periodWMASum += todayValue * 4.0;
             trailingWMAValue = inReal[trailingWMAIdx++];
             smoothedValue = periodWMASum * 0.1;
             periodWMASum -= periodWMASub;
             if( today % 2 == 0 ) {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Even[hilbertIdx];
                detrender_Even[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Even;
                prev_detrender_Even = b * prev_detrender_input_Even;
                detrender += prev_detrender_Even;
                prev_detrender_input_Even = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Even[hilbertIdx];
                Q1_Even[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Even;
                prev_Q1_Even = b * prev_Q1_input_Even;
                Q1 += prev_Q1_Even;
                prev_Q1_input_Even = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForEvenPrev3;
                jI = 0 - jI_Even[hilbertIdx];
                jI_Even[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Even;
                prev_jI_Even = b * prev_jI_input_Even;
                jI += prev_jI_Even;
                prev_jI_input_Even = I1ForEvenPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Even[hilbertIdx];
                jQ_Even[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Even;
                prev_jQ_Even = b * prev_jQ_input_Even;
                jQ += prev_jQ_Even;
                prev_jQ_input_Even = Q1;
                jQ *= adjustedPrevPeriod;
                if( ++hilbertIdx == 3 ) {
                   hilbertIdx = 0;
                }
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForEvenPrev3 - jQ) + 0.8 * prevI2;
                I1ForOddPrev3 = I1ForOddPrev2;
                I1ForOddPrev2 = detrender;
                if( I1ForEvenPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForEvenPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             } else {
                hilbertTempReal = a * smoothedValue;
                detrender = 0 - detrender_Odd[hilbertIdx];
                detrender_Odd[hilbertIdx] = hilbertTempReal;
                detrender += hilbertTempReal;
                detrender -= prev_detrender_Odd;
                prev_detrender_Odd = b * prev_detrender_input_Odd;
                detrender += prev_detrender_Odd;
                prev_detrender_input_Odd = smoothedValue;
                detrender *= adjustedPrevPeriod;
                hilbertTempReal = a * detrender;
                Q1 = 0 - Q1_Odd[hilbertIdx];
                Q1_Odd[hilbertIdx] = hilbertTempReal;
                Q1 += hilbertTempReal;
                Q1 -= prev_Q1_Odd;
                prev_Q1_Odd = b * prev_Q1_input_Odd;
                Q1 += prev_Q1_Odd;
                prev_Q1_input_Odd = detrender;
                Q1 *= adjustedPrevPeriod;
                hilbertTempReal = a * I1ForOddPrev3;
                jI = 0 - jI_Odd[hilbertIdx];
                jI_Odd[hilbertIdx] = hilbertTempReal;
                jI += hilbertTempReal;
                jI -= prev_jI_Odd;
                prev_jI_Odd = b * prev_jI_input_Odd;
                jI += prev_jI_Odd;
                prev_jI_input_Odd = I1ForOddPrev3;
                jI *= adjustedPrevPeriod;
                hilbertTempReal = a * Q1;
                jQ = 0 - jQ_Odd[hilbertIdx];
                jQ_Odd[hilbertIdx] = hilbertTempReal;
                jQ += hilbertTempReal;
                jQ -= prev_jQ_Odd;
                prev_jQ_Odd = b * prev_jQ_input_Odd;
                jQ += prev_jQ_Odd;
                prev_jQ_input_Odd = Q1;
                jQ *= adjustedPrevPeriod;
                Q2 = 0.2 * (Q1 + jI) + 0.8 * prevQ2;
                I2 = 0.2 * (I1ForOddPrev3 - jQ) + 0.8 * prevI2;
                I1ForEvenPrev3 = I1ForEvenPrev2;
                I1ForEvenPrev2 = detrender;
                if( I1ForOddPrev3 != 0.0 ) {
                   tempReal2 = Math.atan(Q1 / I1ForOddPrev3) * rad2Deg;
                } else {
                   tempReal2 = 0.0;
                }
             }
             tempReal = prevPhase - tempReal2;
             prevPhase = tempReal2;
             if( tempReal < 1.0 ) {
                tempReal = 1.0;
             }
             if( tempReal > 1.0 ) {
                tempReal = optInFastLimit / tempReal;
                if( tempReal < optInSlowLimit ) {
                   tempReal = optInSlowLimit;
                }
             } else {
                tempReal = optInFastLimit;
             }
             mama = tempReal * todayValue + (1 - tempReal) * mama;
             tempReal *= 0.5;
             fama = tempReal * mama + (1 - tempReal) * fama;
             if( today >= startIdx ) {
                outMAMA[outIdx] = mama;
                outFAMA[outIdx++] = fama;
             }
             Re = 0.2 * (I2 * prevI2 + Q2 * prevQ2) + 0.8 * Re;
             Im = 0.2 * (I2 * prevQ2 - Q2 * prevI2) + 0.8 * Im;
             prevQ2 = Q2;
             prevI2 = I2;
             tempReal = period;
             if( Im != 0.0 && Re != 0.0 ) {
                period = 360.0 / (Math.atan(Im / Re) * rad2Deg);
             }
             tempReal2 = 1.5 * tempReal;
             if( period > tempReal2 ) {
                period = tempReal2;
             }
             tempReal2 = 0.67 * tempReal;
             if( period < tempReal2 ) {
                period = tempReal2;
             }
             if( period < 6 ) {
                period = 6;
             } else if( period > 50 ) {
                period = 50;
             }
             period = 0.2 * period + 0.8 * tempReal;
             today += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  021807 MF     Initial Version
     */

       public int movingAverageVariablePeriodLookback( int optInMinPeriod, int optInMaxPeriod, MAType optInMAType )
       {
          if( optInMinPeriod == Integer.MIN_VALUE ) {
             optInMinPeriod = 2;
          } else if( optInMinPeriod < 1 || optInMinPeriod > 100000 ) {
             return -1;
          }
          if( optInMaxPeriod == Integer.MIN_VALUE ) {
             optInMaxPeriod = 30;
          } else if( optInMaxPeriod < 1 || optInMaxPeriod > 100000 ) {
             return -1;
          }
          return movingAverageLookback(optInMaxPeriod, optInMAType) ;

       }
       public RetCode movingAverageVariablePeriod( int startIdx,
                                                   int endIdx,
                                                   double inReal[],
                                                   double inPeriods[],
                                                   int optInMinPeriod,
                                                   int optInMaxPeriod,
                                                   MAType optInMAType,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   double outReal[] )
       {
          int i = 0;
          int j = 0;
          int lookbackTotal = 0;
          int outputSize = 0;
          int tempInt = 0;
          int curPeriod = 0;
          int[] localPeriodArray;
          double[] localOutputArray;
          MInteger localBegIdx = new MInteger();
          MInteger localNbElement = new MInteger();
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInMinPeriod == Integer.MIN_VALUE ) {
             optInMinPeriod = 2;
          } else if( optInMinPeriod < 1 || optInMinPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInMaxPeriod == Integer.MIN_VALUE ) {
             optInMaxPeriod = 30;
          } else if( optInMaxPeriod < 1 || optInMaxPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = movingAverageLookback(optInMaxPeriod, optInMAType);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate exact output size */
          if( lookbackTotal > startIdx ) {
             tempInt = lookbackTotal;
          } else {
             tempInt = startIdx;
          }
          if( tempInt > endIdx ) {
             /* No output */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - tempInt + 1;
          /* Allocate intermediate local buffer. */
          localOutputArray = new double[(int)(outputSize * 1)];
          localPeriodArray = new int[(int)(outputSize * 1)];
          /* Copy caller array of period into local buffer.
           * At the same time, truncate to min/max.
           */
          for( i = 0; i < outputSize; i += 1 ) {
             tempInt = (int)inPeriods[startIdx + i];
             if( tempInt < optInMinPeriod ) {
                tempInt = optInMinPeriod;
             } else if( tempInt > optInMaxPeriod ) {
                tempInt = optInMaxPeriod;
             }
             localPeriodArray[i] = tempInt;
          }
          /* Process each element of the input.
           * For each possible period value, the MA is calculated
           * only once.
           * The outReal is then fill up for all element with
           * the same period.
           * A local flag (value 0) is set in localPeriodArray
           * to avoid doing a second time the same calculation.
           */
          for( i = 0; i < outputSize; i += 1 ) {
             curPeriod = localPeriodArray[i];
             if( curPeriod != 0 ) {
                /* TODO: This portion of the function can be slightly speed
                 *       optimized by making the function without unstable period
                 *       start their calculation at 'startIdx+i' instead of startIdx.
                 */
                /* Calculation of the MA required. */
                retCode = movingAverageUnguarded(startIdx, endIdx, inReal, curPeriod, optInMAType, localBegIdx, localNbElement, localOutputArray);
                if( retCode != RetCode.Success ) {
                   outBegIdx.value = 0;
                   outNBElement.value = 0;
                   return retCode ;
                }
                outReal[i] = localOutputArray[i];
                for( j = i + 1; j < outputSize; j += 1 ) {
                   if( localPeriodArray[j] == curPeriod ) {
                      localPeriodArray[j] = 0;
                      /* Flag to avoid recalculation */
                      outReal[j] = localOutputArray[j];
                   }
                }
             }
          }
          /* Done. Inform the caller of the success. */
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode movingAverageVariablePeriodUnguarded( int startIdx,
                                                            int endIdx,
                                                            double inReal[],
                                                            double inPeriods[],
                                                            int optInMinPeriod,
                                                            int optInMaxPeriod,
                                                            MAType optInMAType,
                                                            MInteger outBegIdx,
                                                            MInteger outNBElement,
                                                            double outReal[] )
       {
          int i = 0;
          int j = 0;
          int lookbackTotal = 0;
          int outputSize = 0;
          int tempInt = 0;
          int curPeriod = 0;
          int[] localPeriodArray;
          double[] localOutputArray;
          MInteger localBegIdx = new MInteger();
          MInteger localNbElement = new MInteger();
          RetCode retCode;
          lookbackTotal = movingAverageLookback(optInMaxPeriod, optInMAType);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( lookbackTotal > startIdx ) {
             tempInt = lookbackTotal;
          } else {
             tempInt = startIdx;
          }
          if( tempInt > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - tempInt + 1;
          localOutputArray = new double[(int)(outputSize * 1)];
          localPeriodArray = new int[(int)(outputSize * 1)];
          for( i = 0; i < outputSize; i += 1 ) {
             tempInt = (int)inPeriods[startIdx + i];
             if( tempInt < optInMinPeriod ) {
                tempInt = optInMinPeriod;
             } else if( tempInt > optInMaxPeriod ) {
                tempInt = optInMaxPeriod;
             }
             localPeriodArray[i] = tempInt;
          }
          for( i = 0; i < outputSize; i += 1 ) {
             curPeriod = localPeriodArray[i];
             if( curPeriod != 0 ) {
                retCode = movingAverageUnguarded(startIdx, endIdx, inReal, curPeriod, optInMAType, localBegIdx, localNbElement, localOutputArray);
                if( retCode != RetCode.Success ) {
                   outBegIdx.value = 0;
                   outNBElement.value = 0;
                   return retCode ;
                }
                outReal[i] = localOutputArray[i];
                for( j = i + 1; j < outputSize; j += 1 ) {
                   if( localPeriodArray[j] == curPeriod ) {
                      localPeriodArray[j] = 0;
                      outReal[j] = localOutputArray[j];
                   }
                }
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode movingAverageVariablePeriod( int startIdx,
                                                   int endIdx,
                                                   float inReal[],
                                                   float inPeriods[],
                                                   int optInMinPeriod,
                                                   int optInMaxPeriod,
                                                   MAType optInMAType,
                                                   MInteger outBegIdx,
                                                   MInteger outNBElement,
                                                   double outReal[] )
       {
          int i = 0;
          int j = 0;
          int lookbackTotal = 0;
          int outputSize = 0;
          int tempInt = 0;
          int curPeriod = 0;
          int[] localPeriodArray;
          double[] localOutputArray;
          MInteger localBegIdx = new MInteger();
          MInteger localNbElement = new MInteger();
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInMinPeriod == Integer.MIN_VALUE ) {
             optInMinPeriod = 2;
          } else if( optInMinPeriod < 1 || optInMinPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInMaxPeriod == Integer.MIN_VALUE ) {
             optInMaxPeriod = 30;
          } else if( optInMaxPeriod < 1 || optInMaxPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = movingAverageLookback(optInMaxPeriod, optInMAType);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( lookbackTotal > startIdx ) {
             tempInt = lookbackTotal;
          } else {
             tempInt = startIdx;
          }
          if( tempInt > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - tempInt + 1;
          localOutputArray = new double[(int)(outputSize * 1)];
          localPeriodArray = new int[(int)(outputSize * 1)];
          for( i = 0; i < outputSize; i += 1 ) {
             tempInt = (int)inPeriods[startIdx + i];
             if( tempInt < optInMinPeriod ) {
                tempInt = optInMinPeriod;
             } else if( tempInt > optInMaxPeriod ) {
                tempInt = optInMaxPeriod;
             }
             localPeriodArray[i] = tempInt;
          }
          for( i = 0; i < outputSize; i += 1 ) {
             curPeriod = localPeriodArray[i];
             if( curPeriod != 0 ) {
                retCode = movingAverageUnguarded(startIdx, endIdx, inReal, curPeriod, optInMAType, localBegIdx, localNbElement, localOutputArray);
                if( retCode != RetCode.Success ) {
                   outBegIdx.value = 0;
                   outNBElement.value = 0;
                   return retCode ;
                }
                outReal[i] = localOutputArray[i];
                for( j = i + 1; j < outputSize; j += 1 ) {
                   if( localPeriodArray[j] == curPeriod ) {
                      localPeriodArray[j] = 0;
                      outReal[j] = localOutputArray[j];
                   }
                }
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
       public RetCode movingAverageVariablePeriodUnguarded( int startIdx,
                                                            int endIdx,
                                                            float inReal[],
                                                            float inPeriods[],
                                                            int optInMinPeriod,
                                                            int optInMaxPeriod,
                                                            MAType optInMAType,
                                                            MInteger outBegIdx,
                                                            MInteger outNBElement,
                                                            double outReal[] )
       {
          int i = 0;
          int j = 0;
          int lookbackTotal = 0;
          int outputSize = 0;
          int tempInt = 0;
          int curPeriod = 0;
          int[] localPeriodArray;
          double[] localOutputArray;
          MInteger localBegIdx = new MInteger();
          MInteger localNbElement = new MInteger();
          RetCode retCode;
          lookbackTotal = movingAverageLookback(optInMaxPeriod, optInMAType);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( lookbackTotal > startIdx ) {
             tempInt = lookbackTotal;
          } else {
             tempInt = startIdx;
          }
          if( tempInt > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outputSize = endIdx - tempInt + 1;
          localOutputArray = new double[(int)(outputSize * 1)];
          localPeriodArray = new int[(int)(outputSize * 1)];
          for( i = 0; i < outputSize; i += 1 ) {
             tempInt = (int)inPeriods[startIdx + i];
             if( tempInt < optInMinPeriod ) {
                tempInt = optInMinPeriod;
             } else if( tempInt > optInMaxPeriod ) {
                tempInt = optInMaxPeriod;
             }
             localPeriodArray[i] = tempInt;
          }
          for( i = 0; i < outputSize; i += 1 ) {
             curPeriod = localPeriodArray[i];
             if( curPeriod != 0 ) {
                retCode = movingAverageUnguarded(startIdx, endIdx, inReal, curPeriod, optInMAType, localBegIdx, localNbElement, localOutputArray);
                if( retCode != RetCode.Success ) {
                   outBegIdx.value = 0;
                   outNBElement.value = 0;
                   return retCode ;
                }
                outReal[i] = localOutputArray[i];
                for( j = i + 1; j < outputSize; j += 1 ) {
                   if( localPeriodArray[j] == curPeriod ) {
                      localPeriodArray[j] = 0;
                      outReal[j] = localOutputArray[j];
                   }
                }
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outputSize;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JV       Jesus Viver <324122@cienz.unizar.es>
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  101902 JV   Speed optimization of the algorithm
     *  102202 MF   Speed optimize a bit further
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int maxLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode max( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outReal[outIdx++] = highest;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode maxUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outReal[outIdx++] = highest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode max( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outReal[outIdx++] = highest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode maxUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outReal[outIdx++] = highest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120806 AC   Creation (equal to MAX but outputs index)
     */

       public int maxIndexLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode maxIndex( int startIdx,
                                int endIdx,
                                double inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                int outInteger[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outInteger[outIdx++] = highestIdx;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode maxIndexUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outInteger[outIdx++] = highestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode maxIndex( int startIdx,
                                int endIdx,
                                float inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                int outInteger[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outInteger[outIdx++] = highestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode maxIndexUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double highest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
             }
             outInteger[outIdx++] = highestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  112605 MF   Fix outBegIdx when startIdx != 0
     */

       public int medPriceLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode medPrice( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* MEDPRICE = (High + Low ) / 2
           * This is the high and low of the same price bar.
           *
           * See MIDPRICE to use instead the highest high and lowest
           * low over multiple price bar.
           */
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i]) / 2.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode medPriceUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i]) / 2.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode medPrice( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i]) / 2.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode medPriceUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i]) / 2.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  BT       BobTrader (TADoc.org forum user).
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF    Template creation.
     *  052603 MF    Adapt code to compile with .NET Managed C++
     *  062704 MF    Prevent divide by zero.
     *  121705 MF    Java port related changes.
     *  060907 MF,BT Fix #1727704. MFI logic bug when no price movement
     */

       public int mfiLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod + this.unstablePeriod[FuncUnstId.Mfi.ordinal()] ;

       }
       public RetCode mfi( int startIdx,
                           int endIdx,
                           double inHigh[],
                           double inLow[],
                           double inClose[],
                           double inVolume[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double posSumMF = 0;
          double negSumMF = 0;
          double prevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          int i = 0;
          int today = 0;
          double[] mflow_positive;
          double[] mflow_negative;
          int mflow_Idx = 0;
          int maxIdx_mflow = (50)-1;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Id, Type, Static Size */
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          mflow_positive = new double[optInTimePeriod];
          mflow_negative = new double[optInTimePeriod];
          maxIdx_mflow = (optInTimePeriod)-1;
          mflow_Idx = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Mfi.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          /* Accumulate the positive and negative money flow
           * among the initial period.
           */
          today = startIdx - lookbackTotal;
          prevValue = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
          posSumMF = 0.0;
          negSumMF = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          /* The following two equations are equivalent:
           *    MFI = 100 - (100 / 1 + (posSumMF/negSumMF))
           *    MFI = 100 * (posSumMF/(posSumMF+negSumMF))
           * The second equation is used here for speed optimization.
           */
          if( today > startIdx ) {
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
          } else {
             /* Skip the unstable period. Do the processing
              * but do not write it in the output.
              */
             while( today < startIdx ) {
                posSumMF -= mflow_positive[mflow_Idx];
                negSumMF -= mflow_negative[mflow_Idx];
                tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                tempValue1 *= inVolume[today++];
                if( tempValue2 < 0 ) {
                   mflow_negative[mflow_Idx] = tempValue1;
                   negSumMF += tempValue1;
                   mflow_positive[mflow_Idx] = 0.0;
                } else if( tempValue2 > 0 ) {
                   mflow_positive[mflow_Idx] = tempValue1;
                   posSumMF += tempValue1;
                   mflow_negative[mflow_Idx] = 0.0;
                } else {
                   mflow_positive[mflow_Idx] = 0.0;
                   mflow_negative[mflow_Idx] = 0.0;
                }
                mflow_Idx++;
                if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
             }
          }
          /* Unstable period skipped... now continue
           * processing if needed.
           */
          while( today <= endIdx ) {
             posSumMF -= mflow_positive[mflow_Idx];
             negSumMF -= mflow_negative[mflow_Idx];
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mfiUnguarded( int startIdx,
                                    int endIdx,
                                    double inHigh[],
                                    double inLow[],
                                    double inClose[],
                                    double inVolume[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double posSumMF = 0;
          double negSumMF = 0;
          double prevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          int i = 0;
          int today = 0;
          double[] mflow_positive;
          double[] mflow_negative;
          int mflow_Idx = 0;
          int maxIdx_mflow = (50)-1;
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          mflow_positive = new double[optInTimePeriod];
          mflow_negative = new double[optInTimePeriod];
          maxIdx_mflow = (optInTimePeriod)-1;
          mflow_Idx = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Mfi.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx - lookbackTotal;
          prevValue = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
          posSumMF = 0.0;
          negSumMF = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          if( today > startIdx ) {
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
          } else {
             while( today < startIdx ) {
                posSumMF -= mflow_positive[mflow_Idx];
                negSumMF -= mflow_negative[mflow_Idx];
                tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                tempValue1 *= inVolume[today++];
                if( tempValue2 < 0 ) {
                   mflow_negative[mflow_Idx] = tempValue1;
                   negSumMF += tempValue1;
                   mflow_positive[mflow_Idx] = 0.0;
                } else if( tempValue2 > 0 ) {
                   mflow_positive[mflow_Idx] = tempValue1;
                   posSumMF += tempValue1;
                   mflow_negative[mflow_Idx] = 0.0;
                } else {
                   mflow_positive[mflow_Idx] = 0.0;
                   mflow_negative[mflow_Idx] = 0.0;
                }
                mflow_Idx++;
                if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
             }
          }
          while( today <= endIdx ) {
             posSumMF -= mflow_positive[mflow_Idx];
             negSumMF -= mflow_negative[mflow_Idx];
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mfi( int startIdx,
                           int endIdx,
                           float inHigh[],
                           float inLow[],
                           float inClose[],
                           float inVolume[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double posSumMF = 0;
          double negSumMF = 0;
          double prevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          int i = 0;
          int today = 0;
          double[] mflow_positive;
          double[] mflow_negative;
          int mflow_Idx = 0;
          int maxIdx_mflow = (50)-1;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          mflow_positive = new double[optInTimePeriod];
          mflow_negative = new double[optInTimePeriod];
          maxIdx_mflow = (optInTimePeriod)-1;
          mflow_Idx = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Mfi.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx - lookbackTotal;
          prevValue = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
          posSumMF = 0.0;
          negSumMF = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          if( today > startIdx ) {
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
          } else {
             while( today < startIdx ) {
                posSumMF -= mflow_positive[mflow_Idx];
                negSumMF -= mflow_negative[mflow_Idx];
                tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                tempValue1 *= inVolume[today++];
                if( tempValue2 < 0 ) {
                   mflow_negative[mflow_Idx] = tempValue1;
                   negSumMF += tempValue1;
                   mflow_positive[mflow_Idx] = 0.0;
                } else if( tempValue2 > 0 ) {
                   mflow_positive[mflow_Idx] = tempValue1;
                   posSumMF += tempValue1;
                   mflow_negative[mflow_Idx] = 0.0;
                } else {
                   mflow_positive[mflow_Idx] = 0.0;
                   mflow_negative[mflow_Idx] = 0.0;
                }
                mflow_Idx++;
                if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
             }
          }
          while( today <= endIdx ) {
             posSumMF -= mflow_positive[mflow_Idx];
             negSumMF -= mflow_negative[mflow_Idx];
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode mfiUnguarded( int startIdx,
                                    int endIdx,
                                    float inHigh[],
                                    float inLow[],
                                    float inClose[],
                                    float inVolume[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double posSumMF = 0;
          double negSumMF = 0;
          double prevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          int i = 0;
          int today = 0;
          double[] mflow_positive;
          double[] mflow_negative;
          int mflow_Idx = 0;
          int maxIdx_mflow = (50)-1;
          if( optInTimePeriod < 1 ) return RetCode.AllocErr;
          mflow_positive = new double[optInTimePeriod];
          mflow_negative = new double[optInTimePeriod];
          maxIdx_mflow = (optInTimePeriod)-1;
          mflow_Idx = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.Mfi.ordinal()];
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx - lookbackTotal;
          prevValue = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
          posSumMF = 0.0;
          negSumMF = 0.0;
          today += 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          if( today > startIdx ) {
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
          } else {
             while( today < startIdx ) {
                posSumMF -= mflow_positive[mflow_Idx];
                negSumMF -= mflow_negative[mflow_Idx];
                tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                tempValue1 *= inVolume[today++];
                if( tempValue2 < 0 ) {
                   mflow_negative[mflow_Idx] = tempValue1;
                   negSumMF += tempValue1;
                   mflow_positive[mflow_Idx] = 0.0;
                } else if( tempValue2 > 0 ) {
                   mflow_positive[mflow_Idx] = tempValue1;
                   posSumMF += tempValue1;
                   mflow_negative[mflow_Idx] = 0.0;
                } else {
                   mflow_positive[mflow_Idx] = 0.0;
                   mflow_negative[mflow_Idx] = 0.0;
                }
                mflow_Idx++;
                if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
             }
          }
          while( today <= endIdx ) {
             posSumMF -= mflow_positive[mflow_Idx];
             negSumMF -= mflow_negative[mflow_Idx];
             tempValue1 = (inHigh[today] + inLow[today] + inClose[today]) / 3.0;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             tempValue1 *= inVolume[today++];
             if( tempValue2 < 0 ) {
                mflow_negative[mflow_Idx] = tempValue1;
                negSumMF += tempValue1;
                mflow_positive[mflow_Idx] = 0.0;
             } else if( tempValue2 > 0 ) {
                mflow_positive[mflow_Idx] = tempValue1;
                posSumMF += tempValue1;
                mflow_negative[mflow_Idx] = 0.0;
             } else {
                mflow_positive[mflow_Idx] = 0.0;
                mflow_negative[mflow_Idx] = 0.0;
             }
             tempValue1 = posSumMF + negSumMF;
             if( tempValue1 < 1.0 ) {
                outReal[outIdx++] = 0.0;
             } else {
                outReal[outIdx++] = 100.0 * (posSumMF / tempValue1);
             }
             mflow_Idx++;
             if( mflow_Idx > maxIdx_mflow ) { mflow_Idx = 0; }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  CC       Claude Code (AI assistant)
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  010802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  070226 MF,CC  Speed optimization: cache the highest/lowest index
     *                instead of rescanning the window on every bar (same
     *                approach as MIN/MAX/MINMAX).
     */

       public int midPointLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode midPoint( int startIdx,
                                int endIdx,
                                double inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Find the highest and lowest value of a timeserie
           * over the period.
           *      MIDPOINT = (Highest Value + Lowest Value)/2
           *
           * See MIDPRICE if the input is a price bar with a
           * high and low timeserie.
           */
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           *
           * The highest/lowest of the window is cached with its
           * index; a rescan of the window is needed only when the
           * cached extremum drops out of the window (amortized O(1)
           * per bar instead of O(period)).
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outReal[outIdx++] = (highest + lowest) / 2.0;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPointUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outReal[outIdx++] = (highest + lowest) / 2.0;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPoint( int startIdx,
                                int endIdx,
                                float inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outReal[outIdx++] = (highest + lowest) / 2.0;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPointUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outReal[outIdx++] = (highest + lowest) / 2.0;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  CC       Claude Code (AI assistant)
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  010802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  070226 MF,CC  Speed optimization: for periods above 20, cache the
     *                highest/lowest index instead of rescanning the window
     *                on every bar (same approach as MIN/MAX/WILLR). Smaller
     *                periods keep the simple scan, which auto-vectorizes
     *                and is faster there. Both paths produce identical
     *                output.
     */

       public int midPriceLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode midPrice( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* MIDPRICE = (Highest High + Lowest Low)/2
           *
           * This function is equivalent to MEDPRICE when the
           * period is 1.
           */
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           *
           * Two equivalent algorithms, picked by period. Their outputs are
           * bit-identical; only the scan strategy differs:
           *
           * - Small periods (<= 20): rescan the whole window on every bar.
           *   The two independent comparison chains auto-vectorize on modern
           *   compilers, which beats any per-bar bookkeeping while the window
           *   is short. The threshold sits near the measured crossover
           *   (~period 19-20 with gcc/clang -O3 on x86-64).
           *
           * - Larger periods: cache the highest high/lowest low with its
           *   index; a rescan of the window is needed only when the cached
           *   extremum drops out of the window (amortized O(1) per bar
           *   instead of O(period)).
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          if( optInTimePeriod <= 20 ) {
             while( today <= endIdx ) {
                lowest = inLow[trailingIdx];
                highest = inHigh[trailingIdx];
                trailingIdx += 1;
                for( i = trailingIdx; i <= today; i += 1 ) {
                   tmpLow = inLow[i];
                   if( tmpLow < lowest ) {
                      lowest = tmpLow;
                   }
                   tmpHigh = inHigh[i];
                   if( tmpHigh > highest ) {
                      highest = tmpHigh;
                   }
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                today += 1;
             }
          } else {
             highestIdx = 0 - 1;
             highest = 0.0;
             lowestIdx = 0 - 1;
             lowest = 0.0;
             while( today <= endIdx ) {
                tmpHigh = inHigh[today];
                tmpLow = inLow[today];
                if( highestIdx < trailingIdx ) {
                   highestIdx = trailingIdx;
                   highest = inHigh[highestIdx];
                   i = highestIdx;
                   while( ++i <= today ) {
                      tmpHigh = inHigh[i];
                      if( tmpHigh > highest ) {
                         highestIdx = i;
                         highest = tmpHigh;
                      }
                   }
                } else if( tmpHigh >= highest ) {
                   highestIdx = today;
                   highest = tmpHigh;
                }
                if( lowestIdx < trailingIdx ) {
                   lowestIdx = trailingIdx;
                   lowest = inLow[lowestIdx];
                   i = lowestIdx;
                   while( ++i <= today ) {
                      tmpLow = inLow[i];
                      if( tmpLow < lowest ) {
                         lowestIdx = i;
                         lowest = tmpLow;
                      }
                   }
                } else if( tmpLow <= lowest ) {
                   lowestIdx = today;
                   lowest = tmpLow;
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                trailingIdx += 1;
                today += 1;
             }
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPriceUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          if( optInTimePeriod <= 20 ) {
             while( today <= endIdx ) {
                lowest = inLow[trailingIdx];
                highest = inHigh[trailingIdx];
                trailingIdx += 1;
                for( i = trailingIdx; i <= today; i += 1 ) {
                   tmpLow = inLow[i];
                   if( tmpLow < lowest ) {
                      lowest = tmpLow;
                   }
                   tmpHigh = inHigh[i];
                   if( tmpHigh > highest ) {
                      highest = tmpHigh;
                   }
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                today += 1;
             }
          } else {
             highestIdx = 0 - 1;
             highest = 0.0;
             lowestIdx = 0 - 1;
             lowest = 0.0;
             while( today <= endIdx ) {
                tmpHigh = inHigh[today];
                tmpLow = inLow[today];
                if( highestIdx < trailingIdx ) {
                   highestIdx = trailingIdx;
                   highest = inHigh[highestIdx];
                   i = highestIdx;
                   while( ++i <= today ) {
                      tmpHigh = inHigh[i];
                      if( tmpHigh > highest ) {
                         highestIdx = i;
                         highest = tmpHigh;
                      }
                   }
                } else if( tmpHigh >= highest ) {
                   highestIdx = today;
                   highest = tmpHigh;
                }
                if( lowestIdx < trailingIdx ) {
                   lowestIdx = trailingIdx;
                   lowest = inLow[lowestIdx];
                   i = lowestIdx;
                   while( ++i <= today ) {
                      tmpLow = inLow[i];
                      if( tmpLow < lowest ) {
                         lowestIdx = i;
                         lowest = tmpLow;
                      }
                   }
                } else if( tmpLow <= lowest ) {
                   lowestIdx = today;
                   lowest = tmpLow;
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                trailingIdx += 1;
                today += 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPrice( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          if( optInTimePeriod <= 20 ) {
             while( today <= endIdx ) {
                lowest = inLow[trailingIdx];
                highest = inHigh[trailingIdx];
                trailingIdx += 1;
                for( i = trailingIdx; i <= today; i += 1 ) {
                   tmpLow = inLow[i];
                   if( tmpLow < lowest ) {
                      lowest = tmpLow;
                   }
                   tmpHigh = inHigh[i];
                   if( tmpHigh > highest ) {
                      highest = tmpHigh;
                   }
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                today += 1;
             }
          } else {
             highestIdx = 0 - 1;
             highest = 0.0;
             lowestIdx = 0 - 1;
             lowest = 0.0;
             while( today <= endIdx ) {
                tmpHigh = inHigh[today];
                tmpLow = inLow[today];
                if( highestIdx < trailingIdx ) {
                   highestIdx = trailingIdx;
                   highest = inHigh[highestIdx];
                   i = highestIdx;
                   while( ++i <= today ) {
                      tmpHigh = inHigh[i];
                      if( tmpHigh > highest ) {
                         highestIdx = i;
                         highest = tmpHigh;
                      }
                   }
                } else if( tmpHigh >= highest ) {
                   highestIdx = today;
                   highest = tmpHigh;
                }
                if( lowestIdx < trailingIdx ) {
                   lowestIdx = trailingIdx;
                   lowest = inLow[lowestIdx];
                   i = lowestIdx;
                   while( ++i <= today ) {
                      tmpLow = inLow[i];
                      if( tmpLow < lowest ) {
                         lowestIdx = i;
                         lowest = tmpLow;
                      }
                   }
                } else if( tmpLow <= lowest ) {
                   lowestIdx = today;
                   lowest = tmpLow;
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                trailingIdx += 1;
                today += 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode midPriceUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmpLow = 0;
          double tmpHigh = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          if( optInTimePeriod <= 20 ) {
             while( today <= endIdx ) {
                lowest = inLow[trailingIdx];
                highest = inHigh[trailingIdx];
                trailingIdx += 1;
                for( i = trailingIdx; i <= today; i += 1 ) {
                   tmpLow = inLow[i];
                   if( tmpLow < lowest ) {
                      lowest = tmpLow;
                   }
                   tmpHigh = inHigh[i];
                   if( tmpHigh > highest ) {
                      highest = tmpHigh;
                   }
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                today += 1;
             }
          } else {
             highestIdx = 0 - 1;
             highest = 0.0;
             lowestIdx = 0 - 1;
             lowest = 0.0;
             while( today <= endIdx ) {
                tmpHigh = inHigh[today];
                tmpLow = inLow[today];
                if( highestIdx < trailingIdx ) {
                   highestIdx = trailingIdx;
                   highest = inHigh[highestIdx];
                   i = highestIdx;
                   while( ++i <= today ) {
                      tmpHigh = inHigh[i];
                      if( tmpHigh > highest ) {
                         highestIdx = i;
                         highest = tmpHigh;
                      }
                   }
                } else if( tmpHigh >= highest ) {
                   highestIdx = today;
                   highest = tmpHigh;
                }
                if( lowestIdx < trailingIdx ) {
                   lowestIdx = trailingIdx;
                   lowest = inLow[lowestIdx];
                   i = lowestIdx;
                   while( ++i <= today ) {
                      tmpLow = inLow[i];
                      if( tmpLow < lowest ) {
                         lowestIdx = i;
                         lowest = tmpLow;
                      }
                   }
                } else if( tmpLow <= lowest ) {
                   lowestIdx = today;
                   lowest = tmpLow;
                }
                outReal[outIdx++] = (highest + lowest) / 2.0;
                trailingIdx += 1;
                today += 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JV       Jesus Viver <324122@cienz.unizar.es>
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  101902 JV   Speed optimization of the algorithm
     *  102202 MF   Speed optimize a bit further
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int minLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode min( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outReal[outIdx++] = lowest;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outReal[outIdx++] = lowest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode min( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outReal[outIdx++] = lowest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outReal[outIdx++] = lowest;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120806 AC   Creation (equal to MIN but outputs index)
     */

       public int minIndexLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode minIndex( int startIdx,
                                int endIdx,
                                double inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                int outInteger[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outInteger[outIdx++] = lowestIdx;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minIndexUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outInteger[outIdx++] = lowestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minIndex( int startIdx,
                                int endIdx,
                                float inReal[],
                                int optInTimePeriod,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                int outInteger[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outInteger[outIdx++] = lowestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minIndexUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         int optInTimePeriod,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         int outInteger[] )
       {
          double lowest = 0;
          double tmp = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmp = inReal[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inReal[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
             }
             outInteger[outIdx++] = lowestIdx;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120906 AC   Creation
     */

       public int minMaxLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode minMax( int startIdx,
                              int endIdx,
                              double inReal[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outMin[],
                              double outMax[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMax[outIdx] = highest;
             outMin[outIdx] = lowest;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMaxUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outMin[],
                                       double outMax[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMax[outIdx] = highest;
             outMin[outIdx] = lowest;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMax( int startIdx,
                              int endIdx,
                              float inReal[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outMin[],
                              double outMax[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMax[outIdx] = highest;
             outMin[outIdx] = lowest;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMaxUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outMin[],
                                       double outMax[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMax[outIdx] = highest;
             outMin[outIdx] = lowest;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  AC       Angelo Ciceri
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120906 AC   Creation (equal to MINMAX but outputs index)
     */

       public int minMaxIndexLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode minMaxIndex( int startIdx,
                                   int endIdx,
                                   double inReal[],
                                   int optInTimePeriod,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outMinIdx[],
                                   int outMaxIdx[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMaxIdx[outIdx] = highestIdx;
             outMinIdx[outIdx] = lowestIdx;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMaxIndexUnguarded( int startIdx,
                                            int endIdx,
                                            double inReal[],
                                            int optInTimePeriod,
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outMinIdx[],
                                            int outMaxIdx[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMaxIdx[outIdx] = highestIdx;
             outMinIdx[outIdx] = lowestIdx;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMaxIndex( int startIdx,
                                   int endIdx,
                                   float inReal[],
                                   int optInTimePeriod,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   int outMinIdx[],
                                   int outMaxIdx[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMaxIdx[outIdx] = highestIdx;
             outMinIdx[outIdx] = lowestIdx;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minMaxIndexUnguarded( int startIdx,
                                            int endIdx,
                                            float inReal[],
                                            int optInTimePeriod,
                                            MInteger outBegIdx,
                                            MInteger outNBElement,
                                            int outMinIdx[],
                                            int outMaxIdx[] )
       {
          double highest = 0;
          double lowest = 0;
          double tmpHigh = 0;
          double tmpLow = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int highestIdx = 0;
          int lowestIdx = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          highest = 0.0;
          lowestIdx = 0 - 1;
          lowest = 0.0;
          while( today <= endIdx ) {
             tmpHigh = inReal[today];
             tmpLow = tmpHigh;
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inReal[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmpHigh = inReal[i];
                   if( tmpHigh > highest ) {
                      highestIdx = i;
                      highest = tmpHigh;
                   }
                }
             } else if( tmpHigh >= highest ) {
                highestIdx = today;
                highest = tmpHigh;
             }
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inReal[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmpLow = inReal[i];
                   if( tmpLow < lowest ) {
                      lowestIdx = i;
                      lowest = tmpLow;
                   }
                }
             } else if( tmpLow <= lowest ) {
                lowestIdx = today;
                lowest = tmpLow;
             }
             outMaxIdx[outIdx] = highestIdx;
             outMinIdx[outIdx] = lowestIdx;
             outIdx += 1;
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel
     *  MIF      Mirek Fontan (mira@fontan.cz)
     *  CF       Christo Fogelberg
     *
     * Change history:
     *
     *  MMDDYY BY    Description
     *  -------------------------------------------------------------------
     *  010802 MF    Template creation.
     *  052603 MF    Adapt code to compile with .NET Managed C++
     *  082303 MF    Fix #792298. Remove rounding. Bug reported by AM.
     *  062704 MF    Fix #965557. Div by zero bug reported by MIF.
     *  122204 MF,CF Fix #1090231. Issues when period is 1.
     */

       public int minusDILookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDI.ordinal()] ;
          } else {
             return 1 ;
          }

       }
       public RetCode minusDI( int startIdx,
                               int endIdx,
                               double inHigh[],
                               double inLow[],
                               double inClose[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM1=0
           * B|  | -DM1=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a -DM14, sum the -DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous -DM14
           *  Today's -DM14 = Previous -DM14 -  -------------- + Today's -DM1
           *                                         14
           *
           * Calculation of a -DI14 is as follow:
           *
           *               -DM14
           *     -DI14 =  --------
           *                TR14
           *
           * Calculation of the TR14 is:
           *
           *                                   Previous TR14
           *    Today's TR14 = Previous TR14 - -------------- + Today's TR1
           *                                         14
           *
           *    The first TR14 is the summation of the first 14 TR1. See the
           *    TA_TRANGE function on how to calculate the true range.
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          /* Original implementation from Wilder's book was doing some integer
           * rounding in its calculations.
           *
           * This was understandable in the context that at the time the book
           * was written, most user were doing the calculation by hand.
           *
           * For a computer, rounding is unnecessary (and even problematic when inputs
           * are close to 1).
           *
           * TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
           * you can comment out the following #undef/#define and rebuild the library.
           */
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do the following:
              * for each price bar.
              *          -DM1
              *   -DI1 = ----
              *           TR1
              */
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                /* Plus Delta */
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                /* Minus Delta */
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   /* Case 2 and 4: +DM=0,-DM=diffM */
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffM / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Process the initial DM and TR */
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          /* Process subsequent DI */
          /* Skip the unstable period. Note that this loop must be executed
           * at least ONCE to calculate the first DI.
           */
          i = this.unstablePeriod[FuncUnstId.MinusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             /* Calculate the prevMinusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                /* Case 1,3,5 and 7 */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             /* Calculate the prevTR */
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          /* Now start to write the output in
           * the caller provided outReal.
           */
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevMinusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             /* Calculate the prevMinusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                /* Case 1,3,5 and 7 */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             /* Calculate the prevTR */
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             /* Calculate the DI. The value is rounded (see Wilder book). */
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevMinusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDIUnguarded( int startIdx,
                                        int endIdx,
                                        double inHigh[],
                                        double inLow[],
                                        double inClose[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffM / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.MinusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevMinusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevMinusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDI( int startIdx,
                               int endIdx,
                               float inHigh[],
                               float inLow[],
                               float inClose[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffM / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.MinusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevMinusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevMinusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDIUnguarded( int startIdx,
                                        int endIdx,
                                        float inHigh[],
                                        float inLow[],
                                        float inClose[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevMinusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffM / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevMinusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.MinusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevMinusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevMinusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int minusDMLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDM.ordinal()] - 1 ;
          } else {
             return 1 ;
          }

       }
       public RetCode minusDM( int startIdx,
                               int endIdx,
                               double inHigh[],
                               double inLow[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevMinusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM=0
           * B|  | -DM=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a -DM14, sum the -DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous -DM14
           *  Today's -DM14 = Previous -DM14 -  -------------- + Today's -DM1
           *                                         14
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do a simple DM1
              * for each price bar.
              */
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                /* Plus Delta */
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                /* Minus Delta */
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   /* Case 2 and 4: +DM=0,-DM=diffM */
                   outReal[outIdx++] = diffM;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Process the initial DM */
          outBegIdx.value = startIdx;
          prevMinusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM += diffM;
             }
          }
          /* Process subsequent DM */
          /* Skip the unstable period. */
          i = this.unstablePeriod[FuncUnstId.MinusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                /* Case 1,3,5 and 7 */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
          }
          /* Now start to write the output in
           * the caller provided outReal.
           */
          outReal[0] = prevMinusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                /* Case 2 and 4: +DM=0,-DM=diffM */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                /* Case 1,3,5 and 7 */
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevMinusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDMUnguarded( int startIdx,
                                        int endIdx,
                                        double inHigh[],
                                        double inLow[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevMinusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   outReal[outIdx++] = diffM;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevMinusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
          }
          i = this.unstablePeriod[FuncUnstId.MinusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevMinusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevMinusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDM( int startIdx,
                               int endIdx,
                               float inHigh[],
                               float inLow[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevMinusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   outReal[outIdx++] = diffM;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevMinusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
          }
          i = this.unstablePeriod[FuncUnstId.MinusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevMinusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevMinusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode minusDMUnguarded( int startIdx,
                                        int endIdx,
                                        float inHigh[],
                                        float inLow[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevMinusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.MinusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffM > 0 && diffP < diffM ) {
                   outReal[outIdx++] = diffM;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevMinusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM += diffM;
             }
          }
          i = this.unstablePeriod[FuncUnstId.MinusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevMinusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffM > 0 && diffP < diffM ) {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod + diffM;
             } else {
                prevMinusDM = prevMinusDM - prevMinusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevMinusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int momLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode mom( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The interpretation of the rate of change varies widely depending
           * which software and/or books you are refering to.
           *
           * The following is the table of Rate-Of-Change implemented in TA-LIB:
           *       MOM     = (price - prevPrice)         [Momentum]
           *       ROC     = ((price/prevPrice)-1)*100   [Rate of change]
           *       ROCP    = (price-prevPrice)/prevPrice [Rate of change Percentage]
           *       ROCR    = (price/prevPrice)           [Rate of change ratio]
           *       ROCR100 = (price/prevPrice)*100       [Rate of change ratio 100 Scale]
           *
           * Here are the equivalent function in other software:
           *       TA-Lib  |   Tradestation   |    Metastock
           *       =================================================
           *       MOM     |   Momentum       |    ROC (Point)
           *       ROC     |   ROC            |    ROC (Percent)
           *       ROCP    |   PercentChange  |    -
           *       ROCR    |   -              |    -
           *       ROCR100 |   -              |    MO
           *
           * The MOM function is the only one who is not normalized, and thus
           * should be avoided for comparing different time serie of prices.
           *
           * ROC and ROCP are centered at zero and can have positive and negative
           * value. Here are some equivalence:
           *    ROC = ROCP/100
           *        = ((price-prevPrice)/prevPrice)/100
           *        = ((price/prevPrice)-1)*100
           *
           * ROCR and ROCR100 are ratio respectively centered at 1 and 100 and are
           * always positive values.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate Momentum:
           *    Just substract the value from 'period' ago from
           *    current value.
           */
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             outReal[outIdx++] = inReal[inIdx++] - inReal[trailingIdx++];
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode momUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             outReal[outIdx++] = inReal[inIdx++] - inReal[trailingIdx++];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode mom( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             outReal[outIdx++] = inReal[inIdx++] - inReal[trailingIdx++];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode momUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             outReal[outIdx++] = inReal[inIdx++] - inReal[trailingIdx++];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int multLookback( )
       {
          return 0 ;

       }
       public RetCode mult( int startIdx,
                            int endIdx,
                            double inReal0[],
                            double inReal1[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          i = startIdx;
          while( i <= endIdx ) {
             outReal[outIdx] = (double)(inReal0[i] * inReal1[i]);
             outIdx += 1;
             i += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode multUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal0[],
                                     double inReal1[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          i = startIdx;
          while( i <= endIdx ) {
             outReal[outIdx] = (double)(inReal0[i] * inReal1[i]);
             outIdx += 1;
             i += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode mult( int startIdx,
                            int endIdx,
                            float inReal0[],
                            float inReal1[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          i = startIdx;
          while( i <= endIdx ) {
             outReal[outIdx] = (double)(inReal0[i] * inReal1[i]);
             outIdx += 1;
             i += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode multUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal0[],
                                     float inReal1[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          i = startIdx;
          while( i <= endIdx ) {
             outReal[outIdx] = (double)(inReal0[i] * inReal1[i]);
             outIdx += 1;
             i += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  060306 MF     Initial Version
     */

       public int natrLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          /* The ATR lookback is the sum of:
           *    1 + (optInTimePeriod - 1)
           *
           * Where 1 is for the True Range, and
           * (optInTimePeriod-1) is for the simple
           * moving average.
           */
          return optInTimePeriod + this.unstablePeriod[FuncUnstId.Natr.ordinal()] ;

       }
       public RetCode natr( int startIdx,
                            int endIdx,
                            double inHigh[],
                            double inLow[],
                            double inClose[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double tempValue = 0;
          double[] tempBuffer;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* This function is very similar as ATR, except
           * it is being normalized as follow:
           *
           *    NATR = (ATR(period) / Close) * 100
           *
           *
           * Normalization make the ATR function more relevant
           * in the folllowing scenario:
           *    - Long term analysis where the price changes drastically.
           *    - Cross-market or cross-security ATR comparison.
           *
           * More Info:
           *      Technical Analysis of Stock & Commodities (TASC)
           *      May 2006 by John Forman
           */
          /* Average True Range is the greatest of the following:
           *
           *  val1 = distance from today's high to today's low.
           *  val2 = distance from yesterday's close to today's high.
           *  val3 = distance from yesterday's close to today's low.
           *
           * These value are averaged for the specified period using
           * Wilder method. This method have an unstable period comparable
           * to an Exponential Moving Average (EMA).
           */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = natrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do a TRANGE. */
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          /* Allocate an intermediate buffer for TRANGE. */
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          /* Do TRANGE in the intermediate buffer. */
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          /* First value of the ATR is a simple Average of
           * the TRANGE output for the specified period.
           */
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          /* Subsequent value are smoothed using the
           * previous ATR value (Wilder's approach).
           *  1) Multiply the previous ATR by 'period-1'.
           *  2) Add today TR value.
           *  3) Divide by 'period'.
           */
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Natr.ordinal()];
          /* Skip the unstable period. */
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          /* Now start to write the final ATR in the caller
           * provided outReal.
           */
          outIdx = 1;
          tempValue = inClose[today];
          if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
             outReal[0] = prevATR[0] / tempValue * 100.0;
          } else {
             outReal[0] = 0.0;
          }
          /* Now do the number of requested ATR. */
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             tempValue = inClose[today];
             if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
                outReal[outIdx] = prevATR[0] / tempValue * 100.0;
             } else {
                outReal[0] = 0.0;
             }
             outIdx += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode natrUnguarded( int startIdx,
                                     int endIdx,
                                     double inHigh[],
                                     double inLow[],
                                     double inClose[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double tempValue = 0;
          double[] tempBuffer;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = natrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Natr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          tempValue = inClose[today];
          if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
             outReal[0] = prevATR[0] / tempValue * 100.0;
          } else {
             outReal[0] = 0.0;
          }
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             tempValue = inClose[today];
             if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
                outReal[outIdx] = prevATR[0] / tempValue * 100.0;
             } else {
                outReal[0] = 0.0;
             }
             outIdx += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode natr( int startIdx,
                            int endIdx,
                            float inHigh[],
                            float inLow[],
                            float inClose[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double tempValue = 0;
          double[] tempBuffer;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = natrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Natr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          tempValue = inClose[today];
          if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
             outReal[0] = prevATR[0] / tempValue * 100.0;
          } else {
             outReal[0] = 0.0;
          }
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             tempValue = inClose[today];
             if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
                outReal[outIdx] = prevATR[0] / tempValue * 100.0;
             } else {
                outReal[0] = 0.0;
             }
             outIdx += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
       public RetCode natrUnguarded( int startIdx,
                                     int endIdx,
                                     float inHigh[],
                                     float inLow[],
                                     float inClose[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          RetCode retCode;
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int nbATR = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          double[] prevATR = new double[1];
          double tempValue = 0;
          double[] tempBuffer;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = natrLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod <= 1 ) {
             return trueRangeUnguarded(startIdx, endIdx, inHigh, inLow, inClose, outBegIdx, outNBElement, outReal) ;
          }
          tempBuffer = new double[(int)((lookbackTotal + (endIdx - startIdx) + 1) * 1)];
          retCode = trueRangeUnguarded(startIdx - lookbackTotal + 1, endIdx, inHigh, inLow, inClose, outBegIdx1, outNbElement1, tempBuffer);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          retCode = smaUnguarded(optInTimePeriod - 1, optInTimePeriod - 1, tempBuffer, optInTimePeriod, outBegIdx1, outNbElement1, prevATR);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          today = optInTimePeriod;
          outIdx = this.unstablePeriod[FuncUnstId.Natr.ordinal()];
          while( outIdx != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             outIdx -= 1;
          }
          outIdx = 1;
          tempValue = inClose[today];
          if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
             outReal[0] = prevATR[0] / tempValue * 100.0;
          } else {
             outReal[0] = 0.0;
          }
          nbATR = endIdx - startIdx + 1;
          while( --nbATR != 0 ) {
             prevATR[0] *= optInTimePeriod - 1;
             prevATR[0] += tempBuffer[today++];
             prevATR[0] /= optInTimePeriod;
             tempValue = inClose[today];
             if( !((-0.00000000000001 < tempValue) && (tempValue < 0.00000000000001)) ) {
                outReal[outIdx] = prevATR[0] / tempValue * 100.0;
             } else {
                outReal[0] = 0.0;
             }
             outIdx += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return retCode ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AC       Angelo Ciceri
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  110206 AC   Change volume and open interest to double
     */

       public int obvLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode obv( int startIdx,
                           int endIdx,
                           double inReal[],
                           double inVolume[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int i = 0;
          int outIdx = 0;
          double prevReal = 0;
          double tempReal = 0;
          double prevOBV = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          prevOBV = inVolume[startIdx];
          prevReal = inReal[startIdx];
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inReal[i];
             if( tempReal > prevReal ) {
                prevOBV += inVolume[i];
             } else if( tempReal < prevReal ) {
                prevOBV -= inVolume[i];
             }
             outReal[outIdx++] = prevOBV;
             prevReal = tempReal;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode obvUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    double inVolume[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int i = 0;
          int outIdx = 0;
          double prevReal = 0;
          double tempReal = 0;
          double prevOBV = 0;
          prevOBV = inVolume[startIdx];
          prevReal = inReal[startIdx];
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inReal[i];
             if( tempReal > prevReal ) {
                prevOBV += inVolume[i];
             } else if( tempReal < prevReal ) {
                prevOBV -= inVolume[i];
             }
             outReal[outIdx++] = prevOBV;
             prevReal = tempReal;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode obv( int startIdx,
                           int endIdx,
                           float inReal[],
                           float inVolume[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int i = 0;
          int outIdx = 0;
          double prevReal = 0;
          double tempReal = 0;
          double prevOBV = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          prevOBV = inVolume[startIdx];
          prevReal = inReal[startIdx];
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inReal[i];
             if( tempReal > prevReal ) {
                prevOBV += inVolume[i];
             } else if( tempReal < prevReal ) {
                prevOBV -= inVolume[i];
             }
             outReal[outIdx++] = prevOBV;
             prevReal = tempReal;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode obvUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    float inVolume[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int i = 0;
          int outIdx = 0;
          double prevReal = 0;
          double tempReal = 0;
          double prevOBV = 0;
          prevOBV = inVolume[startIdx];
          prevReal = inReal[startIdx];
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             tempReal = inReal[i];
             if( tempReal > prevReal ) {
                prevOBV += inVolume[i];
             } else if( tempReal < prevReal ) {
                prevOBV -= inVolume[i];
             }
             outReal[outIdx++] = prevOBV;
             prevReal = tempReal;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AM       Adrian Michel
     *  MIF      Mirek Fontan (mira@fontan.cz)
     *  CF       Christo Fogelberg
     *
     * Change history:
     *
     *  MMDDYY BY    Description
     *  -------------------------------------------------------------------
     *  010802 MF    Template creation.
     *  052603 MF    Adapt code to compile with .NET Managed C++
     *  082303 MF    Fix #792298. Remove rounding. Bug reported by AM.
     *  062704 MF    Fix #965557. Div by zero bug reported by MIF.
     *  122204 MF,CF Fix #1090231. Issues when period is 1.
     */

       public int plusDILookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDI.ordinal()] ;
          } else {
             return 1 ;
          }

       }
       public RetCode plusDI( int startIdx,
                              int endIdx,
                              double inHigh[],
                              double inLow[],
                              double inClose[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM1=0
           * B|  | -DM1=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a -DM14, sum the -DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous +DM14
           *  Today's +DM14 = Previous +DM14 -  -------------- + Today's +DM1
           *                                         14
           *
           * Calculation of a +DI14 is as follow:
           *
           *               +DM14
           *     +DI14 =  --------
           *                TR14
           *
           * Calculation of the TR14 is:
           *
           *                                   Previous TR14
           *    Today's TR14 = Previous TR14 - -------------- + Today's TR1
           *                                         14
           *
           *    The first TR14 is the summation of the first 14 TR1. See the
           *    TA_TRANGE function on how to calculate the true range.
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          /* Original implementation from Wilder's book was doing some integer
           * rounding in its calculations.
           *
           * This was understandable in the context that at the time the book
           * was written, most user were doing the calculation by hand.
           *
           * For a computer, rounding is unnecessary (and even problematic when inputs
           * are close to 1).
           *
           * TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
           * you can comment out the following #undef/#define and rebuild the library.
           */
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do the following:
              * for each price bar.
              *          +DM1
              *   +DI1 = ----
              *           TR1
              */
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                /* Plus Delta */
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                /* Minus Delta */
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   /* Case 1 and 3: +DM=diffP,-DM=0 */
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffP / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Process the initial DM and TR */
          today = startIdx;
          outBegIdx.value = today;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          /* Process subsequent DI */
          /* Skip the unstable period. Note that this loop must be executed
           * at least ONCE to calculate the first DI.
           */
          i = this.unstablePeriod[FuncUnstId.PlusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             /* Calculate the prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                /* Case 2,4,5 and 7 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             /* Calculate the prevTR */
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          /* Now start to write the output in
           * the caller provided outReal.
           */
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevPlusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             /* Calculate the prevPlusDM */
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                /* Case 2,4,5 and 7 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             /* Calculate the prevTR */
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             /* Calculate the DI. The value is rounded (see Wilder book). */
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevPlusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDIUnguarded( int startIdx,
                                       int endIdx,
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffP / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.PlusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevPlusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevPlusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDI( int startIdx,
                              int endIdx,
                              float inHigh[],
                              float inLow[],
                              float inClose[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffP / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.PlusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevPlusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevPlusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDIUnguarded( int startIdx,
                                       int endIdx,
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double prevClose = 0;
          double prevPlusDM = 0;
          double prevTR = 0;
          double tempReal = 0;
          double tempReal2 = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDI.ordinal()];
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             prevClose = inClose[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   double _true_range_0;
                   double range_0 = prevHigh - prevLow;
                   double tmp_0 = Math.abs(prevHigh - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   tmp_0 = Math.abs(prevLow - prevClose);
                   if( tmp_0 > range_0 ) {
                      range_0 = tmp_0;
                   }
                   _true_range_0 = range_0;
                   tempReal = _true_range_0;
                   if( ((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[outIdx++] = (double)0.0;
                   } else {
                      outReal[outIdx++] = diffP / tempReal;
                   }
                } else {
                   outReal[outIdx++] = (double)0.0;
                }
                prevClose = inClose[today];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          today = startIdx;
          outBegIdx.value = today;
          prevPlusDM = 0.0;
          prevTR = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          prevClose = inClose[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
             double _true_range_1;
             double range_1 = prevHigh - prevLow;
             double tmp_1 = Math.abs(prevHigh - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             tmp_1 = Math.abs(prevLow - prevClose);
             if( tmp_1 > range_1 ) {
                range_1 = tmp_1;
             }
             _true_range_1 = range_1;
             tempReal = _true_range_1;
             prevTR += tempReal;
             prevClose = inClose[today];
          }
          i = this.unstablePeriod[FuncUnstId.PlusDI.ordinal()] + 1;
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_2;
             double range_2 = prevHigh - prevLow;
             double tmp_2 = Math.abs(prevHigh - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             tmp_2 = Math.abs(prevLow - prevClose);
             if( tmp_2 > range_2 ) {
                range_2 = tmp_2;
             }
             _true_range_2 = range_2;
             tempReal = _true_range_2;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
          }
          if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
             outReal[0] = (100.0 * (prevPlusDM / prevTR));
          } else {
             outReal[0] = 0.0;
          }
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             double _true_range_3;
             double range_3 = prevHigh - prevLow;
             double tmp_3 = Math.abs(prevHigh - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             tmp_3 = Math.abs(prevLow - prevClose);
             if( tmp_3 > range_3 ) {
                range_3 = tmp_3;
             }
             _true_range_3 = range_3;
             tempReal = _true_range_3;
             prevTR = prevTR - prevTR / optInTimePeriod + tempReal;
             prevClose = inClose[today];
             if( !((-0.00000000000001 < prevTR) && (prevTR < 0.00000000000001)) ) {
                outReal[outIdx++] = (100.0 * (prevPlusDM / prevTR));
             } else {
                outReal[outIdx++] = 0.0;
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  CF       Christo Fogelberg
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  010802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  122104 MF,CF  Fix#1089506 for when optInTimePeriod is 1.
     */

       public int plusDMLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInTimePeriod > 1 ) {
             return optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDM.ordinal()] - 1 ;
          } else {
             return 1 ;
          }

       }
       public RetCode plusDM( int startIdx,
                              int endIdx,
                              double inHigh[],
                              double inLow[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevPlusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /*
           * The DM1 (one period) is base on the largest part of
           * today's range that is outside of yesterdays range.
           *
           * The following 7 cases explain how the +DM and -DM are
           * calculated on one period:
           *
           * Case 1:                       Case 2:
           *    C|                        A|
           *     |                         | C|
           *     | +DM1 = (C-A)           B|  | +DM1 = 0
           *     | -DM1 = 0                   | -DM1 = (B-D)
           * A|  |                           D|
           *  | D|
           * B|
           *
           * Case 3:                       Case 4:
           *    C|                           C|
           *     |                        A|  |
           *     | +DM1 = (C-A)            |  | +DM1 = 0
           *     | -DM1 = 0               B|  | -DM1 = (B-D)
           * A|  |                            |
           *  |  |                           D|
           * B|  |
           *    D|
           *
           * Case 5:                      Case 6:
           * A|                           A| C|
           *  | C| +DM1 = 0                |  |  +DM1 = 0
           *  |  | -DM1 = 0                |  |  -DM1 = 0
           *  | D|                         |  |
           * B|                           B| D|
           *
           *
           * Case 7:
           *
           *    C|
           * A|  |
           *  |  | +DM=0
           * B|  | -DM=0
           *    D|
           *
           * In case 3 and 4, the rule is that the smallest delta between
           * (C-A) and (B-D) determine which of +DM or -DM is zero.
           *
           * In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
           * zero.
           *
           * The rules remain the same when A=B and C=D (when the highs
           * equal the lows).
           *
           * When calculating the DM over a period > 1, the one-period DM
           * for the desired period are initialy sum. In other word,
           * for a +DM14, sum the +DM1 for the first 14 days (that's
           * 13 values because there is no DM for the first day!)
           * Subsequent DM are calculated using the Wilder's
           * smoothing approach:
           *
           *                                    Previous +DM14
           *  Today's +DM14 = Previous +DM14 -  -------------- + Today's +DM1
           *                                         14
           *
           * Reference:
           *    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
           */
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          /* Adjust startIdx to account for the lookback period. */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Indicate where the next output should be put
           * in the outReal.
           */
          outIdx = 0;
          /* Trap the case where no smoothing is needed. */
          if( optInTimePeriod <= 1 ) {
             /* No smoothing needed. Just do a simple DM1
              * for each price bar.
              */
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                /* Plus Delta */
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                /* Minus Delta */
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   /* Case 1 and 3: +DM=diffP,-DM=0 */
                   outReal[outIdx++] = diffP;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Process the initial DM */
          outBegIdx.value = startIdx;
          prevPlusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM += diffP;
             }
          }
          /* Process subsequent DM */
          /* Skip the unstable period. */
          i = this.unstablePeriod[FuncUnstId.PlusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                /* Case 2,4,5 and 7 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
          }
          /* Now start to write the output in
           * the caller provided outReal.
           */
          outReal[0] = prevPlusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             /* Plus Delta */
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             /* Minus Delta */
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                /* Case 1 and 3: +DM=diffP,-DM=0 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                /* Case 2,4,5 and 7 */
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevPlusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDMUnguarded( int startIdx,
                                       int endIdx,
                                       double inHigh[],
                                       double inLow[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevPlusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   outReal[outIdx++] = diffP;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevPlusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
          }
          i = this.unstablePeriod[FuncUnstId.PlusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevPlusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevPlusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDM( int startIdx,
                              int endIdx,
                              float inHigh[],
                              float inLow[],
                              int optInTimePeriod,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevPlusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   outReal[outIdx++] = diffP;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevPlusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
          }
          i = this.unstablePeriod[FuncUnstId.PlusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevPlusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevPlusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode plusDMUnguarded( int startIdx,
                                       int endIdx,
                                       float inHigh[],
                                       float inLow[],
                                       int optInTimePeriod,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int today = 0;
          int lookbackTotal = 0;
          int outIdx = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double tempReal = 0;
          double prevPlusDM = 0;
          double diffP = 0;
          double diffM = 0;
          int i = 0;
          if( optInTimePeriod > 1 ) {
             lookbackTotal = optInTimePeriod + this.unstablePeriod[FuncUnstId.PlusDM.ordinal()] - 1;
          } else {
             lookbackTotal = 1;
          }
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod <= 1 ) {
             outBegIdx.value = startIdx;
             today = startIdx - 1;
             prevHigh = inHigh[today];
             prevLow = inLow[today];
             while( today < endIdx ) {
                today += 1;
                tempReal = inHigh[today];
                diffP = tempReal - prevHigh;
                prevHigh = tempReal;
                tempReal = inLow[today];
                diffM = prevLow - tempReal;
                prevLow = tempReal;
                if( diffP > 0 && diffP > diffM ) {
                   outReal[outIdx++] = diffP;
                } else {
                   outReal[outIdx++] = 0;
                }
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          prevPlusDM = 0.0;
          today = startIdx - lookbackTotal;
          prevHigh = inHigh[today];
          prevLow = inLow[today];
          i = optInTimePeriod - 1;
          while( i-- > 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM += diffP;
             }
          }
          i = this.unstablePeriod[FuncUnstId.PlusDM.ordinal()];
          while( i-- != 0 ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
          }
          outReal[0] = prevPlusDM;
          outIdx = 1;
          while( today < endIdx ) {
             today += 1;
             tempReal = inHigh[today];
             diffP = tempReal - prevHigh;
             prevHigh = tempReal;
             tempReal = inLow[today];
             diffM = prevLow - tempReal;
             prevLow = tempReal;
             if( diffP > 0 && diffP > diffM ) {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod + diffP;
             } else {
                prevPlusDM = prevPlusDM - prevPlusDM / optInTimePeriod;
             }
             outReal[outIdx++] = prevPlusDM;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AA       Andrew Atkinson
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  020605 AA   Fix #1117666 Lookback bug.
     */

       public int ppoLookback( int optInFastPeriod, int optInSlowPeriod, MAType optInMAType )
       {
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return -1;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return -1;
          }
          /* Lookback is driven by the slowest MA. */
          return movingAverageLookback(Math.max(optInSlowPeriod, optInFastPeriod), optInMAType) ;

       }
       public RetCode ppo( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInFastPeriod,
                           int optInSlowPeriod,
                           MAType optInMAType,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          double tempReal = 0;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Allocate an intermediate buffer. */
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          /* Make sure slow is really slower than
           * the fast period! if not, swap...
           */
          if( optInSlowPeriod < optInFastPeriod ) {
             /* swap */
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          /* Calculate the fast MA into the tempBuffer. */
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             /* Calculate the slow MA into the output. */
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                /* Calculate ((fast MA)-(slow MA))/(slow MA) in the output. */
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   tempReal = outReal[i];
                   if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[i] = (tempBuffer[j] - tempReal) / tempReal * 100.0;
                   } else {
                      outReal[i] = 0.0;
                   }
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode ppoUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInFastPeriod,
                                    int optInSlowPeriod,
                                    MAType optInMAType,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          double tempReal = 0;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   tempReal = outReal[i];
                   if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[i] = (tempBuffer[j] - tempReal) / tempReal * 100.0;
                   } else {
                      outReal[i] = 0.0;
                   }
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode ppo( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInFastPeriod,
                           int optInSlowPeriod,
                           MAType optInMAType,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          double tempReal = 0;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastPeriod == Integer.MIN_VALUE ) {
             optInFastPeriod = 12;
          } else if( optInFastPeriod < 2 || optInFastPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowPeriod == Integer.MIN_VALUE ) {
             optInSlowPeriod = 26;
          } else if( optInSlowPeriod < 2 || optInSlowPeriod > 100000 ) {
             return RetCode.BadParam;
          }
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   tempReal = outReal[i];
                   if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[i] = (tempBuffer[j] - tempReal) / tempReal * 100.0;
                   } else {
                      outReal[i] = 0.0;
                   }
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
       public RetCode ppoUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInFastPeriod,
                                    int optInSlowPeriod,
                                    MAType optInMAType,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double[] tempBuffer;
          RetCode retCode;
          double tempReal = 0;
          int tempInteger = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement2 = new MInteger();
          int i = 0;
          int j = 0;
          tempBuffer = new double[(int)((endIdx - startIdx + 1) * 1)];
          if( optInSlowPeriod < optInFastPeriod ) {
             tempInteger = optInSlowPeriod;
             optInSlowPeriod = optInFastPeriod;
             optInFastPeriod = tempInteger;
          }
          retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInFastPeriod, optInMAType, outBegIdx2, outNbElement2, tempBuffer);
          if( retCode == RetCode.Success ) {
             retCode = movingAverageUnguarded(startIdx, endIdx, inReal, optInSlowPeriod, optInMAType, outBegIdx1, outNbElement1, outReal);
             if( retCode == RetCode.Success ) {
                tempInteger = outBegIdx1.value - outBegIdx2.value;
                for( i = 0, j = tempInteger; i < outNbElement1.value; i += 1, j += 1 ) {
                   tempReal = outReal[i];
                   if( !((-0.00000000000001 < tempReal) && (tempReal < 0.00000000000001)) ) {
                      outReal[i] = (tempBuffer[j] - tempReal) / tempReal * 100.0;
                   } else {
                      outReal[i] = 0.0;
                   }
                }
                outBegIdx.value = outBegIdx1.value;
                outNBElement.value = outNbElement1.value;
             }
          }
          return retCode ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int rocLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode roc( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The interpretation of the rate of change varies widely depending
           * which software and/or books you are refering to.
           *
           * The following is the table of Rate-Of-Change implemented in TA-LIB:
           *       MOM     = (price - prevPrice)         [Momentum]
           *       ROC     = ((price/prevPrice)-1)*100   [Rate of change]
           *       ROCP    = (price-prevPrice)/prevPrice [Rate of change Percentage]
           *       ROCR    = (price/prevPrice)           [Rate of change ratio]
           *       ROCR100 = (price/prevPrice)*100       [Rate of change ratio 100 Scale]
           *
           * Here are the equivalent function in other software:
           *       TA-Lib  |   Tradestation   |    Metastock
           *       =================================================
           *       MOM     |   Momentum       |    ROC (Point)
           *       ROC     |   ROC            |    ROC (Percent)
           *       ROCP    |   PercentChange  |    -
           *       ROCR    |   -              |    -
           *       ROCR100 |   -              |    MO
           *
           * The MOM function is the only one who is not normalized, and thus
           * should be avoided for comparing different time serie of prices.
           *
           * ROC and ROCP are centered at zero and can have positive and negative
           * value. Here are some equivalence:
           *    ROC = ROCP/100
           *        = ((price-prevPrice)/prevPrice)/100
           *        = ((price/prevPrice)-1)*100
           *
           * ROCR and ROCR100 are ratio respectively centered at 1 and 100 and are
           * always positive values.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate Rate of change: ((price / prevPrice)-1)*100 */
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] / tempReal - 1.0) * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] / tempReal - 1.0) * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode roc( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] / tempReal - 1.0) * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] / tempReal - 1.0) * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int rocPLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode rocP( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The interpretation of the rate of change varies widely depending
           * which software and/or books you are refering to.
           *
           * The following is the table of Rate-Of-Change implemented in TA-LIB:
           *       MOM     = (price - prevPrice)         [Momentum]
           *       ROC     = ((price/prevPrice)-1)*100   [Rate of change]
           *       ROCP    = (price-prevPrice)/prevPrice [Rate of change Percentage]
           *       ROCR    = (price/prevPrice)           [Rate of change ratio]
           *       ROCR100 = (price/prevPrice)*100       [Rate of change ratio 100 Scale]
           *
           * Here are the equivalent function in other software:
           *       TA-Lib  |   Tradestation   |    Metastock
           *       =================================================
           *       MOM     |   Momentum       |    ROC (Point)
           *       ROC     |   ROC            |    ROC (Percent)
           *       ROCP    |   PercentChange  |    -
           *       ROCR    |   -              |    -
           *       ROCR100 |   -              |    MO
           *
           * The MOM function is the only one who is not normalized, and thus
           * should be avoided for comparing different time serie of prices.
           *
           * ROC and ROCP are centered at zero and can have positive and negative
           * value. Here are some equivalence:
           *    ROC = ROCP/100
           *        = ((price-prevPrice)/prevPrice)/100
           *        = ((price/prevPrice)-1)*100
           *
           * ROCR and ROCR100 are ratio respectively centered at 1 and 100 and are
           * always positive values.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate Rate of change Ratio: (price / prevPrice) */
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] - tempReal) / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocPUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] - tempReal) / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocP( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] - tempReal) / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocPUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = (inReal[inIdx] - tempReal) / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int rocRLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode rocR( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The interpretation of the rate of change varies widely depending
           * which software and/or books you are refering to.
           *
           * The following is the table of Rate-Of-Change implemented in TA-LIB:
           *       MOM     = (price - prevPrice)         [Momentum]
           *       ROC     = ((price/prevPrice)-1)*100   [Rate of change]
           *       ROCP    = (price-prevPrice)/prevPrice [Rate of change Percentage]
           *       ROCR    = (price/prevPrice)           [Rate of change ratio]
           *       ROCR100 = (price/prevPrice)*100       [Rate of change ratio 100 Scale]
           *
           * Here are the equivalent function in other software:
           *       TA-Lib  |   Tradestation   |    Metastock
           *       =================================================
           *       MOM     |   Momentum       |    ROC (Point)
           *       ROC     |   ROC            |    ROC (Percent)
           *       ROCP    |   PercentChange  |    -
           *       ROCR    |   -              |    -
           *       ROCR100 |   -              |    MO
           *
           * The MOM function is the only one who is not normalized, and thus
           * should be avoided for comparing different time serie of prices.
           *
           * ROC and ROCP are centered at zero and can have positive and negative
           * value. Here are some equivalence:
           *    ROC = ROCP/100
           *        = ((price-prevPrice)/prevPrice)/100
           *        = ((price/prevPrice)-1)*100
           *
           * ROCR and ROCR100 are ratio respectively centered at 1 and 100 and are
           * always positive values.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate Rate of change Ratio: (price / prevPrice) */
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocRUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocR( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocRUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int rocR100Lookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod ;

       }
       public RetCode rocR100( int startIdx,
                               int endIdx,
                               double inReal[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The interpretation of the rate of change varies widely depending
           * which software and/or books you are refering to.
           *
           * The following is the table of Rate-Of-Change implemented in TA-LIB:
           *       MOM     = (price - prevPrice)         [Momentum]
           *       ROC     = ((price/prevPrice)-1)*100   [Rate of change]
           *       ROCP    = (price-prevPrice)/prevPrice [Rate of change Percentage]
           *       ROCR    = (price/prevPrice)           [Rate of change ratio]
           *       ROCR100 = (price/prevPrice)*100       [Rate of change ratio 100 Scale]
           *
           * Here are the equivalent function in other software:
           *       TA-Lib  |   Tradestation   |    Metastock
           *       =================================================
           *       MOM     |   Momentum       |    ROC (Point)
           *       ROC     |   ROC            |    ROC (Percent)
           *       ROCP    |   PercentChange  |    -
           *       ROCR    |   -              |    -
           *       ROCR100 |   -              |    MO
           *
           * The MOM function is the only one who is not normalized, and thus
           * should be avoided for comparing different time serie of prices.
           *
           * ROC and ROCP are centered at zero and can have positive and negative
           * value. Here are some equivalence:
           *    ROC = ROCP/100
           *        = ((price-prevPrice)/prevPrice)/100
           *        = ((price/prevPrice)-1)*100
           *
           * ROCR and ROCR100 are ratio respectively centered at 1 and 100 and are
           * always positive values.
           */
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Calculate Rate of change Ratio: (price / prevPrice) */
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocR100Unguarded( int startIdx,
                                        int endIdx,
                                        double inReal[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocR100( int startIdx,
                               int endIdx,
                               float inReal[],
                               int optInTimePeriod,
                               MInteger outBegIdx,
                               MInteger outNBElement,
                               double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 10;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode rocR100Unguarded( int startIdx,
                                        int endIdx,
                                        float inReal[],
                                        int optInTimePeriod,
                                        MInteger outBegIdx,
                                        MInteger outNBElement,
                                        double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          double tempReal = 0;
          if( startIdx < optInTimePeriod ) {
             startIdx = optInTimePeriod;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          inIdx = startIdx;
          trailingIdx = startIdx - optInTimePeriod;
          while( inIdx <= endIdx ) {
             tempReal = inReal[trailingIdx++];
             if( tempReal != 0.0 ) {
                outReal[outIdx++] = inReal[inIdx] / tempReal * 100.0;
             } else {
                outReal[outIdx++] = 0.0;
             }
             inIdx += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  062804 MF   Resolve div by zero bug on limit case.
     */

       public int rsiLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          int retValue;
          retValue = optInTimePeriod + this.unstablePeriod[FuncUnstId.Rsi.ordinal()];
          if( this.compatibility == Compatibility.Metastock ) {
             retValue = retValue - 1;
          }
          return retValue ;

       }
       public RetCode rsi( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* The following algorithm is base on the original
           * work from Wilder's and shall represent the
           * original idea behind the classic RSI.
           *
           * Metastock is starting the calculation one price
           * bar earlier. To make this possible, they assume
           * that the very first bar will be identical to the
           * previous one (no gain or loss).
           */
          /* If changing this function, please check also CMO
           * which is mostly identical (just different in one step
           * of calculation).
           */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = (int)rsiLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          /* Trap special case where the period is '1'.
           * In that case, just copy the input into the
           * output for the requested range (as-is !)
           */
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = (int)(endIdx - startIdx + 1);
             outNBElement.value = (int)i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          /* Accumulate Wilder's "Average Gain" and "Average Loss"
           * among the initial period.
           */
          today = startIdx - lookbackTotal;
          prevValue = (double)inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Rsi.ordinal()];
          /* If there is no unstable period,
           * calculate the 'additional' initial
           * price bar who is particuliar to
           * metastock.
           * If there is an unstable period,
           * no need to calculate since this
           * first value will be surely skip.
           */
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             /* Preserve prevValue because it may get
              * overwritten by the output.
              * (because output ptr could be the same as input ptr).
              */
             savePrevValue = prevValue;
             /* No unstable period, so must calculate first output
              * particular to Metastock.
              * (Metastock re-use the first price bar, so there
              *  is no loss/gain at first. Beats me why they
              *  are doing all this).
              */
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = (double)inReal[today];
                today = today + 1;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / (double)optInTimePeriod;
             tempValue2 = prevGain / (double)optInTimePeriod;
             /* Write the output. */
             tempValue1 = tempValue2 + tempValue1;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (tempValue2 / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
             /* Are we done? */
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             /* Start over for the next price bar. */
             today = today - (int)optInTimePeriod;
             prevValue = savePrevValue;
          }
          /* Remaining of the processing is identical
           * for both Classic calculation and Metastock.
           */
          prevGain = 0.0;
          prevLoss = 0.0;
          today = today + 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          /* Subsequent prevLoss and prevGain are smoothed
           * using the previous values (Wilder's approach).
           *  1) Multiply the previous by 'period-1'.
           *  2) Add today value.
           *  3) Divide by 'period'.
           */
          prevLoss /= (double)optInTimePeriod;
          prevGain /= (double)optInTimePeriod;
          /* Often documentation present the RSI calculation as follow:
           *    RSI = 100 - (100 / 1 + (prevGain/prevLoss))
           *
           * The following is equivalent:
           *    RSI = 100 * (prevGain/(prevGain+prevLoss))
           *
           * The second equation is used here for speed optimization.
           */
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          } else {
             /* Skip the unstable period. Do the processing
              * but do not write it in the output.
              */
             while( today < startIdx ) {
                tempValue1 = (double)inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= (double)(optInTimePeriod - 1);
                prevGain *= (double)(optInTimePeriod - 1);
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= (double)optInTimePeriod;
                prevGain /= (double)optInTimePeriod;
                today = today + 1;
             }
          }
          /* Unstable period skipped... now continue
           * processing if needed.
           */
          while( today <= endIdx ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= (double)(optInTimePeriod - 1);
             prevGain *= (double)(optInTimePeriod - 1);
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= (double)optInTimePeriod;
             prevGain /= (double)optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode rsiUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = (int)rsiLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = (int)(endIdx - startIdx + 1);
             outNBElement.value = (int)i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = (double)inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Rsi.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = (double)inReal[today];
                today = today + 1;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / (double)optInTimePeriod;
             tempValue2 = prevGain / (double)optInTimePeriod;
             tempValue1 = tempValue2 + tempValue1;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (tempValue2 / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today = today - (int)optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today = today + 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= (double)optInTimePeriod;
          prevGain /= (double)optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = (double)inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= (double)(optInTimePeriod - 1);
                prevGain *= (double)(optInTimePeriod - 1);
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= (double)optInTimePeriod;
                prevGain /= (double)optInTimePeriod;
                today = today + 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= (double)(optInTimePeriod - 1);
             prevGain *= (double)(optInTimePeriod - 1);
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= (double)optInTimePeriod;
             prevGain /= (double)optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode rsi( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = (int)rsiLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = (int)(endIdx - startIdx + 1);
             outNBElement.value = (int)i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = (double)inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Rsi.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = (double)inReal[today];
                today = today + 1;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / (double)optInTimePeriod;
             tempValue2 = prevGain / (double)optInTimePeriod;
             tempValue1 = tempValue2 + tempValue1;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (tempValue2 / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today = today - (int)optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today = today + 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= (double)optInTimePeriod;
          prevGain /= (double)optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = (double)inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= (double)(optInTimePeriod - 1);
                prevGain *= (double)(optInTimePeriod - 1);
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= (double)optInTimePeriod;
                prevGain /= (double)optInTimePeriod;
                today = today + 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= (double)(optInTimePeriod - 1);
             prevGain *= (double)(optInTimePeriod - 1);
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= (double)optInTimePeriod;
             prevGain /= (double)optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode rsiUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          int unstablePeriod = 0;
          int i = 0;
          double prevGain = 0;
          double prevLoss = 0;
          double prevValue = 0;
          double savePrevValue = 0;
          double tempValue1 = 0;
          double tempValue2 = 0;
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackTotal = (int)rsiLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             i = (int)(endIdx - startIdx + 1);
             outNBElement.value = (int)i;
             System.arraycopy(inReal, startIdx, outReal, 0, i * 1);
             return RetCode.Success ;
          }
          today = startIdx - lookbackTotal;
          prevValue = (double)inReal[today];
          unstablePeriod = this.unstablePeriod[FuncUnstId.Rsi.ordinal()];
          if( unstablePeriod == 0 && this.compatibility == Compatibility.Metastock ) {
             savePrevValue = prevValue;
             prevGain = 0.0;
             prevLoss = 0.0;
             for( i = optInTimePeriod; i > 0; i -= 1 ) {
                tempValue1 = (double)inReal[today];
                today = today + 1;
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
             }
             tempValue1 = prevLoss / (double)optInTimePeriod;
             tempValue2 = prevGain / (double)optInTimePeriod;
             tempValue1 = tempValue2 + tempValue1;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (tempValue2 / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
             if( today > endIdx ) {
                outBegIdx.value = startIdx;
                outNBElement.value = outIdx;
                return RetCode.Success ;
             }
             today = today - (int)optInTimePeriod;
             prevValue = savePrevValue;
          }
          prevGain = 0.0;
          prevLoss = 0.0;
          today = today + 1;
          for( i = optInTimePeriod; i > 0; i -= 1 ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
          }
          prevLoss /= (double)optInTimePeriod;
          prevGain /= (double)optInTimePeriod;
          if( today > startIdx ) {
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          } else {
             while( today < startIdx ) {
                tempValue1 = (double)inReal[today];
                tempValue2 = tempValue1 - prevValue;
                prevValue = tempValue1;
                prevLoss *= (double)(optInTimePeriod - 1);
                prevGain *= (double)(optInTimePeriod - 1);
                if( tempValue2 < 0.0 ) {
                   prevLoss -= tempValue2;
                } else {
                   prevGain += tempValue2;
                }
                prevLoss /= (double)optInTimePeriod;
                prevGain /= (double)optInTimePeriod;
                today = today + 1;
             }
          }
          while( today <= endIdx ) {
             tempValue1 = (double)inReal[today];
             today = today + 1;
             tempValue2 = tempValue1 - prevValue;
             prevValue = tempValue1;
             prevLoss *= (double)(optInTimePeriod - 1);
             prevGain *= (double)(optInTimePeriod - 1);
             if( tempValue2 < 0.0 ) {
                prevLoss -= tempValue2;
             } else {
                prevGain += tempValue2;
             }
             prevLoss /= (double)optInTimePeriod;
             prevGain /= (double)optInTimePeriod;
             tempValue1 = prevGain + prevLoss;
             if( !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) ) {
                outReal[outIdx] = 100.0 * (prevGain / tempValue1);
                outIdx = outIdx + 1;
             } else {
                outReal[outIdx] = 0.0;
                outIdx = outIdx + 1;
             }
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  CF       Christo Fogelberg
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  010802 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  122104 MF,CF  Fix#1089506 for out-of-bound access to ep_temp.
     */

       public int sarLookback( double optInAcceleration, double optInMaximum )
       {
          if( optInAcceleration == -4e37 ) {
             optInAcceleration = 2e-2;
          } else if( optInAcceleration < 0e0 || optInAcceleration > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInMaximum == -4e37 ) {
             optInMaximum = 2e-1;
          } else if( optInMaximum < 0e0 || optInMaximum > 1.7976931348623157e308 ) {
             return -1;
          }
          /* SAR always sacrify one price bar to establish the
           * initial extreme price.
           */
          return 1 ;

       }
       public RetCode sar( int startIdx,
                           int endIdx,
                           double inHigh[],
                           double inLow[],
                           double optInAcceleration,
                           double optInMaximum,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double af = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInAcceleration == -4e37 ) {
             optInAcceleration = 2e-2;
          } else if( optInAcceleration < 0e0 || optInAcceleration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInMaximum == -4e37 ) {
             optInMaximum = 2e-1;
          } else if( optInMaximum < 0e0 || optInMaximum > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* > 0 indicates long. == 0 indicates short */
          /* Implementation of the SAR has been a little bit open to interpretation
           * since Wilder (the original author) did not define a precise algorithm
           * on how to bootstrap the algorithm. Take any existing software application
           * and you will see slight variation on how the algorithm was adapted.
           *
           * What is the initial trade direction? Long or short?
           * ===================================================
           * The interpretation of what should be the initial SAR values is
           * open to interpretation, particularly since the caller to the function
           * does not specify the initial direction of the trade.
           *
           * In TA-Lib, the following logic is used:
           *  - Calculate +DM and -DM between the first and
           *    second bar. The highest directional indication will
           *    indicate the assumed direction of the trade for the second
           *    price bar.
           *  - In the case of a tie between +DM and -DM,
           *    the direction is LONG by default.
           *
           * What is the initial "extreme point" and thus SAR?
           * =================================================
           * The following shows how different people took different approach:
           *  - Metastock use the first price bar high/low depending of
           *    the direction. No SAR is calculated for the first price
           *    bar.
           *  - Tradestation use the closing price of the second bar. No
           *    SAR are calculated for the first price bar.
           *  - Wilder (the original author) use the SIP from the
           *    previous trade (cannot be implement here since the
           *    direction and length of the previous trade is unknonw).
           *  - The Magazine TASC seems to follow Wilder approach which
           *    is not practical here.
           *
           * TA-Lib "consume" the first price bar and use its high/low as the
           * initial SAR of the second price bar. I found that approach to be
           * the closest to Wilders idea of having the first entry day use
           * the previous extreme point, except that here the extreme point is
           * derived solely from the first price bar. I found the same approach
           * to be used by Metastock.
           */
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           *
           * Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Make sure the acceleration and maximum are coherent.
           * If not, correct the acceleration.
           */
          af = optInAcceleration;
          if( af > optInMaximum ) {
             optInAcceleration = optInMaximum;
             af = optInAcceleration;
          }
          /* Identify if the initial direction is long or short.
           * (ep is just used as a temp buffer here, the name
           *  of the parameter is not significant).
           */
          retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
          if( ep_temp[0] > 0 ) {
             isLong = 0;
          } else {
             isLong = 1;
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          /* Write the first SAR. */
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( isLong == 1 ) {
             ep = inHigh[todayIdx];
             sar = newLow;
          } else {
             ep = inLow[todayIdx];
             sar = newHigh;
          }
          /* Cheat on the newLow and newHigh for the
           * first iteration.
           */
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                /* Switch to short if the low penetrates the SAR value. */
                if( newLow <= sar ) {
                   /* Switch and Overide the SAR with the ep */
                   isLong = 0;
                   sar = ep;
                   /* Make sure the overide SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   /* Output the overide SAR */
                   outReal[outIdx++] = sar;
                   /* Adjust af and ep */
                   af = optInAcceleration;
                   ep = newLow;
                   /* Calculate the new SAR */
                   sar = sar + af * (ep - sar);
                   /* Make sure the new SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   /* No switch */
                   /* Output the SAR (was calculated in the previous iteration) */
                   outReal[outIdx++] = sar;
                   /* Adjust af and ep. */
                   if( newHigh > ep ) {
                      ep = newHigh;
                      af += optInAcceleration;
                      if( af > optInMaximum ) {
                         af = optInMaximum;
                      }
                   }
                   /* Calculate the new SAR */
                   sar = sar + af * (ep - sar);
                   /* Make sure the new SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             /* Switch to long if the high penetrates the SAR value. */
             } else if( newHigh >= sar ) {
                /* Switch and Overide the SAR with the ep */
                isLong = 1;
                sar = ep;
                /* Make sure the overide SAR is within
                 * yesterday's and today's range.
                 */
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                /* Output the overide SAR */
                outReal[outIdx++] = sar;
                /* Adjust af and ep */
                af = optInAcceleration;
                ep = newHigh;
                /* Calculate the new SAR */
                sar = sar + af * (ep - sar);
                /* Make sure the new SAR is within
                 * yesterday's and today's range.
                 */
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                /* No switch */
                /* Output the SAR (was calculated in the previous iteration) */
                outReal[outIdx++] = sar;
                /* Adjust af and ep. */
                if( newLow < ep ) {
                   ep = newLow;
                   af += optInAcceleration;
                   if( af > optInMaximum ) {
                      af = optInMaximum;
                   }
                }
                /* Calculate the new SAR */
                sar = sar + af * (ep - sar);
                /* Make sure the new SAR is within
                 * yesterday's and today's range.
                 */
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sarUnguarded( int startIdx,
                                    int endIdx,
                                    double inHigh[],
                                    double inLow[],
                                    double optInAcceleration,
                                    double optInMaximum,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double af = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          af = optInAcceleration;
          if( af > optInMaximum ) {
             optInAcceleration = optInMaximum;
             af = optInAcceleration;
          }
          retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
          if( ep_temp[0] > 0 ) {
             isLong = 0;
          } else {
             isLong = 1;
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( isLong == 1 ) {
             ep = inHigh[todayIdx];
             sar = newLow;
          } else {
             ep = inLow[todayIdx];
             sar = newHigh;
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   outReal[outIdx++] = sar;
                   af = optInAcceleration;
                   ep = newLow;
                   sar = sar + af * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      af += optInAcceleration;
                      if( af > optInMaximum ) {
                         af = optInMaximum;
                      }
                   }
                   sar = sar + af * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                outReal[outIdx++] = sar;
                af = optInAcceleration;
                ep = newHigh;
                sar = sar + af * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = sar;
                if( newLow < ep ) {
                   ep = newLow;
                   af += optInAcceleration;
                   if( af > optInMaximum ) {
                      af = optInMaximum;
                   }
                }
                sar = sar + af * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sar( int startIdx,
                           int endIdx,
                           float inHigh[],
                           float inLow[],
                           double optInAcceleration,
                           double optInMaximum,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double af = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInAcceleration == -4e37 ) {
             optInAcceleration = 2e-2;
          } else if( optInAcceleration < 0e0 || optInAcceleration > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInMaximum == -4e37 ) {
             optInMaximum = 2e-1;
          } else if( optInMaximum < 0e0 || optInMaximum > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          af = optInAcceleration;
          if( af > optInMaximum ) {
             optInAcceleration = optInMaximum;
             af = optInAcceleration;
          }
          retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
          if( ep_temp[0] > 0 ) {
             isLong = 0;
          } else {
             isLong = 1;
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( isLong == 1 ) {
             ep = inHigh[todayIdx];
             sar = newLow;
          } else {
             ep = inLow[todayIdx];
             sar = newHigh;
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   outReal[outIdx++] = sar;
                   af = optInAcceleration;
                   ep = newLow;
                   sar = sar + af * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      af += optInAcceleration;
                      if( af > optInMaximum ) {
                         af = optInMaximum;
                      }
                   }
                   sar = sar + af * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                outReal[outIdx++] = sar;
                af = optInAcceleration;
                ep = newHigh;
                sar = sar + af * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = sar;
                if( newLow < ep ) {
                   ep = newLow;
                   af += optInAcceleration;
                   if( af > optInMaximum ) {
                      af = optInMaximum;
                   }
                }
                sar = sar + af * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sarUnguarded( int startIdx,
                                    int endIdx,
                                    float inHigh[],
                                    float inLow[],
                                    double optInAcceleration,
                                    double optInMaximum,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double af = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          af = optInAcceleration;
          if( af > optInMaximum ) {
             optInAcceleration = optInMaximum;
             af = optInAcceleration;
          }
          retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
          if( ep_temp[0] > 0 ) {
             isLong = 0;
          } else {
             isLong = 1;
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( isLong == 1 ) {
             ep = inHigh[todayIdx];
             sar = newLow;
          } else {
             ep = inLow[todayIdx];
             sar = newHigh;
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   outReal[outIdx++] = sar;
                   af = optInAcceleration;
                   ep = newLow;
                   sar = sar + af * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      af += optInAcceleration;
                      if( af > optInMaximum ) {
                         af = optInMaximum;
                      }
                   }
                   sar = sar + af * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                outReal[outIdx++] = sar;
                af = optInAcceleration;
                ep = newHigh;
                sar = sar + af * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = sar;
                if( newLow < ep ) {
                   ep = newLow;
                   af += optInAcceleration;
                   if( af > optInMaximum ) {
                      af = optInMaximum;
                   }
                }
                sar = sar + af * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  PP       Peter Pudaite
     *  CF       Christo Fogelberg
     *
     * Change history:
     *
     *  MMDDYY BY    Description
     *  -------------------------------------------------------------------
     *  120802 MF    Template creation.
     *  091503 PP    Reworked TA_SAR to allow customisation of more SAR params.
     *  092103 MF    Some changes related on first round of tests
     *  092303 PP    Minor bug fixes.
     *  122104 MF,CF Fix#1089506 for out-of-bound access to ep_temp.
     */

       public int sarExtLookback( double optInStartValue, double optInOffsetOnReverse, double optInAccelerationInitLong, double optInAccelerationLong, double optInAccelerationMaxLong, double optInAccelerationInitShort, double optInAccelerationShort, double optInAccelerationMaxShort )
       {
          if( optInStartValue == -4e37 ) {
             optInStartValue = 0e0;
          }
          if( optInOffsetOnReverse == -4e37 ) {
             optInOffsetOnReverse = 0e0;
          } else if( optInOffsetOnReverse < 0e0 || optInOffsetOnReverse > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationInitLong == -4e37 ) {
             optInAccelerationInitLong = 2e-2;
          } else if( optInAccelerationInitLong < 0e0 || optInAccelerationInitLong > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationLong == -4e37 ) {
             optInAccelerationLong = 2e-2;
          } else if( optInAccelerationLong < 0e0 || optInAccelerationLong > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationMaxLong == -4e37 ) {
             optInAccelerationMaxLong = 2e-1;
          } else if( optInAccelerationMaxLong < 0e0 || optInAccelerationMaxLong > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationInitShort == -4e37 ) {
             optInAccelerationInitShort = 2e-2;
          } else if( optInAccelerationInitShort < 0e0 || optInAccelerationInitShort > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationShort == -4e37 ) {
             optInAccelerationShort = 2e-2;
          } else if( optInAccelerationShort < 0e0 || optInAccelerationShort > 1.7976931348623157e308 ) {
             return -1;
          }
          if( optInAccelerationMaxShort == -4e37 ) {
             optInAccelerationMaxShort = 2e-1;
          } else if( optInAccelerationMaxShort < 0e0 || optInAccelerationMaxShort > 1.7976931348623157e308 ) {
             return -1;
          }
          /* SAR always sacrifices one price bar to establish the
           * initial extreme price.
           */
          return 1 ;

       }
       public RetCode sarExt( int startIdx,
                              int endIdx,
                              double inHigh[],
                              double inLow[],
                              double optInStartValue,
                              double optInOffsetOnReverse,
                              double optInAccelerationInitLong,
                              double optInAccelerationLong,
                              double optInAccelerationMaxLong,
                              double optInAccelerationInitShort,
                              double optInAccelerationShort,
                              double optInAccelerationMaxShort,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double afLong = 0;
          double afShort = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInStartValue == -4e37 ) {
             optInStartValue = 0e0;
          }
          if( optInOffsetOnReverse == -4e37 ) {
             optInOffsetOnReverse = 0e0;
          } else if( optInOffsetOnReverse < 0e0 || optInOffsetOnReverse > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationInitLong == -4e37 ) {
             optInAccelerationInitLong = 2e-2;
          } else if( optInAccelerationInitLong < 0e0 || optInAccelerationInitLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationLong == -4e37 ) {
             optInAccelerationLong = 2e-2;
          } else if( optInAccelerationLong < 0e0 || optInAccelerationLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationMaxLong == -4e37 ) {
             optInAccelerationMaxLong = 2e-1;
          } else if( optInAccelerationMaxLong < 0e0 || optInAccelerationMaxLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationInitShort == -4e37 ) {
             optInAccelerationInitShort = 2e-2;
          } else if( optInAccelerationInitShort < 0e0 || optInAccelerationInitShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationShort == -4e37 ) {
             optInAccelerationShort = 2e-2;
          } else if( optInAccelerationShort < 0e0 || optInAccelerationShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationMaxShort == -4e37 ) {
             optInAccelerationMaxShort = 2e-1;
          } else if( optInAccelerationMaxShort < 0e0 || optInAccelerationMaxShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          /* > 0 indicates long. == 0 indicates short */
          /* This function is the same as TA_SAR, except that the caller has
           * greater control on the SAR dynamic and initial state.
           *
           * In additon, the TA_SAREXT returns negative values when the position
           * is short. This allow to distinguish when the SAR do actually reverse.
           */
          /* Implementation of the SAR has been a little bit open to interpretation
           * since Wilder (the original author) did not define a precise algorithm
           * on how to bootstrap the algorithm. Take any existing software application
           * and you will see slight variation on how the algorithm was adapted.
           *
           * What is the initial trade direction? Long or short?
           * ===================================================
           * The interpretation of what should be the initial SAR values is
           * open to interpretation, particularly since the caller to the function
           * does not specify the initial direction of the trade.
           *
           * In TA-Lib, the following default logic is used:
           *  - Calculate +DM and -DM between the first and
           *    second bar. The highest directional indication will
           *    indicate the assumed direction of the trade for the second
           *    price bar.
           *  - In the case of a tie between +DM and -DM,
           *    the direction is LONG by default.
           *
           * What is the initial "extreme point" and thus SAR?
           * =================================================
           * The following shows how different people took different approach:
           *  - Metastock use the first price bar high/low depending of
           *    the direction. No SAR is calculated for the first price
           *    bar.
           *  - Tradestation use the closing price of the second bar. No
           *    SAR are calculated for the first price bar.
           *  - Wilder (the original author) use the SIP from the
           *    previous trade (cannot be implement here since the
           *    direction and length of the previous trade is unknonw).
           *  - The Magazine TASC seems to follow Wilder approach which
           *    is not practical here.
           *
           * TA-Lib "consume" the first price bar and use its high/low as the
           * initial SAR of the second price bar. I found that approach to be
           * the closest to Wilders idea of having the first entry day use
           * the previous extreme point, except that here the extreme point is
           * derived solely from the first price bar. I found the same approach
           * to be used by Metastock.
           *
           *
           * Can I force the initial SAR?
           * ============================
           * Yes. Using the optInStartValue_0 parameter:
           *  optInStartValue_0 >  0 : SAR is long at optInStartValue_0.
           *  optInStartValue_0 <  0 : SAR is short at fabs(optInStartValue_0).
           *
           * And when optInStartValue_0 == 0, the logic is the same as for TA_SAR
           * (See previous two sections).
           */
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           *
           * Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Check if the acceleration factors are being defined by the user.
           * Make sure the acceleration and maximum are coherent.
           * If not, correct the acceleration.
           * Default afLong = 0.02
           * Default afShort = 0.02
           */
          afLong = optInAccelerationInitLong;
          afShort = optInAccelerationInitShort;
          if( afLong > optInAccelerationMaxLong ) {
             optInAccelerationInitLong = optInAccelerationMaxLong;
             afLong = optInAccelerationInitLong;
          }
          if( optInAccelerationLong > optInAccelerationMaxLong ) {
             optInAccelerationLong = optInAccelerationMaxLong;
          }
          if( afShort > optInAccelerationMaxShort ) {
             optInAccelerationInitShort = optInAccelerationMaxShort;
             afShort = optInAccelerationInitShort;
          }
          if( optInAccelerationShort > optInAccelerationMaxShort ) {
             optInAccelerationShort = optInAccelerationMaxShort;
          }
          /* Initialise SAR calculations */
          if( optInStartValue == 0 ) {
             /* Default action */
             /* Identify if the initial direction is long or short.
              * (ep is just used as a temp buffer here, the name
              *  of the parameter is not significant).
              */
             retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
             if( ep_temp[0] > 0 ) {
                isLong = 0;
             } else {
                isLong = 1;
             }
             if( retCode != RetCode.Success ) {
                outBegIdx.value = 0;
                outNBElement.value = 0;
                return retCode ;
             }
          } else if( optInStartValue > 0 ) {
             /* Start Long */
             isLong = 1;
          } else {
             /* optInStartValue_0 < 0 => Start Short */
             isLong = 0;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          /* Write the first SAR. */
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( optInStartValue == 0 ) {
             /* Default action */
             if( isLong == 1 ) {
                ep = inHigh[todayIdx];
                sar = newLow;
             } else {
                ep = inLow[todayIdx];
                sar = newHigh;
             }
          } else if( optInStartValue > 0 ) {
             /* Start Long at specified value. */
             ep = inHigh[todayIdx];
             sar = optInStartValue;
          } else {
             /* if optInStartValue < 0 => Start Short at specified value. */
             ep = inLow[todayIdx];
             sar = Math.abs(optInStartValue);
          }
          /* Cheat on the newLow and newHigh for the
           * first iteration.
           */
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                /* Switch to short if the low penetrates the SAR value. */
                if( newLow <= sar ) {
                   /* Switch and Overide the SAR with the ep */
                   isLong = 0;
                   sar = ep;
                   /* Make sure the overide SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   /* Output the overide SAR */
                   if( optInOffsetOnReverse != 0.0 ) {
                      sar += sar * optInOffsetOnReverse;
                   }
                   outReal[outIdx++] = 0 - sar;
                   /* Adjust afShort and ep */
                   afShort = optInAccelerationInitShort;
                   ep = newLow;
                   /* Calculate the new SAR */
                   sar = sar + afShort * (ep - sar);
                   /* Make sure the new SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   /* No switch */
                   /* Output the SAR (was calculated in the previous iteration) */
                   outReal[outIdx++] = sar;
                   /* Adjust afLong and ep. */
                   if( newHigh > ep ) {
                      ep = newHigh;
                      afLong += optInAccelerationLong;
                      if( afLong > optInAccelerationMaxLong ) {
                         afLong = optInAccelerationMaxLong;
                      }
                   }
                   /* Calculate the new SAR */
                   sar = sar + afLong * (ep - sar);
                   /* Make sure the new SAR is within
                    * yesterday's and today's range.
                    */
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             /* Switch to long if the high penetrates the SAR value. */
             } else if( newHigh >= sar ) {
                /* Switch and Overide the SAR with the ep */
                isLong = 1;
                sar = ep;
                /* Make sure the overide SAR is within
                 * yesterday's and today's range.
                 */
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                /* Output the overide SAR */
                if( optInOffsetOnReverse != 0.0 ) {
                   sar -= sar * optInOffsetOnReverse;
                }
                outReal[outIdx++] = sar;
                /* Adjust afLong and ep */
                afLong = optInAccelerationInitLong;
                ep = newHigh;
                /* Calculate the new SAR */
                sar = sar + afLong * (ep - sar);
                /* Make sure the new SAR is within
                 * yesterday's and today's range.
                 */
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                /* No switch */
                /* Output the SAR (was calculated in the previous iteration) */
                outReal[outIdx++] = 0 - sar;
                /* Adjust afShort and ep. */
                if( newLow < ep ) {
                   ep = newLow;
                   afShort += optInAccelerationShort;
                   if( afShort > optInAccelerationMaxShort ) {
                      afShort = optInAccelerationMaxShort;
                   }
                }
                /* Calculate the new SAR */
                sar = sar + afShort * (ep - sar);
                /* Make sure the new SAR is within
                 * yesterday's and today's range.
                 */
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sarExtUnguarded( int startIdx,
                                       int endIdx,
                                       double inHigh[],
                                       double inLow[],
                                       double optInStartValue,
                                       double optInOffsetOnReverse,
                                       double optInAccelerationInitLong,
                                       double optInAccelerationLong,
                                       double optInAccelerationMaxLong,
                                       double optInAccelerationInitShort,
                                       double optInAccelerationShort,
                                       double optInAccelerationMaxShort,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double afLong = 0;
          double afShort = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          afLong = optInAccelerationInitLong;
          afShort = optInAccelerationInitShort;
          if( afLong > optInAccelerationMaxLong ) {
             optInAccelerationInitLong = optInAccelerationMaxLong;
             afLong = optInAccelerationInitLong;
          }
          if( optInAccelerationLong > optInAccelerationMaxLong ) {
             optInAccelerationLong = optInAccelerationMaxLong;
          }
          if( afShort > optInAccelerationMaxShort ) {
             optInAccelerationInitShort = optInAccelerationMaxShort;
             afShort = optInAccelerationInitShort;
          }
          if( optInAccelerationShort > optInAccelerationMaxShort ) {
             optInAccelerationShort = optInAccelerationMaxShort;
          }
          if( optInStartValue == 0 ) {
             retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
             if( ep_temp[0] > 0 ) {
                isLong = 0;
             } else {
                isLong = 1;
             }
             if( retCode != RetCode.Success ) {
                outBegIdx.value = 0;
                outNBElement.value = 0;
                return retCode ;
             }
          } else if( optInStartValue > 0 ) {
             isLong = 1;
          } else {
             isLong = 0;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( optInStartValue == 0 ) {
             if( isLong == 1 ) {
                ep = inHigh[todayIdx];
                sar = newLow;
             } else {
                ep = inLow[todayIdx];
                sar = newHigh;
             }
          } else if( optInStartValue > 0 ) {
             ep = inHigh[todayIdx];
             sar = optInStartValue;
          } else {
             ep = inLow[todayIdx];
             sar = Math.abs(optInStartValue);
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   if( optInOffsetOnReverse != 0.0 ) {
                      sar += sar * optInOffsetOnReverse;
                   }
                   outReal[outIdx++] = 0 - sar;
                   afShort = optInAccelerationInitShort;
                   ep = newLow;
                   sar = sar + afShort * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      afLong += optInAccelerationLong;
                      if( afLong > optInAccelerationMaxLong ) {
                         afLong = optInAccelerationMaxLong;
                      }
                   }
                   sar = sar + afLong * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                if( optInOffsetOnReverse != 0.0 ) {
                   sar -= sar * optInOffsetOnReverse;
                }
                outReal[outIdx++] = sar;
                afLong = optInAccelerationInitLong;
                ep = newHigh;
                sar = sar + afLong * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = 0 - sar;
                if( newLow < ep ) {
                   ep = newLow;
                   afShort += optInAccelerationShort;
                   if( afShort > optInAccelerationMaxShort ) {
                      afShort = optInAccelerationMaxShort;
                   }
                }
                sar = sar + afShort * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sarExt( int startIdx,
                              int endIdx,
                              float inHigh[],
                              float inLow[],
                              double optInStartValue,
                              double optInOffsetOnReverse,
                              double optInAccelerationInitLong,
                              double optInAccelerationLong,
                              double optInAccelerationMaxLong,
                              double optInAccelerationInitShort,
                              double optInAccelerationShort,
                              double optInAccelerationMaxShort,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double afLong = 0;
          double afShort = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInStartValue == -4e37 ) {
             optInStartValue = 0e0;
          }
          if( optInOffsetOnReverse == -4e37 ) {
             optInOffsetOnReverse = 0e0;
          } else if( optInOffsetOnReverse < 0e0 || optInOffsetOnReverse > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationInitLong == -4e37 ) {
             optInAccelerationInitLong = 2e-2;
          } else if( optInAccelerationInitLong < 0e0 || optInAccelerationInitLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationLong == -4e37 ) {
             optInAccelerationLong = 2e-2;
          } else if( optInAccelerationLong < 0e0 || optInAccelerationLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationMaxLong == -4e37 ) {
             optInAccelerationMaxLong = 2e-1;
          } else if( optInAccelerationMaxLong < 0e0 || optInAccelerationMaxLong > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationInitShort == -4e37 ) {
             optInAccelerationInitShort = 2e-2;
          } else if( optInAccelerationInitShort < 0e0 || optInAccelerationInitShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationShort == -4e37 ) {
             optInAccelerationShort = 2e-2;
          } else if( optInAccelerationShort < 0e0 || optInAccelerationShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( optInAccelerationMaxShort == -4e37 ) {
             optInAccelerationMaxShort = 2e-1;
          } else if( optInAccelerationMaxShort < 0e0 || optInAccelerationMaxShort > 1.7976931348623157e308 ) {
             return RetCode.BadParam;
          }
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          afLong = optInAccelerationInitLong;
          afShort = optInAccelerationInitShort;
          if( afLong > optInAccelerationMaxLong ) {
             optInAccelerationInitLong = optInAccelerationMaxLong;
             afLong = optInAccelerationInitLong;
          }
          if( optInAccelerationLong > optInAccelerationMaxLong ) {
             optInAccelerationLong = optInAccelerationMaxLong;
          }
          if( afShort > optInAccelerationMaxShort ) {
             optInAccelerationInitShort = optInAccelerationMaxShort;
             afShort = optInAccelerationInitShort;
          }
          if( optInAccelerationShort > optInAccelerationMaxShort ) {
             optInAccelerationShort = optInAccelerationMaxShort;
          }
          if( optInStartValue == 0 ) {
             retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
             if( ep_temp[0] > 0 ) {
                isLong = 0;
             } else {
                isLong = 1;
             }
             if( retCode != RetCode.Success ) {
                outBegIdx.value = 0;
                outNBElement.value = 0;
                return retCode ;
             }
          } else if( optInStartValue > 0 ) {
             isLong = 1;
          } else {
             isLong = 0;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( optInStartValue == 0 ) {
             if( isLong == 1 ) {
                ep = inHigh[todayIdx];
                sar = newLow;
             } else {
                ep = inLow[todayIdx];
                sar = newHigh;
             }
          } else if( optInStartValue > 0 ) {
             ep = inHigh[todayIdx];
             sar = optInStartValue;
          } else {
             ep = inLow[todayIdx];
             sar = Math.abs(optInStartValue);
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   if( optInOffsetOnReverse != 0.0 ) {
                      sar += sar * optInOffsetOnReverse;
                   }
                   outReal[outIdx++] = 0 - sar;
                   afShort = optInAccelerationInitShort;
                   ep = newLow;
                   sar = sar + afShort * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      afLong += optInAccelerationLong;
                      if( afLong > optInAccelerationMaxLong ) {
                         afLong = optInAccelerationMaxLong;
                      }
                   }
                   sar = sar + afLong * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                if( optInOffsetOnReverse != 0.0 ) {
                   sar -= sar * optInOffsetOnReverse;
                }
                outReal[outIdx++] = sar;
                afLong = optInAccelerationInitLong;
                ep = newHigh;
                sar = sar + afLong * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = 0 - sar;
                if( newLow < ep ) {
                   ep = newLow;
                   afShort += optInAccelerationShort;
                   if( afShort > optInAccelerationMaxShort ) {
                      afShort = optInAccelerationMaxShort;
                   }
                }
                sar = sar + afShort * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode sarExtUnguarded( int startIdx,
                                       int endIdx,
                                       float inHigh[],
                                       float inLow[],
                                       double optInStartValue,
                                       double optInOffsetOnReverse,
                                       double optInAccelerationInitLong,
                                       double optInAccelerationLong,
                                       double optInAccelerationMaxLong,
                                       double optInAccelerationInitShort,
                                       double optInAccelerationShort,
                                       double optInAccelerationMaxShort,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          RetCode retCode;
          int isLong = 0;
          int todayIdx = 0;
          int outIdx = 0;
          MInteger tempInt = new MInteger();
          double newHigh = 0;
          double newLow = 0;
          double prevHigh = 0;
          double prevLow = 0;
          double afLong = 0;
          double afShort = 0;
          double ep = 0;
          double sar = 0;
          double[] ep_temp = new double[1];
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          afLong = optInAccelerationInitLong;
          afShort = optInAccelerationInitShort;
          if( afLong > optInAccelerationMaxLong ) {
             optInAccelerationInitLong = optInAccelerationMaxLong;
             afLong = optInAccelerationInitLong;
          }
          if( optInAccelerationLong > optInAccelerationMaxLong ) {
             optInAccelerationLong = optInAccelerationMaxLong;
          }
          if( afShort > optInAccelerationMaxShort ) {
             optInAccelerationInitShort = optInAccelerationMaxShort;
             afShort = optInAccelerationInitShort;
          }
          if( optInAccelerationShort > optInAccelerationMaxShort ) {
             optInAccelerationShort = optInAccelerationMaxShort;
          }
          if( optInStartValue == 0 ) {
             retCode = minusDMUnguarded(startIdx, startIdx, inHigh, inLow, 1, tempInt, tempInt, ep_temp);
             if( ep_temp[0] > 0 ) {
                isLong = 0;
             } else {
                isLong = 1;
             }
             if( retCode != RetCode.Success ) {
                outBegIdx.value = 0;
                outNBElement.value = 0;
                return retCode ;
             }
          } else if( optInStartValue > 0 ) {
             isLong = 1;
          } else {
             isLong = 0;
          }
          outBegIdx.value = startIdx;
          outIdx = 0;
          todayIdx = startIdx;
          newHigh = inHigh[todayIdx - 1];
          newLow = inLow[todayIdx - 1];
          if( optInStartValue == 0 ) {
             if( isLong == 1 ) {
                ep = inHigh[todayIdx];
                sar = newLow;
             } else {
                ep = inLow[todayIdx];
                sar = newHigh;
             }
          } else if( optInStartValue > 0 ) {
             ep = inHigh[todayIdx];
             sar = optInStartValue;
          } else {
             ep = inLow[todayIdx];
             sar = Math.abs(optInStartValue);
          }
          newLow = inLow[todayIdx];
          newHigh = inHigh[todayIdx];
          while( todayIdx <= endIdx ) {
             prevLow = newLow;
             prevHigh = newHigh;
             newLow = inLow[todayIdx];
             newHigh = inHigh[todayIdx];
             todayIdx += 1;
             if( isLong == 1 ) {
                if( newLow <= sar ) {
                   isLong = 0;
                   sar = ep;
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                   if( optInOffsetOnReverse != 0.0 ) {
                      sar += sar * optInOffsetOnReverse;
                   }
                   outReal[outIdx++] = 0 - sar;
                   afShort = optInAccelerationInitShort;
                   ep = newLow;
                   sar = sar + afShort * (ep - sar);
                   if( sar < prevHigh ) {
                      sar = prevHigh;
                   }
                   if( sar < newHigh ) {
                      sar = newHigh;
                   }
                } else {
                   outReal[outIdx++] = sar;
                   if( newHigh > ep ) {
                      ep = newHigh;
                      afLong += optInAccelerationLong;
                      if( afLong > optInAccelerationMaxLong ) {
                         afLong = optInAccelerationMaxLong;
                      }
                   }
                   sar = sar + afLong * (ep - sar);
                   if( sar > prevLow ) {
                      sar = prevLow;
                   }
                   if( sar > newLow ) {
                      sar = newLow;
                   }
                }
             } else if( newHigh >= sar ) {
                isLong = 1;
                sar = ep;
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
                if( optInOffsetOnReverse != 0.0 ) {
                   sar -= sar * optInOffsetOnReverse;
                }
                outReal[outIdx++] = sar;
                afLong = optInAccelerationInitLong;
                ep = newHigh;
                sar = sar + afLong * (ep - sar);
                if( sar > prevLow ) {
                   sar = prevLow;
                }
                if( sar > newLow ) {
                   sar = newLow;
                }
             } else {
                outReal[outIdx++] = 0 - sar;
                if( newLow < ep ) {
                   ep = newLow;
                   afShort += optInAccelerationShort;
                   if( afShort > optInAccelerationMaxShort ) {
                      afShort = optInAccelerationMaxShort;
                   }
                }
                sar = sar + afShort * (ep - sar);
                if( sar < prevHigh ) {
                   sar = prevHigh;
                }
                if( sar < newHigh ) {
                   sar = newHigh;
                }
             }
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  082507 MF     Initial Version
     */

       public int sinLookback( )
       {
          return 0 ;

       }
       public RetCode sin( int startIdx,
                           int endIdx,
                           double inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sinUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sin( int startIdx,
                           int endIdx,
                           float inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sinUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sin(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int sinhLookback( )
       {
          return 0 ;

       }
       public RetCode sinh( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sinh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sinhUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sinh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sinh( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sinh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sinhUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sinh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int smaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode sma( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = (int)(optInTimePeriod - 1);
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the MA calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          periodTotal = 0.0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += (double)inReal[i];
                i = i + 1;
             }
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the inReal and
           * outReal to be the same buffer.
           */
          outIdx = 0;
          while( i <= endIdx ) {
             periodTotal += (double)inReal[i];
             i = i + 1;
             tempReal = periodTotal;
             periodTotal -= (double)inReal[trailingIdx];
             trailingIdx = trailingIdx + 1;
             outReal[outIdx] = tempReal / (double)optInTimePeriod;
             outIdx = outIdx + 1;
          }
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode smaUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = (int)(optInTimePeriod - 1);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0.0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += (double)inReal[i];
                i = i + 1;
             }
          }
          outIdx = 0;
          while( i <= endIdx ) {
             periodTotal += (double)inReal[i];
             i = i + 1;
             tempReal = periodTotal;
             periodTotal -= (double)inReal[trailingIdx];
             trailingIdx = trailingIdx + 1;
             outReal[outIdx] = tempReal / (double)optInTimePeriod;
             outIdx = outIdx + 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sma( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = (int)(optInTimePeriod - 1);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0.0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += (double)inReal[i];
                i = i + 1;
             }
          }
          outIdx = 0;
          while( i <= endIdx ) {
             periodTotal += (double)inReal[i];
             i = i + 1;
             tempReal = periodTotal;
             periodTotal -= (double)inReal[trailingIdx];
             trailingIdx = trailingIdx + 1;
             outReal[outIdx] = tempReal / (double)optInTimePeriod;
             outIdx = outIdx + 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode smaUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = (int)(optInTimePeriod - 1);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0.0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += (double)inReal[i];
                i = i + 1;
             }
          }
          outIdx = 0;
          while( i <= endIdx ) {
             periodTotal += (double)inReal[i];
             i = i + 1;
             tempReal = periodTotal;
             periodTotal -= (double)inReal[trailingIdx];
             trailingIdx = trailingIdx + 1;
             outReal[outIdx] = tempReal / (double)optInTimePeriod;
             outIdx = outIdx + 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int sqrtLookback( )
       {
          return 0 ;

       }
       public RetCode sqrt( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sqrt(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sqrtUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sqrt(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sqrt( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sqrt(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sqrtUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.sqrt(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JV       Jesus Viver <324122@cienz.unizar.es>
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  100502 JV   Speed optimization of the algorithm
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  090404 MF   Fix #978056. Trap sqrt with negative zero values.
     */

       public int stdDevLookback( int optInTimePeriod, double optInNbDev )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          /* Lookback is driven by the variance. */
          return varianceLookback(optInTimePeriod, optInNbDev) ;

       }
       public RetCode stdDev( int startIdx,
                              int endIdx,
                              double inReal[],
                              int optInTimePeriod,
                              double optInNbDev,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int i = 0;
          RetCode retCode;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          /* Calculate the variance. */
          retCode = varianceUnguarded(startIdx, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, outReal);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          /* Calculate the square root of each variance, this
           * is the standard deviation.
           *
           * Multiply also by the ratio specified.
           */
          if( optInNbDev != 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal) * optInNbDev;
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal);
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          }
          return RetCode.Success ;
       }
       public RetCode stdDevUnguarded( int startIdx,
                                       int endIdx,
                                       double inReal[],
                                       int optInTimePeriod,
                                       double optInNbDev,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int i = 0;
          RetCode retCode;
          double tempReal = 0;
          retCode = varianceUnguarded(startIdx, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, outReal);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          if( optInNbDev != 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal) * optInNbDev;
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal);
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          }
          return RetCode.Success ;
       }
       public RetCode stdDev( int startIdx,
                              int endIdx,
                              float inReal[],
                              int optInTimePeriod,
                              double optInNbDev,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          int i = 0;
          RetCode retCode;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          retCode = varianceUnguarded(startIdx, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, outReal);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          if( optInNbDev != 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal) * optInNbDev;
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal);
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          }
          return RetCode.Success ;
       }
       public RetCode stdDevUnguarded( int startIdx,
                                       int endIdx,
                                       float inReal[],
                                       int optInTimePeriod,
                                       double optInNbDev,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          int i = 0;
          RetCode retCode;
          double tempReal = 0;
          retCode = varianceUnguarded(startIdx, endIdx, inReal, optInTimePeriod, 1.0, outBegIdx, outNBElement, outReal);
          if( retCode != RetCode.Success ) {
             return retCode ;
          }
          if( optInNbDev != 1.0 ) {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal) * optInNbDev;
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          } else {
             for( i = 0; i < (int)outNBElement.value; i += 1 ) {
                tempReal = outReal[i];
                if( !(tempReal < 0.00000000000001) ) {
                   outReal[i] = Math.sqrt(tempReal);
                } else {
                   outReal[i] = (double)0.0;
                }
             }
          }
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int stochLookback( int optInFastK_Period, int optInSlowK_Period, MAType optInSlowK_MAType, int optInSlowD_Period, MAType optInSlowD_MAType )
       {
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return -1;
          }
          if( optInSlowK_Period == Integer.MIN_VALUE ) {
             optInSlowK_Period = 3;
          } else if( optInSlowK_Period < 1 || optInSlowK_Period > 100000 ) {
             return -1;
          }
          if( optInSlowD_Period == Integer.MIN_VALUE ) {
             optInSlowD_Period = 3;
          } else if( optInSlowD_Period < 1 || optInSlowD_Period > 100000 ) {
             return -1;
          }
          int retValue;
          /* Account for the initial data needed for Fast-K. */
          retValue = optInFastK_Period - 1;
          /* Add the smoothing being done for %K slow */
          retValue += movingAverageLookback(optInSlowK_Period, optInSlowK_MAType);
          /* Add the smoothing being done for %D slow. */
          retValue += movingAverageLookback(optInSlowD_Period, optInSlowD_MAType);
          return retValue ;

       }
       public RetCode stoch( int startIdx,
                             int endIdx,
                             double inHigh[],
                             double inLow[],
                             double inClose[],
                             int optInFastK_Period,
                             int optInSlowK_Period,
                             MAType optInSlowK_MAType,
                             int optInSlowD_Period,
                             MAType optInSlowD_MAType,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outSlowK[],
                             double outSlowD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackKSlow = 0;
          int lookbackDSlow = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowK_Period == Integer.MIN_VALUE ) {
             optInSlowK_Period = 3;
          } else if( optInSlowK_Period < 1 || optInSlowK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowD_Period == Integer.MIN_VALUE ) {
             optInSlowD_Period = 3;
          } else if( optInSlowD_Period < 1 || optInSlowD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          /* With stochastic, there is a total of 4 different lines that
           * are defined: FASTK, FASTD, SLOWK and SLOWD.
           *
           * The D is the signal line usually drawn over its
           * corresponding K function.
           *
           *                    (Today's Close - LowestLow)
           *  FASTK(Kperiod) =  --------------------------- * 100
           *                     (HighestHigh - LowestLow)
           *
           *  FASTD(FastDperiod, MA type) = MA Smoothed FASTK over FastDperiod
           *
           *  SLOWK(SlowKperiod, MA type) = MA Smoothed FASTK over SlowKperiod
           *
           *  SLOWD(SlowDperiod, MA Type) = MA Smoothed SLOWK over SlowDperiod
           *
           * The HighestHigh and LowestLow are the extreme values among the
           * last 'Kperiod'.
           *
           * SLOWK and FASTD are equivalent when using the same period.
           *
           * The following shows how these four lines are made available in TA-LIB:
           *
           *  TA_STOCH  : Returns the SLOWK and SLOWD
           *  TA_STOCHF : Returns the FASTK and FASTD
           *
           * The TA_STOCH function correspond to the more widely implemented version
           * found in many software/charting package. The TA_STOCHF is more rarely
           * used because its higher volatility cause often whipsaws.
           */
          /* Identify the lookback needed. */
          lookbackK = optInFastK_Period - 1;
          lookbackKSlow = movingAverageLookback(optInSlowK_Period, optInSlowK_MAType);
          lookbackDSlow = movingAverageLookback(optInSlowD_Period, optInSlowD_MAType);
          lookbackTotal = lookbackK + lookbackDSlow + lookbackKSlow;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             /* Succeed... but no data in the output. */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the K calculation:
           *
           *    Kt = 100 x ((Ct-Lt)/(Ht-Lt))
           *
           * Kt is today stochastic
           * Ct is today closing price.
           * Lt is the lowest price of the last K Period (including today)
           * Ht is the highest price of the last K Period (including today)
           */
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          /* Calculate just enough K for ending up with the caller
           * requested range. (The range of k must consider all
           * the lookback involve with the smoothing).
           */
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          /* Allocate a temporary buffer large enough to
           * store the K.
           *
           * If the output is the same as the input, great
           * we just save ourself one memory allocation.
           */
          bufferIsAllocated = 0;
          if( outSlowK == inHigh || outSlowK == inLow || outSlowK == inClose ) {
             tempBuffer = outSlowK;
          } else if( outSlowD == inHigh || outSlowD == inLow || outSlowD == inClose ) {
             tempBuffer = outSlowD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          /* Do the K calculation */
          while( today <= endIdx ) {
             /* Set the lowest low */
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             /* Set the highest high */
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             /* Calculate stochastic. */
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          /* Un-smoothed K calculation completed. This K calculation is not returned
           * to the caller. It is always smoothed and then return.
           * Some documentation will refer to the smoothed version as being
           * "K-Slow", but often this end up to be shorten to "K".
           */
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInSlowK_Period, optInSlowK_MAType, outBegIdx, outNBElement, tempBuffer);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             /* Something wrong happen? No further data? */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Calculate the %D which is simply a moving average of
           * the already smoothed %K.
           */
          retCode = movingAverageUnguarded(0, (int)outNBElement.value - 1, tempBuffer, optInSlowD_Period, optInSlowD_MAType, outBegIdx, outNBElement, outSlowD);
          /* Copy tempBuffer into the caller buffer.
           * (Calculation could not be done directly in the
           *  caller buffer because more input data then the
           *  requested range was needed for doing %D).
           */
          System.arraycopy(tempBuffer, lookbackDSlow, outSlowK, 0, (int)outNBElement.value * 1);
          /* Don't need K anymore, free it if it was allocated here. */
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             /* Something wrong happen while processing %D? */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Note: Keep the outBegIdx relative to the
           *       caller input before returning.
           */
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stochUnguarded( int startIdx,
                                      int endIdx,
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      int optInFastK_Period,
                                      int optInSlowK_Period,
                                      MAType optInSlowK_MAType,
                                      int optInSlowD_Period,
                                      MAType optInSlowD_MAType,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outSlowK[],
                                      double outSlowD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackKSlow = 0;
          int lookbackDSlow = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          lookbackK = optInFastK_Period - 1;
          lookbackKSlow = movingAverageLookback(optInSlowK_Period, optInSlowK_MAType);
          lookbackDSlow = movingAverageLookback(optInSlowD_Period, optInSlowD_MAType);
          lookbackTotal = lookbackK + lookbackDSlow + lookbackKSlow;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( outSlowK == inHigh || outSlowK == inLow || outSlowK == inClose ) {
             tempBuffer = outSlowK;
          } else if( outSlowD == inHigh || outSlowD == inLow || outSlowD == inClose ) {
             tempBuffer = outSlowD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInSlowK_Period, optInSlowK_MAType, outBegIdx, outNBElement, tempBuffer);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(0, (int)outNBElement.value - 1, tempBuffer, optInSlowD_Period, optInSlowD_MAType, outBegIdx, outNBElement, outSlowD);
          System.arraycopy(tempBuffer, lookbackDSlow, outSlowK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stoch( int startIdx,
                             int endIdx,
                             float inHigh[],
                             float inLow[],
                             float inClose[],
                             int optInFastK_Period,
                             int optInSlowK_Period,
                             MAType optInSlowK_MAType,
                             int optInSlowD_Period,
                             MAType optInSlowD_MAType,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outSlowK[],
                             double outSlowD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackKSlow = 0;
          int lookbackDSlow = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowK_Period == Integer.MIN_VALUE ) {
             optInSlowK_Period = 3;
          } else if( optInSlowK_Period < 1 || optInSlowK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInSlowD_Period == Integer.MIN_VALUE ) {
             optInSlowD_Period = 3;
          } else if( optInSlowD_Period < 1 || optInSlowD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackK = optInFastK_Period - 1;
          lookbackKSlow = movingAverageLookback(optInSlowK_Period, optInSlowK_MAType);
          lookbackDSlow = movingAverageLookback(optInSlowD_Period, optInSlowD_MAType);
          lookbackTotal = lookbackK + lookbackDSlow + lookbackKSlow;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( false || false || false ) {
             tempBuffer = outSlowK;
          } else if( false || false || false ) {
             tempBuffer = outSlowD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInSlowK_Period, optInSlowK_MAType, outBegIdx, outNBElement, tempBuffer);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(0, (int)outNBElement.value - 1, tempBuffer, optInSlowD_Period, optInSlowD_MAType, outBegIdx, outNBElement, outSlowD);
          System.arraycopy(tempBuffer, lookbackDSlow, outSlowK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stochUnguarded( int startIdx,
                                      int endIdx,
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      int optInFastK_Period,
                                      int optInSlowK_Period,
                                      MAType optInSlowK_MAType,
                                      int optInSlowD_Period,
                                      MAType optInSlowD_MAType,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outSlowK[],
                                      double outSlowD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackKSlow = 0;
          int lookbackDSlow = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          lookbackK = optInFastK_Period - 1;
          lookbackKSlow = movingAverageLookback(optInSlowK_Period, optInSlowK_MAType);
          lookbackDSlow = movingAverageLookback(optInSlowD_Period, optInSlowD_MAType);
          lookbackTotal = lookbackK + lookbackDSlow + lookbackKSlow;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( false || false || false ) {
             tempBuffer = outSlowK;
          } else if( false || false || false ) {
             tempBuffer = outSlowD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInSlowK_Period, optInSlowK_MAType, outBegIdx, outNBElement, tempBuffer);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = movingAverageUnguarded(0, (int)outNBElement.value - 1, tempBuffer, optInSlowD_Period, optInSlowD_MAType, outBegIdx, outNBElement, outSlowD);
          System.arraycopy(tempBuffer, lookbackDSlow, outSlowK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  EKO      echo999@ifrance.com
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  051103 EKO  Found bug and fix related to outFastD.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int stochFLookback( int optInFastK_Period, int optInFastD_Period, MAType optInFastD_MAType )
       {
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return -1;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return -1;
          }
          int retValue;
          /* Account for the initial data needed for Fast-K. */
          retValue = optInFastK_Period - 1;
          /* Add the smoothing being done for Fast-D */
          retValue += movingAverageLookback(optInFastD_Period, optInFastD_MAType);
          return retValue ;

       }
       public RetCode stochF( int startIdx,
                              int endIdx,
                              double inHigh[],
                              double inLow[],
                              double inClose[],
                              int optInFastK_Period,
                              int optInFastD_Period,
                              MAType optInFastD_MAType,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outFastK[],
                              double outFastD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackFastD = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          /* With stochastic, there is a total of 4 different lines that
           * are defined: FASTK, FASTD, SLOWK and SLOWD.
           *
           * The D is the signal line usually drawn over its
           * corresponding K function.
           *
           *                    (Today's Close - LowestLow)
           *  FASTK(Kperiod) =  --------------------------- * 100
           *                     (HighestHigh - LowestLow)
           *
           *  FASTD(FastDperiod, MA type) = MA Smoothed FASTK over FastDperiod
           *
           *  SLOWK(SlowKperiod, MA type) = MA Smoothed FASTK over SlowKperiod
           *
           *  SLOWD(SlowDperiod, MA Type) = MA Smoothed SLOWK over SlowDperiod
           *
           * The HighestHigh and LowestLow are the extreme values among the
           * last 'Kperiod'.
           *
           * SLOWK and FASTD are equivalent when using the same period.
           *
           * The following shows how these four lines are made available in TA-LIB:
           *
           *  TA_STOCH  : Returns the SLOWK and SLOWD
           *  TA_STOCHF : Returns the FASTK and FASTD
           *
           * The TA_STOCH function correspond to the more widely implemented version
           * found in many software/charting package. The TA_STOCHF is more rarely
           * used because its higher volatility cause often whipsaws.
           */
          /* Identify the lookback needed. */
          lookbackK = optInFastK_Period - 1;
          lookbackFastD = movingAverageLookback(optInFastD_Period, optInFastD_MAType);
          lookbackTotal = lookbackK + lookbackFastD;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             /* Succeed... but no data in the output. */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the K calculation:
           *
           *    Kt = 100 x ((Ct-Lt)/(Ht-Lt))
           *
           * Kt is today stochastic
           * Ct is today closing price.
           * Lt is the lowest price of the last K Period (including today)
           * Ht is the highest price of the last K Period (including today)
           */
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          /* Calculate just enough K for ending up with the caller
           * requested range. (The range of k must consider all
           * the lookback involve with the smoothing).
           */
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          /* Allocate a temporary buffer large enough to
           * store the K.
           *
           * If the output is the same as the input, great
           * we just save ourself one memory allocation.
           */
          bufferIsAllocated = 0;
          if( outFastK == inHigh || outFastK == inLow || outFastK == inClose ) {
             tempBuffer = outFastK;
          } else if( outFastD == inHigh || outFastD == inLow || outFastD == inClose ) {
             tempBuffer = outFastD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          /* Do the K calculation */
          while( today <= endIdx ) {
             /* Set the lowest low */
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             /* Set the highest high */
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             /* Calculate stochastic. */
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          /* Fast-K calculation completed. This K calculation is returned
           * to the caller. It is smoothed to become Fast-D.
           */
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInFastD_Period, optInFastD_MAType, outBegIdx, outNBElement, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             /* Something wrong happen? No further data? */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Copy tempBuffer into the caller buffer.
           * (Calculation could not be done directly in the
           *  caller buffer because more input data then the
           *  requested range was needed for doing %D).
           */
          System.arraycopy(tempBuffer, lookbackFastD, outFastK, 0, (int)outNBElement.value * 1);
          /* Don't need K anymore, free it if it was allocated here. */
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             /* Something wrong happen while processing %D? */
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          /* Note: Keep the outBegIdx relative to the
           *       caller input before returning.
           */
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stochFUnguarded( int startIdx,
                                       int endIdx,
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       int optInFastK_Period,
                                       int optInFastD_Period,
                                       MAType optInFastD_MAType,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outFastK[],
                                       double outFastD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackFastD = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          lookbackK = optInFastK_Period - 1;
          lookbackFastD = movingAverageLookback(optInFastD_Period, optInFastD_MAType);
          lookbackTotal = lookbackK + lookbackFastD;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( outFastK == inHigh || outFastK == inLow || outFastK == inClose ) {
             tempBuffer = outFastK;
          } else if( outFastD == inHigh || outFastD == inLow || outFastD == inClose ) {
             tempBuffer = outFastD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInFastD_Period, optInFastD_MAType, outBegIdx, outNBElement, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          System.arraycopy(tempBuffer, lookbackFastD, outFastK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stochF( int startIdx,
                              int endIdx,
                              float inHigh[],
                              float inLow[],
                              float inClose[],
                              int optInFastK_Period,
                              int optInFastD_Period,
                              MAType optInFastD_MAType,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outFastK[],
                              double outFastD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackFastD = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackK = optInFastK_Period - 1;
          lookbackFastD = movingAverageLookback(optInFastD_Period, optInFastD_MAType);
          lookbackTotal = lookbackK + lookbackFastD;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( false || false || false ) {
             tempBuffer = outFastK;
          } else if( false || false || false ) {
             tempBuffer = outFastD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInFastD_Period, optInFastD_MAType, outBegIdx, outNBElement, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          System.arraycopy(tempBuffer, lookbackFastD, outFastK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode stochFUnguarded( int startIdx,
                                       int endIdx,
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       int optInFastK_Period,
                                       int optInFastD_Period,
                                       MAType optInFastD_MAType,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outFastK[],
                                       double outFastD[] )
       {
          RetCode retCode;
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          double[] tempBuffer;
          int outIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int lookbackTotal = 0;
          int lookbackK = 0;
          int lookbackFastD = 0;
          int trailingIdx = 0;
          int today = 0;
          int i = 0;
          int bufferIsAllocated = 0;
          lookbackK = optInFastK_Period - 1;
          lookbackFastD = movingAverageLookback(optInFastD_Period, optInFastD_MAType);
          lookbackTotal = lookbackK + lookbackFastD;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          today = trailingIdx + lookbackK;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          bufferIsAllocated = 0;
          if( false || false || false ) {
             tempBuffer = outFastK;
          } else if( false || false || false ) {
             tempBuffer = outFastD;
          } else {
             bufferIsAllocated = 1;
             tempBuffer = new double[(int)((endIdx - today + 1) * 1)];
          }
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / 100.0;
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / 100.0;
             }
             if( diff != 0.0 ) {
                tempBuffer[outIdx++] = (inClose[today] - lowest) / diff;
             } else {
                tempBuffer[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          retCode = movingAverageUnguarded(0, outIdx - 1, tempBuffer, optInFastD_Period, optInFastD_MAType, outBegIdx, outNBElement, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             if( (bufferIsAllocated) != 0 ) {
             }
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          System.arraycopy(tempBuffer, lookbackFastD, outFastK, 0, (int)outNBElement.value * 1);
          if( (bufferIsAllocated) != 0 ) {
          }
          if( retCode != RetCode.Success ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  PP       Peter Pudaite
     *  AA       Andrew Atkinson
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     *  101103 PP   Initial creation of code.
     *  112603 MF   Add independent control to the RSI period.
     *  020605 AA   Fix #1117656. NULL pointer assignement.
     */

       public int stochRsiLookback( int optInTimePeriod, int optInFastK_Period, int optInFastD_Period, MAType optInFastD_MAType )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return -1;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return -1;
          }
          int retValue;
          retValue = rsiLookback(optInTimePeriod) + stochFLookback(optInFastK_Period, optInFastD_Period, optInFastD_MAType);
          return retValue ;

       }
       public RetCode stochRsi( int startIdx,
                                int endIdx,
                                double inReal[],
                                int optInTimePeriod,
                                int optInFastK_Period,
                                int optInFastD_Period,
                                MAType optInFastD_MAType,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outFastK[],
                                double outFastD[] )
       {
          double[] tempRSIBuffer;
          RetCode retCode;
          int lookbackTotal = 0;
          int lookbackSTOCHF = 0;
          int tempArraySize = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          /* Stochastic RSI
           *
           * Reference: "Stochastic RSI and Dynamic Momentum Index"
           *            by Tushar Chande and Stanley Kroll
           *            Stock&Commodities V.11:5 (189-199)
           *
           * The TA-Lib version offer flexibility beyond what is explain
           * in the Stock&Commodities article.
           *
           * To calculate the "Unsmoothed stochastic RSI" with symetry like
           * explain in the article, keep the optInTimePeriod and optInFastK_Period
           * equal. Example:
           *
           *    unsmoothed stoch RSI 14 : optInTimePeriod   = 14
           *                              optInFastK_Period = 14
           *                              optInFastD_Period = 'x'
           *
           * The outFastK is the unsmoothed RSI discuss in the article.
           *
           * You can set the optInFastD_Period to smooth the RSI. The smooth
           * version will be found in outFastD. The outFastK will still contain
           * the unsmoothed stoch RSI. If you do not care about the smoothing of
           * the StochRSI, just leave optInFastD_Period to 1 and ignore outFastD.
           */
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackSTOCHF = stochFLookback(optInFastK_Period, optInFastD_Period, optInFastD_MAType);
          lookbackTotal = rsiLookback(optInTimePeriod) + lookbackSTOCHF;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          tempArraySize = endIdx - startIdx + 1 + lookbackSTOCHF;
          tempRSIBuffer = new double[(int)(tempArraySize * 1)];
          retCode = rsiUnguarded(startIdx - lookbackSTOCHF, endIdx, inReal, optInTimePeriod, outBegIdx1, outNbElement1, tempRSIBuffer);
          if( retCode != RetCode.Success || outNbElement1.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = stochFUnguarded(0, tempArraySize - 1, tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, optInFastK_Period, optInFastD_Period, optInFastD_MAType, outBegIdx2, outNBElement, outFastK, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode stochRsiUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         int optInTimePeriod,
                                         int optInFastK_Period,
                                         int optInFastD_Period,
                                         MAType optInFastD_MAType,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outFastK[],
                                         double outFastD[] )
       {
          double[] tempRSIBuffer;
          RetCode retCode;
          int lookbackTotal = 0;
          int lookbackSTOCHF = 0;
          int tempArraySize = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackSTOCHF = stochFLookback(optInFastK_Period, optInFastD_Period, optInFastD_MAType);
          lookbackTotal = rsiLookback(optInTimePeriod) + lookbackSTOCHF;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          tempArraySize = endIdx - startIdx + 1 + lookbackSTOCHF;
          tempRSIBuffer = new double[(int)(tempArraySize * 1)];
          retCode = rsiUnguarded(startIdx - lookbackSTOCHF, endIdx, inReal, optInTimePeriod, outBegIdx1, outNbElement1, tempRSIBuffer);
          if( retCode != RetCode.Success || outNbElement1.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = stochFUnguarded(0, tempArraySize - 1, tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, optInFastK_Period, optInFastD_Period, optInFastD_MAType, outBegIdx2, outNBElement, outFastK, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode stochRsi( int startIdx,
                                int endIdx,
                                float inReal[],
                                int optInTimePeriod,
                                int optInFastK_Period,
                                int optInFastD_Period,
                                MAType optInFastD_MAType,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outFastK[],
                                double outFastD[] )
       {
          double[] tempRSIBuffer;
          RetCode retCode;
          int lookbackTotal = 0;
          int lookbackSTOCHF = 0;
          int tempArraySize = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastK_Period == Integer.MIN_VALUE ) {
             optInFastK_Period = 5;
          } else if( optInFastK_Period < 1 || optInFastK_Period > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInFastD_Period == Integer.MIN_VALUE ) {
             optInFastD_Period = 3;
          } else if( optInFastD_Period < 1 || optInFastD_Period > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackSTOCHF = stochFLookback(optInFastK_Period, optInFastD_Period, optInFastD_MAType);
          lookbackTotal = rsiLookback(optInTimePeriod) + lookbackSTOCHF;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          tempArraySize = endIdx - startIdx + 1 + lookbackSTOCHF;
          tempRSIBuffer = new double[(int)(tempArraySize * 1)];
          retCode = rsiUnguarded(startIdx - lookbackSTOCHF, endIdx, inReal, optInTimePeriod, outBegIdx1, outNbElement1, tempRSIBuffer);
          if( retCode != RetCode.Success || outNbElement1.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = stochFUnguarded(0, tempArraySize - 1, tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, optInFastK_Period, optInFastD_Period, optInFastD_MAType, outBegIdx2, outNBElement, outFastK, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode stochRsiUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         int optInTimePeriod,
                                         int optInFastK_Period,
                                         int optInFastD_Period,
                                         MAType optInFastD_MAType,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outFastK[],
                                         double outFastD[] )
       {
          double[] tempRSIBuffer;
          RetCode retCode;
          int lookbackTotal = 0;
          int lookbackSTOCHF = 0;
          int tempArraySize = 0;
          MInteger outBegIdx1 = new MInteger();
          MInteger outBegIdx2 = new MInteger();
          MInteger outNbElement1 = new MInteger();
          outBegIdx.value = 0;
          outNBElement.value = 0;
          lookbackSTOCHF = stochFLookback(optInFastK_Period, optInFastD_Period, optInFastD_MAType);
          lookbackTotal = rsiLookback(optInTimePeriod) + lookbackSTOCHF;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          tempArraySize = endIdx - startIdx + 1 + lookbackSTOCHF;
          tempRSIBuffer = new double[(int)(tempArraySize * 1)];
          retCode = rsiUnguarded(startIdx - lookbackSTOCHF, endIdx, inReal, optInTimePeriod, outBegIdx1, outNbElement1, tempRSIBuffer);
          if( retCode != RetCode.Success || outNbElement1.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          retCode = stochFUnguarded(0, tempArraySize - 1, tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, optInFastK_Period, optInFastD_Period, optInFastD_MAType, outBegIdx2, outNBElement, outFastK, outFastD);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int subLookback( )
       {
          return 0 ;

       }
       public RetCode sub( int startIdx,
                           int endIdx,
                           double inReal0[],
                           double inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Default return values */
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] - inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode subUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal0[],
                                    double inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] - inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sub( int startIdx,
                           int endIdx,
                           float inReal0[],
                           float inReal1[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] - inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode subUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal0[],
                                    float inReal1[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = inReal0[i] - inReal1[i];
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  120802 MF   Template creation.
     */

       public int sumLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode sum( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the MA calculation using tight loops. */
          /* Add-up the initial period, except for the last value. */
          periodTotal = 0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += inReal[i++];
             }
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the inReal and
           * outReal to be the same buffer.
           */
          outIdx = 0;
          do {
             periodTotal += inReal[i++];
             tempReal = periodTotal;
             periodTotal -= inReal[trailingIdx++];
             outReal[outIdx++] = tempReal;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sumUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += inReal[i++];
             }
          }
          outIdx = 0;
          do {
             periodTotal += inReal[i++];
             tempReal = periodTotal;
             periodTotal -= inReal[trailingIdx++];
             outReal[outIdx++] = tempReal;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sum( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += inReal[i++];
             }
          }
          outIdx = 0;
          do {
             periodTotal += inReal[i++];
             tempReal = periodTotal;
             periodTotal -= inReal[trailingIdx++];
             outReal[outIdx++] = tempReal;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode sumUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          double periodTotal = 0;
          double tempReal = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int lookbackTotal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal = 0;
          trailingIdx = startIdx - lookbackTotal;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                periodTotal += inReal[i++];
             }
          }
          outIdx = 0;
          do {
             periodTotal += inReal[i++];
             tempReal = periodTotal;
             periodTotal -= inReal[trailingIdx++];
             outReal[outIdx++] = tempReal;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MHL      Matthew Lindblom
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  120802 MF     Template creation.
     *  032003 MHL    Implementation of T3
     *  040503 MF     Adapt for compatibility with published code
     *                for TradeStation and Metastock.
     *                See "Smoothing Techniques For More Accurate Signals"
     *                from Tim Tillson in Stock&Commodities V16:1 Page 33-37
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  070226 MF,CC  Allow period of 1: output is an exact copy of the
     *                input, consistent with TA_MA (issues #48, #59). The
     *                natural math is only near-identity at period=1: the
     *                coefficients sum to 1 in real arithmetic but not in
     *                floating point (~1e-14 drift), so the copy is explicit.
     */

       public int t3Lookback( int optInTimePeriod, double optInVFactor )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInVFactor == -4e37 ) {
             optInVFactor = 7e-1;
          } else if( optInVFactor < 0e0 || optInVFactor > 1e0 ) {
             return -1;
          }
          return 6 * (optInTimePeriod - 1) + this.unstablePeriod[FuncUnstId.T3.ordinal()] ;

       }
       public RetCode t3( int startIdx,
                          int endIdx,
                          double inReal[],
                          int optInTimePeriod,
                          double optInVFactor,
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int outIdx = 0;
          int lookbackTotal = 0;
          int today = 0;
          int i = 0;
          double k = 0;
          double one_minus_k = 0;
          double e1 = 0;
          double e2 = 0;
          double e3 = 0;
          double e4 = 0;
          double e5 = 0;
          double e6 = 0;
          double c1 = 0;
          double c2 = 0;
          double c3 = 0;
          double c4 = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInVFactor == -4e37 ) {
             optInVFactor = 7e-1;
          } else if( optInVFactor < 0e0 || optInVFactor > 1e0 ) {
             return RetCode.BadParam;
          }
          /* For an explanation of this function, please read:
           *
           * Magazine articles written by Tim Tillson
           *
           * Essentially, a T3 of time serie 't' is:
           *   EMA1(x,Period) = EMA(x,Period)
           *   EMA2(x,Period) = EMA(EMA1(x,Period),Period)
           *   GD(x,Period,vFactor) = (EMA1(x,Period)*(1+vFactor)) - (EMA2(x,Period)*vFactor)
           *   T3 = GD (GD ( GD(t, Period, vFactor), Period, vFactor), Period, vFactor);
           *
           * T3 offers a moving average with less lags then the
           * traditional EMA.
           *
           * Do not confuse a T3 with EMA3. Both are called "Triple EMA"
           * in the litterature.
           */
          lookbackTotal = 6 * (optInTimePeriod - 1) + this.unstablePeriod[FuncUnstId.T3.ordinal()];
          if( startIdx <= lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          /* No smoothing at period of 1: the output is a copy of the input
           * (same convention as TA_MA for every MAType). Explicit because the
           * coefficients below sum to 1 only in real arithmetic; going through
           * the math would leave ~1e-14 floating-point drift on every value.
           */
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          k = 2.0 / (optInTimePeriod + 1.0);
          one_minus_k = 1.0 - k;
          /* Initialize e1 */
          tempReal = inReal[today++];
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             tempReal += inReal[today++];
          }
          e1 = tempReal / optInTimePeriod;
          /* Initialize e2 */
          tempReal = e1;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             tempReal += e1;
          }
          e2 = tempReal / optInTimePeriod;
          /* Initialize e3 */
          tempReal = e2;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             tempReal += e2;
          }
          e3 = tempReal / optInTimePeriod;
          /* Initialize e4 */
          tempReal = e3;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             tempReal += e3;
          }
          e4 = tempReal / optInTimePeriod;
          /* Initialize e5 */
          tempReal = e4;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             tempReal += e4;
          }
          e5 = tempReal / optInTimePeriod;
          /* Initialize e6 */
          tempReal = e5;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             tempReal += e5;
          }
          e6 = tempReal / optInTimePeriod;
          /* Skip the unstable period */
          while( today <= startIdx ) {
             /* Do the calculation but do not write the output */
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
          }
          /* Calculate the constants */
          tempReal = optInVFactor * optInVFactor;
          c1 = 0 - tempReal * optInVFactor;
          c2 = 3.0 * (tempReal - c1);
          c3 = (0 - 6.0) * tempReal - 3.0 * (optInVFactor - c1);
          c4 = 1.0 + 3.0 * optInVFactor - c1 + 3.0 * tempReal;
          /* Write the first output */
          outIdx = 0;
          outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          /* Calculate and output the remaining of the range. */
          while( today <= endIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
             outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          }
          /* Indicates to the caller the number of output
           * successfully calculated.
           */
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode t3Unguarded( int startIdx,
                                   int endIdx,
                                   double inReal[],
                                   int optInTimePeriod,
                                   double optInVFactor,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int lookbackTotal = 0;
          int today = 0;
          int i = 0;
          double k = 0;
          double one_minus_k = 0;
          double e1 = 0;
          double e2 = 0;
          double e3 = 0;
          double e4 = 0;
          double e5 = 0;
          double e6 = 0;
          double c1 = 0;
          double c2 = 0;
          double c3 = 0;
          double c4 = 0;
          double tempReal = 0;
          lookbackTotal = 6 * (optInTimePeriod - 1) + this.unstablePeriod[FuncUnstId.T3.ordinal()];
          if( startIdx <= lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          k = 2.0 / (optInTimePeriod + 1.0);
          one_minus_k = 1.0 - k;
          tempReal = inReal[today++];
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             tempReal += inReal[today++];
          }
          e1 = tempReal / optInTimePeriod;
          tempReal = e1;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             tempReal += e1;
          }
          e2 = tempReal / optInTimePeriod;
          tempReal = e2;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             tempReal += e2;
          }
          e3 = tempReal / optInTimePeriod;
          tempReal = e3;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             tempReal += e3;
          }
          e4 = tempReal / optInTimePeriod;
          tempReal = e4;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             tempReal += e4;
          }
          e5 = tempReal / optInTimePeriod;
          tempReal = e5;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             tempReal += e5;
          }
          e6 = tempReal / optInTimePeriod;
          while( today <= startIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
          }
          tempReal = optInVFactor * optInVFactor;
          c1 = 0 - tempReal * optInVFactor;
          c2 = 3.0 * (tempReal - c1);
          c3 = (0 - 6.0) * tempReal - 3.0 * (optInVFactor - c1);
          c4 = 1.0 + 3.0 * optInVFactor - c1 + 3.0 * tempReal;
          outIdx = 0;
          outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          while( today <= endIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
             outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode t3( int startIdx,
                          int endIdx,
                          float inReal[],
                          int optInTimePeriod,
                          double optInVFactor,
                          MInteger outBegIdx,
                          MInteger outNBElement,
                          double outReal[] )
       {
          int outIdx = 0;
          int lookbackTotal = 0;
          int today = 0;
          int i = 0;
          double k = 0;
          double one_minus_k = 0;
          double e1 = 0;
          double e2 = 0;
          double e3 = 0;
          double e4 = 0;
          double e5 = 0;
          double e6 = 0;
          double c1 = 0;
          double c2 = 0;
          double c3 = 0;
          double c4 = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInVFactor == -4e37 ) {
             optInVFactor = 7e-1;
          } else if( optInVFactor < 0e0 || optInVFactor > 1e0 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = 6 * (optInTimePeriod - 1) + this.unstablePeriod[FuncUnstId.T3.ordinal()];
          if( startIdx <= lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          k = 2.0 / (optInTimePeriod + 1.0);
          one_minus_k = 1.0 - k;
          tempReal = inReal[today++];
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             tempReal += inReal[today++];
          }
          e1 = tempReal / optInTimePeriod;
          tempReal = e1;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             tempReal += e1;
          }
          e2 = tempReal / optInTimePeriod;
          tempReal = e2;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             tempReal += e2;
          }
          e3 = tempReal / optInTimePeriod;
          tempReal = e3;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             tempReal += e3;
          }
          e4 = tempReal / optInTimePeriod;
          tempReal = e4;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             tempReal += e4;
          }
          e5 = tempReal / optInTimePeriod;
          tempReal = e5;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             tempReal += e5;
          }
          e6 = tempReal / optInTimePeriod;
          while( today <= startIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
          }
          tempReal = optInVFactor * optInVFactor;
          c1 = 0 - tempReal * optInVFactor;
          c2 = 3.0 * (tempReal - c1);
          c3 = (0 - 6.0) * tempReal - 3.0 * (optInVFactor - c1);
          c4 = 1.0 + 3.0 * optInVFactor - c1 + 3.0 * tempReal;
          outIdx = 0;
          outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          while( today <= endIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
             outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode t3Unguarded( int startIdx,
                                   int endIdx,
                                   float inReal[],
                                   int optInTimePeriod,
                                   double optInVFactor,
                                   MInteger outBegIdx,
                                   MInteger outNBElement,
                                   double outReal[] )
       {
          int outIdx = 0;
          int lookbackTotal = 0;
          int today = 0;
          int i = 0;
          double k = 0;
          double one_minus_k = 0;
          double e1 = 0;
          double e2 = 0;
          double e3 = 0;
          double e4 = 0;
          double e5 = 0;
          double e6 = 0;
          double c1 = 0;
          double c2 = 0;
          double c3 = 0;
          double c4 = 0;
          double tempReal = 0;
          lookbackTotal = 6 * (optInTimePeriod - 1) + this.unstablePeriod[FuncUnstId.T3.ordinal()];
          if( startIdx <= lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             today = startIdx;
             while( today <= endIdx ) {
                outReal[outIdx++] = inReal[today++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          today = startIdx - lookbackTotal;
          k = 2.0 / (optInTimePeriod + 1.0);
          one_minus_k = 1.0 - k;
          tempReal = inReal[today++];
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             tempReal += inReal[today++];
          }
          e1 = tempReal / optInTimePeriod;
          tempReal = e1;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             tempReal += e1;
          }
          e2 = tempReal / optInTimePeriod;
          tempReal = e2;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             tempReal += e2;
          }
          e3 = tempReal / optInTimePeriod;
          tempReal = e3;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             tempReal += e3;
          }
          e4 = tempReal / optInTimePeriod;
          tempReal = e4;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             tempReal += e4;
          }
          e5 = tempReal / optInTimePeriod;
          tempReal = e5;
          for( i = optInTimePeriod - 1; i > 0; i -= 1 ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             tempReal += e5;
          }
          e6 = tempReal / optInTimePeriod;
          while( today <= startIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
          }
          tempReal = optInVFactor * optInVFactor;
          c1 = 0 - tempReal * optInVFactor;
          c2 = 3.0 * (tempReal - c1);
          c3 = (0 - 6.0) * tempReal - 3.0 * (optInVFactor - c1);
          c4 = 1.0 + 3.0 * optInVFactor - c1 + 3.0 * tempReal;
          outIdx = 0;
          outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          while( today <= endIdx ) {
             e1 = k * inReal[today++] + one_minus_k * e1;
             e2 = k * e1 + one_minus_k * e2;
             e3 = k * e2 + one_minus_k * e3;
             e4 = k * e3 + one_minus_k * e4;
             e5 = k * e4 + one_minus_k * e5;
             e6 = k * e5 + one_minus_k * e6;
             outReal[outIdx++] = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int tanLookback( )
       {
          return 0 ;

       }
       public RetCode tan( int startIdx,
                           int endIdx,
                           double inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tanUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tan( int startIdx,
                           int endIdx,
                           float inReal[],
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tanUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tan(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  090807 MF     Initial Version
     */

       public int tanhLookback( )
       {
          return 0 ;

       }
       public RetCode tanh( int startIdx,
                            int endIdx,
                            double inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tanh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tanhUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tanh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tanh( int startIdx,
                            int endIdx,
                            float inReal[],
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tanh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode tanhUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          for( i = startIdx, outIdx = 0; i <= endIdx; i += 1, outIdx += 1 ) {
             outReal[outIdx] = Math.tanh(inReal[i]);
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY     Description
     *  -------------------------------------------------------------------
     *  112400 MF     Template creation.
     *  052603 MF     Adapt code to compile with .NET Managed C++
     *  070226 MF,CC  Allow period of 1: output is an exact copy of the
     *                input, consistent with TA_MA (issues #48, #59). The
     *                natural math (3*e1 - 3*e2 + e3 with e1=e2=e3=x) is
     *                exact on x86 but not under FMA contraction (ARM64
     *                clang leaves ~1e-14 residue), so the copy is explicit.
     */

       public int temaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          int retValue;
          /* Get lookack for one EMA. */
          retValue = emaLookback(optInTimePeriod);
          return retValue * 3 ;

       }
       public RetCode tema( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          MInteger thirdEMABegIdx = new MInteger();
          MInteger thirdEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          int firstEMAIdx = 0;
          int secondEMAIdx = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* For an explanation of this function, please read:
           *
           * Stocks & Commodities V. 12:1 (11-19):
           *   Smoothing Data With Faster Moving Averages
           * Stocks & Commodities V. 12:2 (72-80):
           *   Smoothing Data With Less Lag
           *
           * Both magazine articles written by Patrick G. Mulloy
           *
           * Essentially, a TEMA of time serie 't' is:
           *   EMA1 = EMA(t,period)
           *   EMA2 = EMA(EMA(t,period),period)
           *   EMA3 = EMA(EMA(EMA(t,period),period))
           *   TEMA = 3*EMA1 - 3*EMA2 + EMA3
           *
           * TEMA offers a moving average with less lags then the
           * traditional EMA.
           *
           * Do not confuse a TEMA with EMA3. Both are called "Triple EMA"
           * in the litterature.
           *
           * DEMA is very similar (and from the same author).
           */
          /* Will change only on success. */
          outNBElement.value = 0;
          outBegIdx.value = 0;
          /* Adjust startIdx to account for the lookback period. */
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 3;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          /* No smoothing at period of 1: the output is a copy of the input
           * (same convention as TA_MA for every MAType). Explicit because the
           * 3*e1 - 3*e2 + e3 composition cancels exactly only without FMA
           * contraction; ARM64 fused multiply-add leaves ~1e-14 residue.
           */
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             while( startIdx <= endIdx ) {
                outReal[outIdx++] = inReal[startIdx++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          /* Allocate a temporary buffer for the firstEMA. */
          tempInt = lookbackTotal + (endIdx - startIdx) + 1;
          firstEMA = new double[(int)(tempInt * 1)];
          /* Calculate the first EMA */
          retCode = emaUnguarded(startIdx - lookbackEMA * 2, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          /* Verify for failure or if not enough data after
           * calculating the first EMA.
           */
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             return retCode ;
          }
          /* Allocate a temporary buffer for storing the EMA2 */
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          /* Return empty output on failure or if not enough data after
           * calculating the second EMA.
           */
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             return retCode ;
          }
          /* Calculate the EMA3 into the caller provided output. */
          retCode = emaUnguarded(0, secondEMANbElement.value - 1, secondEMA, optInTimePeriod, thirdEMABegIdx, thirdEMANbElement, outReal);
          /* Return empty output on failure or if not enough data after
           * calculating the third EMA.
           */
          if( retCode != RetCode.Success || thirdEMANbElement.value == 0 ) {
             return retCode ;
          }
          /* Indicate where the output starts relative to
           * the caller input.
           */
          firstEMAIdx = thirdEMABegIdx.value + secondEMABegIdx.value;
          secondEMAIdx = thirdEMABegIdx.value;
          outBegIdx.value = firstEMAIdx + firstEMABegIdx.value;
          /* Do the TEMA:
           *  Iterate through the EMA3 (output buffer) and adjust
           *  the value by using the EMA2 and EMA1.
           */
          outIdx = 0;
          while( outIdx < thirdEMANbElement.value ) {
             outReal[outIdx] = outReal[outIdx] + (3.0 * firstEMA[firstEMAIdx++] - 3.0 * secondEMA[secondEMAIdx++]);
             outIdx += 1;
          }
          /* Indicates to the caller the number of output
           * successfully calculated.
           */
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode temaUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          MInteger thirdEMABegIdx = new MInteger();
          MInteger thirdEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          int firstEMAIdx = 0;
          int secondEMAIdx = 0;
          RetCode retCode;
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 3;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             while( startIdx <= endIdx ) {
                outReal[outIdx++] = inReal[startIdx++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          tempInt = lookbackTotal + (endIdx - startIdx) + 1;
          firstEMA = new double[(int)(tempInt * 1)];
          retCode = emaUnguarded(startIdx - lookbackEMA * 2, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             return retCode ;
          }
          retCode = emaUnguarded(0, secondEMANbElement.value - 1, secondEMA, optInTimePeriod, thirdEMABegIdx, thirdEMANbElement, outReal);
          if( retCode != RetCode.Success || thirdEMANbElement.value == 0 ) {
             return retCode ;
          }
          firstEMAIdx = thirdEMABegIdx.value + secondEMABegIdx.value;
          secondEMAIdx = thirdEMABegIdx.value;
          outBegIdx.value = firstEMAIdx + firstEMABegIdx.value;
          outIdx = 0;
          while( outIdx < thirdEMANbElement.value ) {
             outReal[outIdx] = outReal[outIdx] + (3.0 * firstEMA[firstEMAIdx++] - 3.0 * secondEMA[secondEMAIdx++]);
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode tema( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          MInteger thirdEMABegIdx = new MInteger();
          MInteger thirdEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          int firstEMAIdx = 0;
          int secondEMAIdx = 0;
          RetCode retCode;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 3;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             while( startIdx <= endIdx ) {
                outReal[outIdx++] = inReal[startIdx++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          tempInt = lookbackTotal + (endIdx - startIdx) + 1;
          firstEMA = new double[(int)(tempInt * 1)];
          retCode = emaUnguarded(startIdx - lookbackEMA * 2, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             return retCode ;
          }
          retCode = emaUnguarded(0, secondEMANbElement.value - 1, secondEMA, optInTimePeriod, thirdEMABegIdx, thirdEMANbElement, outReal);
          if( retCode != RetCode.Success || thirdEMANbElement.value == 0 ) {
             return retCode ;
          }
          firstEMAIdx = thirdEMABegIdx.value + secondEMABegIdx.value;
          secondEMAIdx = thirdEMABegIdx.value;
          outBegIdx.value = firstEMAIdx + firstEMABegIdx.value;
          outIdx = 0;
          while( outIdx < thirdEMANbElement.value ) {
             outReal[outIdx] = outReal[outIdx] + (3.0 * firstEMA[firstEMAIdx++] - 3.0 * secondEMA[secondEMAIdx++]);
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode temaUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] firstEMA;
          double[] secondEMA;
          MInteger firstEMABegIdx = new MInteger();
          MInteger firstEMANbElement = new MInteger();
          MInteger secondEMABegIdx = new MInteger();
          MInteger secondEMANbElement = new MInteger();
          MInteger thirdEMABegIdx = new MInteger();
          MInteger thirdEMANbElement = new MInteger();
          int tempInt = 0;
          int outIdx = 0;
          int lookbackTotal = 0;
          int lookbackEMA = 0;
          int firstEMAIdx = 0;
          int secondEMAIdx = 0;
          RetCode retCode;
          outNBElement.value = 0;
          outBegIdx.value = 0;
          lookbackEMA = emaLookback(optInTimePeriod);
          lookbackTotal = lookbackEMA * 3;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outIdx = 0;
             while( startIdx <= endIdx ) {
                outReal[outIdx++] = inReal[startIdx++];
             }
             outNBElement.value = outIdx;
             return RetCode.Success ;
          }
          tempInt = lookbackTotal + (endIdx - startIdx) + 1;
          firstEMA = new double[(int)(tempInt * 1)];
          retCode = emaUnguarded(startIdx - lookbackEMA * 2, endIdx, inReal, optInTimePeriod, firstEMABegIdx, firstEMANbElement, firstEMA);
          if( retCode != RetCode.Success || firstEMANbElement.value == 0 ) {
             return retCode ;
          }
          secondEMA = new double[(int)(firstEMANbElement.value * 1)];
          retCode = emaUnguarded(0, firstEMANbElement.value - 1, firstEMA, optInTimePeriod, secondEMABegIdx, secondEMANbElement, secondEMA);
          if( retCode != RetCode.Success || secondEMANbElement.value == 0 ) {
             return retCode ;
          }
          retCode = emaUnguarded(0, secondEMANbElement.value - 1, secondEMA, optInTimePeriod, thirdEMABegIdx, thirdEMANbElement, outReal);
          if( retCode != RetCode.Success || thirdEMANbElement.value == 0 ) {
             return retCode ;
          }
          firstEMAIdx = thirdEMABegIdx.value + secondEMABegIdx.value;
          secondEMAIdx = thirdEMABegIdx.value;
          outBegIdx.value = firstEMAIdx + firstEMABegIdx.value;
          outIdx = 0;
          while( outIdx < thirdEMANbElement.value ) {
             outReal[outIdx] = outReal[outIdx] + (3.0 * firstEMA[firstEMAIdx++] - 3.0 * secondEMA[secondEMAIdx++]);
             outIdx += 1;
          }
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int trueRangeLookback( )
       {
          return 1 ;

       }
       public RetCode trueRange( int startIdx,
                                 int endIdx,
                                 double inHigh[],
                                 double inLow[],
                                 double inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          double val2 = 0;
          double val3 = 0;
          double greatest = 0;
          double tempCY = 0;
          double tempLT = 0;
          double tempHT = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* True Range is the greatest of the following:
           *
           *  val1 = distance from today's high to today's low.
           *  val2 = distance from yesterday's close to today's high.
           *  val3 = distance from yesterday's close to today's low.
           *
           * Some books and software makes the first TR value to be
           * the (high - low) of the first bar. This function instead
           * ignore the first price bar, and only output starting at the
           * second price bar are valid. This is done for avoiding
           * inconsistency.
           */
          /* Move up the start index if there is not
           * enough initial data.
           * Always one price bar gets consumed.
           */
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          while( today <= endIdx ) {
             /* Find the greatest of the 3 values. */
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             greatest = tempHT - tempLT;
             /* val1 */
             val2 = Math.abs(tempCY - tempHT);
             if( val2 > greatest ) {
                greatest = val2;
             }
             val3 = Math.abs(tempCY - tempLT);
             if( val3 > greatest ) {
                greatest = val3;
             }
             outReal[outIdx++] = greatest;
             today += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trueRangeUnguarded( int startIdx,
                                          int endIdx,
                                          double inHigh[],
                                          double inLow[],
                                          double inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          double val2 = 0;
          double val3 = 0;
          double greatest = 0;
          double tempCY = 0;
          double tempLT = 0;
          double tempHT = 0;
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             greatest = tempHT - tempLT;
             val2 = Math.abs(tempCY - tempHT);
             if( val2 > greatest ) {
                greatest = val2;
             }
             val3 = Math.abs(tempCY - tempLT);
             if( val3 > greatest ) {
                greatest = val3;
             }
             outReal[outIdx++] = greatest;
             today += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trueRange( int startIdx,
                                 int endIdx,
                                 float inHigh[],
                                 float inLow[],
                                 float inClose[],
                                 MInteger outBegIdx,
                                 MInteger outNBElement,
                                 double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          double val2 = 0;
          double val3 = 0;
          double greatest = 0;
          double tempCY = 0;
          double tempLT = 0;
          double tempHT = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             greatest = tempHT - tempLT;
             val2 = Math.abs(tempCY - tempHT);
             if( val2 > greatest ) {
                greatest = val2;
             }
             val3 = Math.abs(tempCY - tempLT);
             if( val3 > greatest ) {
                greatest = val3;
             }
             outReal[outIdx++] = greatest;
             today += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trueRangeUnguarded( int startIdx,
                                          int endIdx,
                                          float inHigh[],
                                          float inLow[],
                                          float inClose[],
                                          MInteger outBegIdx,
                                          MInteger outNBElement,
                                          double outReal[] )
       {
          int today = 0;
          int outIdx = 0;
          double val2 = 0;
          double val3 = 0;
          double greatest = 0;
          double tempCY = 0;
          double tempLT = 0;
          double tempHT = 0;
          if( startIdx < 1 ) {
             startIdx = 1;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             greatest = tempHT - tempLT;
             val2 = Math.abs(tempCY - tempHT);
             if( val2 > greatest ) {
                greatest = val2;
             }
             val3 = Math.abs(tempCY - tempLT);
             if( val3 > greatest ) {
                greatest = val3;
             }
             outReal[outIdx++] = greatest;
             today += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  CR       Chris (crokusek@hotmail.com)
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010503 MF   Initial Coding
     *  031703 MF   Fix #701060. Correct logic when using a range with
     *              startIdx/endIdx. Thanks to Chris for reporting this.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int trimaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode trima( int startIdx,
                             int endIdx,
                             double inReal[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int lookbackTotal = 0;
          double numerator = 0;
          double numeratorSub = 0;
          double numeratorAdd = 0;
          int i = 0;
          int outIdx = 0;
          int todayIdx = 0;
          int trailingIdx = 0;
          int middleIdx = 0;
          double factor = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          lookbackTotal = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* TRIMA Description
           * =================
           * The triangular MA is a weighted moving average. Instead of the
           * TA_WMA who put more weigth on the latest price bar, the triangular
           * put more weigth on the data in the middle of the specified period.
           *
           * Examples:
           *   For TimeSerie={a,b,c,d,e,f...} ('a' is the older price)
           *
           *   1st value for TRIMA 4-Period is:  ((1*a)+(2*b)+(2*c)+(1*d)) / 6
           *   2nd value for TRIMA 4-Period is:  ((1*b)+(2*c)+(2*d)+(1*e)) / 6
           *
           *   1st value for TRIMA 5-Period is:  ((1*a)+(2*b)+(3*c)+(2*d)+(1*e)) / 9
           *   2nd value for TRIMA 5-Period is:  ((1*b)+(2*c)+(3*d)+(2*e)+(1*f)) / 9
           *
           * Generally Accepted Implementation
           * ==================================
           * Using algebra, it can be demonstrated that the TRIMA is equivalent to
           * doing a SMA of a SMA. The following explain the rules:
           *
           *  (1) When the period is even, TRIMA(x,period)=SMA(SMA(x,period/2),(period/2)+1)
           *  (2) When the period is odd,  TRIMA(x,period)=SMA(SMA(x,(period+1)/2),(period+1)/2)
           *
           * In other word:
           *  (1) A period of 4 becomes TRIMA(x,4) = SMA( SMA( x, 2), 3 )
           *  (2) A period of 5 becomes TRIMA(x,5) = SMA( SMA( x, 3), 3 )
           *
           * The SMA of a SMA is the algorithm generaly found in books.
           *
           * Tradestation Implementation
           * ===========================
           * Tradestation deviate from the generally accepted implementation by
           * making the TRIMA to be as follow:
           *    TRIMA(x,period) = SMA( SMA( x, (int)(period/2)+1), (int)(period/2)+1 );
           * This formula is done regardless if the period is even or odd.
           *
           * In other word:
           *  (1) A period of 4 becomes TRIMA(x,4) = SMA( SMA( x, 3), 3 )
           *  (2) A period of 5 becomes TRIMA(x,5) = SMA( SMA( x, 3), 3 )
           *  (3) A period of 6 becomes TRIMA(x,5) = SMA( SMA( x, 4), 4 )
           *  (4) A period of 7 becomes TRIMA(x,5) = SMA( SMA( x, 4), 4 )
           *
           * It is not clear to me if the Tradestation approach is a bug or a deliberate
           * decision to do things differently.
           *
           * Metastock Implementation
           * ========================
           * Output is the same as the generally accepted implementation.
           *
           * TA-Lib Implementation
           * =====================
           * Output is also the same as the generally accepted implementation.
           *
           * For speed optimization and avoid memory allocation, TA-Lib use
           * a better algorithm than the usual SMA of a SMA.
           *
           * The calculation from one TRIMA value to the next is done by doing 4
           * little adjustment (the following show a TRIMA 4-period):
           *
           * TRIMA at time 'd': ((1*a)+(2*b)+(2*c)+(1*d)) / 6
           * TRIMA at time 'e': ((1*b)+(2*c)+(2*d)+(1*e)) / 6
           *
           * To go from TRIMA 'd' to 'e', the following is done:
           *       1) 'a' and 'b' are substract from the numerator.
           *       2) 'd' is added to the numerator.
           *       3) 'e' is added to the numerator.
           *       4) Calculate TRIMA by doing numerator / 6
           *       5) Repeat sequence for next output
           *
           * These operations are the same steps done by TA-LIB:
           *       1) is done by numeratorSub
           *       2) is done by numeratorAdd.
           *       3) is obtain from the latest input
           *       4) Calculate and write TRIMA in the output
           *       5) Repeat for next output.
           *
           * Of course, numerotrAdd and numeratorSub needs to be
           * adjusted for each iteration.
           *
           * The update of numeratorSub needs values from the input at
           * the trailingIdx and middleIdx position.
           *
           * The update of numeratorAdd needs values from the input at
           * the middleIdx and todayIdx.
           */
          outIdx = 0;
          if( optInTimePeriod % 2 == 1 ) {
             /* Logic for Odd period */
             /* Calculate the factor which is 1 divided by the
              * sumation of the weight.
              *
              * The sum of the weight is calculated as follow:
              *
              * The simple sumation serie 1+2+3... n can be
              * express as n(n+1)/2
              *
              * From this logic, a "triangular" sumation formula
              * can be found depending if the period is odd or even.
              *
              * Odd Period Formula:
              *  period = 5 and with n=(int)(period/2)
              *  the formula for a "triangular" serie is:
              *    1+2+3+2+1 = (n*(n+1))+n+1
              *              = (n+1)*(n+1)
              *              = 3 * 3 = 9
              *
              * Even period Formula:
              *   period = 6 and with n=(int)(period/2)
              *   the formula for a "triangular" serie is:
              *    1+2+3+3+2+1 = n*(n+1)
              *                = 3 * 4 = 12
              */
             /* Note: entirely done with int and becomes double only
              *       on assignement to the factor variable.
              */
             i = optInTimePeriod >> 1;
             factor = (i + 1) * (i + 1);
             factor = 1.0 / factor;
             /* Initialize all the variable before
              * starting to iterate for each output.
              */
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             /* Write the first output */
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             /* Note: The value at the trailingIdx was saved
              *       in tempReal to account for the case where
              *       outReal and inReal are ptr on the same
              *       buffer.
              */
             /* Iterate for remaining output */
             while( todayIdx <= endIdx ) {
                /* Step (1) */
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                /* Step (2) */
                numerator += numeratorAdd;
                numeratorAdd -= tempReal;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                /* Step (3) */
                numerator += tempReal;
                /* Step (4) */
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          } else {
             /* Even logic.
              *
              * Very similar to the odd logic, except:
              *  - calculation of the factor is different.
              *  - the coverage of the numeratorSub and numeratorAdd is
              *    slightly different.
              *  - Adjustment of numeratorAdd is different. See Step (2).
              */
             i = optInTimePeriod >> 1;
             factor = i * (i + 1);
             factor = 1.0 / factor;
             /* Initialize all the variable before
              * starting to iterate for each output.
              */
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i - 1;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             /* Write the first output */
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             /* Note: The value at the trailingIdx was saved
              *       in tempReal to account for the case where
              *       outReal and inReal are ptr on the same
              *       buffer.
              */
             /* Iterate for remaining output */
             while( todayIdx <= endIdx ) {
                /* Step (1) */
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                /* Step (2) */
                numeratorAdd -= tempReal;
                numerator += numeratorAdd;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                /* Step (3) */
                numerator += tempReal;
                /* Step (4) */
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trimaUnguarded( int startIdx,
                                      int endIdx,
                                      double inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int lookbackTotal = 0;
          double numerator = 0;
          double numeratorSub = 0;
          double numeratorAdd = 0;
          int i = 0;
          int outIdx = 0;
          int todayIdx = 0;
          int trailingIdx = 0;
          int middleIdx = 0;
          double factor = 0;
          double tempReal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod % 2 == 1 ) {
             i = optInTimePeriod >> 1;
             factor = (i + 1) * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numerator += numeratorAdd;
                numeratorAdd -= tempReal;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          } else {
             i = optInTimePeriod >> 1;
             factor = i * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i - 1;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numeratorAdd -= tempReal;
                numerator += numeratorAdd;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trima( int startIdx,
                             int endIdx,
                             float inReal[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          int lookbackTotal = 0;
          double numerator = 0;
          double numeratorSub = 0;
          double numeratorAdd = 0;
          int i = 0;
          int outIdx = 0;
          int todayIdx = 0;
          int trailingIdx = 0;
          int middleIdx = 0;
          double factor = 0;
          double tempReal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod % 2 == 1 ) {
             i = optInTimePeriod >> 1;
             factor = (i + 1) * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numerator += numeratorAdd;
                numeratorAdd -= tempReal;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          } else {
             i = optInTimePeriod >> 1;
             factor = i * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i - 1;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numeratorAdd -= tempReal;
                numerator += numeratorAdd;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode trimaUnguarded( int startIdx,
                                      int endIdx,
                                      float inReal[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          int lookbackTotal = 0;
          double numerator = 0;
          double numeratorSub = 0;
          double numeratorAdd = 0;
          int i = 0;
          int outIdx = 0;
          int todayIdx = 0;
          int trailingIdx = 0;
          int middleIdx = 0;
          double factor = 0;
          double tempReal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          if( optInTimePeriod % 2 == 1 ) {
             i = optInTimePeriod >> 1;
             factor = (i + 1) * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numerator += numeratorAdd;
                numeratorAdd -= tempReal;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          } else {
             i = optInTimePeriod >> 1;
             factor = i * (i + 1);
             factor = 1.0 / factor;
             trailingIdx = startIdx - lookbackTotal;
             middleIdx = trailingIdx + i - 1;
             todayIdx = middleIdx + i;
             numerator = 0.0;
             numeratorSub = 0.0;
             for( i = middleIdx; i >= trailingIdx; i -= 1 ) {
                tempReal = inReal[i];
                numeratorSub += tempReal;
                numerator += numeratorSub;
             }
             numeratorAdd = 0.0;
             middleIdx += 1;
             for( i = middleIdx; i <= todayIdx; i += 1 ) {
                tempReal = inReal[i];
                numeratorAdd += tempReal;
                numerator += numeratorAdd;
             }
             outIdx = 0;
             tempReal = inReal[trailingIdx++];
             outReal[outIdx++] = numerator * factor;
             todayIdx += 1;
             while( todayIdx <= endIdx ) {
                numerator -= numeratorSub;
                numeratorSub -= tempReal;
                tempReal = inReal[middleIdx++];
                numeratorSub += tempReal;
                numeratorAdd -= tempReal;
                numerator += numeratorAdd;
                tempReal = inReal[todayIdx++];
                numeratorAdd += tempReal;
                numerator += tempReal;
                tempReal = inReal[trailingIdx++];
                outReal[outIdx++] = numerator * factor;
             }
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  AA       Andrew Atkinson
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  020605 AA   Fix #1117656. NULL pointer assignement.
     */

       public int trixLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          int emaLookback;
          emaLookback = emaLookback(optInTimePeriod);
          return emaLookback * 3 + rocRLookback(1) ;

       }
       public RetCode trix( int startIdx,
                            int endIdx,
                            double inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] tempBuffer;
          MInteger nbElement = new MInteger();
          MInteger begIdx = new MInteger();
          int totalLookback = 0;
          int emaLookback = 0;
          int rocLookback = 0;
          RetCode retCode;
          int nbElementToOutput = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Adjust the startIdx to account for the lookback. */
          emaLookback = emaLookback(optInTimePeriod);
          rocLookback = rocRLookback(1);
          totalLookback = emaLookback * 3 + rocLookback;
          if( startIdx < totalLookback ) {
             startIdx = totalLookback;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          nbElementToOutput = endIdx - startIdx + 1 + totalLookback;
          /* Allocate a temporary buffer for performing
           * the calculation.
           */
          tempBuffer = new double[(int)(nbElementToOutput * 1)];
          /* Calculate the first EMA */
          retCode = emaUnguarded(startIdx - totalLookback, endIdx, inReal, optInTimePeriod, begIdx, nbElement, tempBuffer);
          /* Verify for failure or if not enough data after
           * calculating the EMA.
           */
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= 1;
          /* Make this variable zero base from now on. */
          /* Calculate the second EMA */
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          /* Verify for failure or if not enough data after
           * calculating the EMA.
           */
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          /* Calculate the third EMA */
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          /* Verify for failure or if not enough data after
           * calculating the EMA.
           */
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          /* Calculate the 1-day Rate-Of-Change */
          nbElementToOutput -= emaLookback;
          retCode = rocUnguarded(0, nbElementToOutput, tempBuffer, 1, begIdx, outNBElement, outReal);
          /* Verify for failure or if not enough data after
           * calculating the rate-of-change.
           */
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode trixUnguarded( int startIdx,
                                     int endIdx,
                                     double inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] tempBuffer;
          MInteger nbElement = new MInteger();
          MInteger begIdx = new MInteger();
          int totalLookback = 0;
          int emaLookback = 0;
          int rocLookback = 0;
          RetCode retCode;
          int nbElementToOutput = 0;
          emaLookback = emaLookback(optInTimePeriod);
          rocLookback = rocRLookback(1);
          totalLookback = emaLookback * 3 + rocLookback;
          if( startIdx < totalLookback ) {
             startIdx = totalLookback;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          nbElementToOutput = endIdx - startIdx + 1 + totalLookback;
          tempBuffer = new double[(int)(nbElementToOutput * 1)];
          retCode = emaUnguarded(startIdx - totalLookback, endIdx, inReal, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= 1;
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = rocUnguarded(0, nbElementToOutput, tempBuffer, 1, begIdx, outNBElement, outReal);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode trix( int startIdx,
                            int endIdx,
                            float inReal[],
                            int optInTimePeriod,
                            MInteger outBegIdx,
                            MInteger outNBElement,
                            double outReal[] )
       {
          double[] tempBuffer;
          MInteger nbElement = new MInteger();
          MInteger begIdx = new MInteger();
          int totalLookback = 0;
          int emaLookback = 0;
          int rocLookback = 0;
          RetCode retCode;
          int nbElementToOutput = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          emaLookback = emaLookback(optInTimePeriod);
          rocLookback = rocRLookback(1);
          totalLookback = emaLookback * 3 + rocLookback;
          if( startIdx < totalLookback ) {
             startIdx = totalLookback;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          nbElementToOutput = endIdx - startIdx + 1 + totalLookback;
          tempBuffer = new double[(int)(nbElementToOutput * 1)];
          retCode = emaUnguarded(startIdx - totalLookback, endIdx, inReal, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= 1;
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = rocUnguarded(0, nbElementToOutput, tempBuffer, 1, begIdx, outNBElement, outReal);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
       public RetCode trixUnguarded( int startIdx,
                                     int endIdx,
                                     float inReal[],
                                     int optInTimePeriod,
                                     MInteger outBegIdx,
                                     MInteger outNBElement,
                                     double outReal[] )
       {
          double[] tempBuffer;
          MInteger nbElement = new MInteger();
          MInteger begIdx = new MInteger();
          int totalLookback = 0;
          int emaLookback = 0;
          int rocLookback = 0;
          RetCode retCode;
          int nbElementToOutput = 0;
          emaLookback = emaLookback(optInTimePeriod);
          rocLookback = rocRLookback(1);
          totalLookback = emaLookback * 3 + rocLookback;
          if( startIdx < totalLookback ) {
             startIdx = totalLookback;
          }
          if( startIdx > endIdx ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return RetCode.Success ;
          }
          outBegIdx.value = startIdx;
          nbElementToOutput = endIdx - startIdx + 1 + totalLookback;
          tempBuffer = new double[(int)(nbElementToOutput * 1)];
          retCode = emaUnguarded(startIdx - totalLookback, endIdx, inReal, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= 1;
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = emaUnguarded(0, nbElementToOutput, tempBuffer, optInTimePeriod, begIdx, nbElement, tempBuffer);
          if( retCode != RetCode.Success || nbElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          nbElementToOutput -= emaLookback;
          retCode = rocUnguarded(0, nbElementToOutput, tempBuffer, 1, begIdx, outNBElement, outReal);
          if( retCode != RetCode.Success || (int)outNBElement.value == 0 ) {
             outNBElement.value = 0;
             outBegIdx.value = 0;
             return retCode ;
          }
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  090103 MF   Initial coding re-using the existing TA_LinearReg
     */

       public int tsfLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode tsf( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Linear Regression is a concept also known as the
           * "least squares method" or "best fit." Linear
           * Regression attempts to fit a straight line between
           * several data points in such a way that distance
           * between each data point and the line is minimized.
           *
           * For each point, a straight line over the specified
           * previous bar period is determined in terms
           * of y = b + m*x:
           *
           * TA_LINEARREG          : Returns b+m*(period-1)
           * TA_LINEARREG_SLOPE    : Returns 'm'
           * TA_LINEARREG_ANGLE    : Returns 'm' in degree.
           * TA_LINEARREG_INTERCEPT: Returns 'b'
           * TA_TSF                : Returns b+m*(period)
           */
          /* Adjust startIdx to account for the lookback period. */
          lookbackTotal = tsfLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          /* Index into the output. */
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode tsfUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = tsfLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode tsf( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = tsfLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode tsfUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int outIdx = 0;
          int today = 0;
          int lookbackTotal = 0;
          double SumX = 0;
          double SumXY = 0;
          double SumY = 0;
          double SumXSqr = 0;
          double Divisor = 0;
          double m = 0;
          double b = 0;
          int i = 0;
          double tempValue1 = 0;
          lookbackTotal = tsfLookback(optInTimePeriod);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          outIdx = 0;
          today = startIdx;
          SumX = optInTimePeriod * (optInTimePeriod - 1) * 0.5;
          SumXSqr = optInTimePeriod * (optInTimePeriod - 1) * (2 * optInTimePeriod - 1) / 6;
          Divisor = SumX * SumX - optInTimePeriod * SumXSqr;
          while( today <= endIdx ) {
             SumXY = 0;
             SumY = 0;
             for( i = optInTimePeriod; i-- != 0;  ) {
                tempValue1 = inReal[today - i];
                SumY += tempValue1;
                SumXY += (double)i * tempValue1;
             }
             m = (optInTimePeriod * SumXY - SumX * SumY) / Divisor;
             b = (SumY - m * SumX) / (double)optInTimePeriod;
             outReal[outIdx++] = b + m * (double)optInTimePeriod;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  112605 MF   Fix outBegIdx when startIdx != 0
     */

       public int typPriceLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode typPrice( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                double inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Typical price = (High + Low + Close ) / 3 */
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode typPriceUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode typPrice( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                float inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode typPriceUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  DM       Drew McCormack (http://www.trade-strategist.com)
     *  MF       Mario Fortier
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  281206 DM   Initial Implementation
     *  010606 MF   Abstract local arrays. Detect divide by zero.
     */

       public int ultOscLookback( int optInTimePeriod1, int optInTimePeriod2, int optInTimePeriod3 )
       {
          if( optInTimePeriod1 == Integer.MIN_VALUE ) {
             optInTimePeriod1 = 7;
          } else if( optInTimePeriod1 < 1 || optInTimePeriod1 > 100000 ) {
             return -1;
          }
          if( optInTimePeriod2 == Integer.MIN_VALUE ) {
             optInTimePeriod2 = 14;
          } else if( optInTimePeriod2 < 1 || optInTimePeriod2 > 100000 ) {
             return -1;
          }
          if( optInTimePeriod3 == Integer.MIN_VALUE ) {
             optInTimePeriod3 = 28;
          } else if( optInTimePeriod3 < 1 || optInTimePeriod3 > 100000 ) {
             return -1;
          }
          int maxPeriod;
          /* Lookback for the Ultimate Oscillator is the lookback of the SMA with the longest
           * time period, plus 1 for the True Range.
           */
          maxPeriod = Math.max(Math.max(optInTimePeriod1, optInTimePeriod2), optInTimePeriod3);
          return smaLookback(maxPeriod) + 1 ;

       }
       public RetCode ultOsc( int startIdx,
                              int endIdx,
                              double inHigh[],
                              double inLow[],
                              double inClose[],
                              int optInTimePeriod1,
                              int optInTimePeriod2,
                              int optInTimePeriod3,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          double a1Total = 0;
          double a2Total = 0;
          double a3Total = 0;
          double b1Total = 0;
          double b2Total = 0;
          double b3Total = 0;
          double trueLow = 0;
          double trueRange = 0;
          double closeMinusTrueLow = 0;
          double tempDouble = 0;
          double output = 0;
          double tempHT = 0;
          double tempLT = 0;
          double tempCY = 0;
          int lookbackTotal = 0;
          int longestPeriod = 0;
          int longestIndex = 0;
          int i = 0;
          int j = 0;
          int today = 0;
          int outIdx = 0;
          int trailingIdx1 = 0;
          int trailingIdx2 = 0;
          int trailingIdx3 = 0;
          int[] usedFlag = new int[3];
          int[] periods = new int[3];
          int[] sortedPeriods = new int[3];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod1 == Integer.MIN_VALUE ) {
             optInTimePeriod1 = 7;
          } else if( optInTimePeriod1 < 1 || optInTimePeriod1 > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod2 == Integer.MIN_VALUE ) {
             optInTimePeriod2 = 14;
          } else if( optInTimePeriod2 < 1 || optInTimePeriod2 > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod3 == Integer.MIN_VALUE ) {
             optInTimePeriod3 = 28;
          } else if( optInTimePeriod3 < 1 || optInTimePeriod3 > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          /* Ensure that the time periods are ordered from shortest to longest.
           * Sort.
           */
          periods[0] = optInTimePeriod1;
          periods[1] = optInTimePeriod2;
          periods[2] = optInTimePeriod3;
          usedFlag[0] = 0;
          usedFlag[1] = 0;
          usedFlag[2] = 0;
          for( i = 0; i < 3; i += 1 ) {
             longestPeriod = 0;
             longestIndex = 0;
             for( j = 0; j < 3; j += 1 ) {
                if( usedFlag[j] == 0 && periods[j] > longestPeriod ) {
                   longestPeriod = periods[j];
                   longestIndex = j;
                }
             }
             usedFlag[longestIndex] = 1;
             sortedPeriods[i] = longestPeriod;
          }
          optInTimePeriod1 = sortedPeriods[2];
          optInTimePeriod2 = sortedPeriods[1];
          optInTimePeriod3 = sortedPeriods[0];
          /* Adjust startIdx for lookback period. */
          lookbackTotal = ultOscLookback(optInTimePeriod1, optInTimePeriod2, optInTimePeriod3);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          /* Prime running totals used in moving averages */
          a1Total = 0;
          b1Total = 0;
          for( i = startIdx - optInTimePeriod1 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             b1Total += trueRange;
          }
          a2Total = 0;
          b2Total = 0;
          for( i = startIdx - optInTimePeriod2 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total += closeMinusTrueLow;
             b2Total += trueRange;
          }
          a3Total = 0;
          b3Total = 0;
          for( i = startIdx - optInTimePeriod3 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total += closeMinusTrueLow;
             b3Total += trueRange;
          }
          /* Calculate oscillator */
          today = startIdx;
          outIdx = 0;
          trailingIdx1 = today - optInTimePeriod1 + 1;
          trailingIdx2 = today - optInTimePeriod2 + 1;
          trailingIdx3 = today - optInTimePeriod3 + 1;
          while( today <= endIdx ) {
             /* Add on today's terms */
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[today] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             a2Total += closeMinusTrueLow;
             a3Total += closeMinusTrueLow;
             b1Total += trueRange;
             b2Total += trueRange;
             b3Total += trueRange;
             /* Calculate the oscillator value for today */
             output = 0.0;
             if( !((-0.00000000000001 < b1Total) && (b1Total < 0.00000000000001)) ) {
                output += 4.0 * (a1Total / b1Total);
             }
             if( !((-0.00000000000001 < b2Total) && (b2Total < 0.00000000000001)) ) {
                output += 2.0 * (a2Total / b2Total);
             }
             if( !((-0.00000000000001 < b3Total) && (b3Total < 0.00000000000001)) ) {
                output += a3Total / b3Total;
             }
             /* Remove the trailing terms to prepare for next day */
             tempLT = inLow[trailingIdx1];
             tempHT = inHigh[trailingIdx1];
             tempCY = inClose[trailingIdx1 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx1] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total -= closeMinusTrueLow;
             b1Total -= trueRange;
             tempLT = inLow[trailingIdx2];
             tempHT = inHigh[trailingIdx2];
             tempCY = inClose[trailingIdx2 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx2] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total -= closeMinusTrueLow;
             b2Total -= trueRange;
             tempLT = inLow[trailingIdx3];
             tempHT = inHigh[trailingIdx3];
             tempCY = inClose[trailingIdx3 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx3] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total -= closeMinusTrueLow;
             b3Total -= trueRange;
             /* Last operation is to write the output. Must
              * be done after the trailing index have all been
              * taken care of because the caller is allowed
              * to have the input array to be also the output
              * array.
              */
             outReal[outIdx] = 100.0 * (output / 7.0);
             /* Increment indexes */
             outIdx += 1;
             today += 1;
             trailingIdx1 += 1;
             trailingIdx2 += 1;
             trailingIdx3 += 1;
          }
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ultOscUnguarded( int startIdx,
                                       int endIdx,
                                       double inHigh[],
                                       double inLow[],
                                       double inClose[],
                                       int optInTimePeriod1,
                                       int optInTimePeriod2,
                                       int optInTimePeriod3,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          double a1Total = 0;
          double a2Total = 0;
          double a3Total = 0;
          double b1Total = 0;
          double b2Total = 0;
          double b3Total = 0;
          double trueLow = 0;
          double trueRange = 0;
          double closeMinusTrueLow = 0;
          double tempDouble = 0;
          double output = 0;
          double tempHT = 0;
          double tempLT = 0;
          double tempCY = 0;
          int lookbackTotal = 0;
          int longestPeriod = 0;
          int longestIndex = 0;
          int i = 0;
          int j = 0;
          int today = 0;
          int outIdx = 0;
          int trailingIdx1 = 0;
          int trailingIdx2 = 0;
          int trailingIdx3 = 0;
          int[] usedFlag = new int[3];
          int[] periods = new int[3];
          int[] sortedPeriods = new int[3];
          outBegIdx.value = 0;
          outNBElement.value = 0;
          periods[0] = optInTimePeriod1;
          periods[1] = optInTimePeriod2;
          periods[2] = optInTimePeriod3;
          usedFlag[0] = 0;
          usedFlag[1] = 0;
          usedFlag[2] = 0;
          for( i = 0; i < 3; i += 1 ) {
             longestPeriod = 0;
             longestIndex = 0;
             for( j = 0; j < 3; j += 1 ) {
                if( usedFlag[j] == 0 && periods[j] > longestPeriod ) {
                   longestPeriod = periods[j];
                   longestIndex = j;
                }
             }
             usedFlag[longestIndex] = 1;
             sortedPeriods[i] = longestPeriod;
          }
          optInTimePeriod1 = sortedPeriods[2];
          optInTimePeriod2 = sortedPeriods[1];
          optInTimePeriod3 = sortedPeriods[0];
          lookbackTotal = ultOscLookback(optInTimePeriod1, optInTimePeriod2, optInTimePeriod3);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          a1Total = 0;
          b1Total = 0;
          for( i = startIdx - optInTimePeriod1 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             b1Total += trueRange;
          }
          a2Total = 0;
          b2Total = 0;
          for( i = startIdx - optInTimePeriod2 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total += closeMinusTrueLow;
             b2Total += trueRange;
          }
          a3Total = 0;
          b3Total = 0;
          for( i = startIdx - optInTimePeriod3 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total += closeMinusTrueLow;
             b3Total += trueRange;
          }
          today = startIdx;
          outIdx = 0;
          trailingIdx1 = today - optInTimePeriod1 + 1;
          trailingIdx2 = today - optInTimePeriod2 + 1;
          trailingIdx3 = today - optInTimePeriod3 + 1;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[today] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             a2Total += closeMinusTrueLow;
             a3Total += closeMinusTrueLow;
             b1Total += trueRange;
             b2Total += trueRange;
             b3Total += trueRange;
             output = 0.0;
             if( !((-0.00000000000001 < b1Total) && (b1Total < 0.00000000000001)) ) {
                output += 4.0 * (a1Total / b1Total);
             }
             if( !((-0.00000000000001 < b2Total) && (b2Total < 0.00000000000001)) ) {
                output += 2.0 * (a2Total / b2Total);
             }
             if( !((-0.00000000000001 < b3Total) && (b3Total < 0.00000000000001)) ) {
                output += a3Total / b3Total;
             }
             tempLT = inLow[trailingIdx1];
             tempHT = inHigh[trailingIdx1];
             tempCY = inClose[trailingIdx1 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx1] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total -= closeMinusTrueLow;
             b1Total -= trueRange;
             tempLT = inLow[trailingIdx2];
             tempHT = inHigh[trailingIdx2];
             tempCY = inClose[trailingIdx2 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx2] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total -= closeMinusTrueLow;
             b2Total -= trueRange;
             tempLT = inLow[trailingIdx3];
             tempHT = inHigh[trailingIdx3];
             tempCY = inClose[trailingIdx3 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx3] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total -= closeMinusTrueLow;
             b3Total -= trueRange;
             outReal[outIdx] = 100.0 * (output / 7.0);
             outIdx += 1;
             today += 1;
             trailingIdx1 += 1;
             trailingIdx2 += 1;
             trailingIdx3 += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ultOsc( int startIdx,
                              int endIdx,
                              float inHigh[],
                              float inLow[],
                              float inClose[],
                              int optInTimePeriod1,
                              int optInTimePeriod2,
                              int optInTimePeriod3,
                              MInteger outBegIdx,
                              MInteger outNBElement,
                              double outReal[] )
       {
          double a1Total = 0;
          double a2Total = 0;
          double a3Total = 0;
          double b1Total = 0;
          double b2Total = 0;
          double b3Total = 0;
          double trueLow = 0;
          double trueRange = 0;
          double closeMinusTrueLow = 0;
          double tempDouble = 0;
          double output = 0;
          double tempHT = 0;
          double tempLT = 0;
          double tempCY = 0;
          int lookbackTotal = 0;
          int longestPeriod = 0;
          int longestIndex = 0;
          int i = 0;
          int j = 0;
          int today = 0;
          int outIdx = 0;
          int trailingIdx1 = 0;
          int trailingIdx2 = 0;
          int trailingIdx3 = 0;
          int[] usedFlag = new int[3];
          int[] periods = new int[3];
          int[] sortedPeriods = new int[3];
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod1 == Integer.MIN_VALUE ) {
             optInTimePeriod1 = 7;
          } else if( optInTimePeriod1 < 1 || optInTimePeriod1 > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod2 == Integer.MIN_VALUE ) {
             optInTimePeriod2 = 14;
          } else if( optInTimePeriod2 < 1 || optInTimePeriod2 > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInTimePeriod3 == Integer.MIN_VALUE ) {
             optInTimePeriod3 = 28;
          } else if( optInTimePeriod3 < 1 || optInTimePeriod3 > 100000 ) {
             return RetCode.BadParam;
          }
          outBegIdx.value = 0;
          outNBElement.value = 0;
          periods[0] = optInTimePeriod1;
          periods[1] = optInTimePeriod2;
          periods[2] = optInTimePeriod3;
          usedFlag[0] = 0;
          usedFlag[1] = 0;
          usedFlag[2] = 0;
          for( i = 0; i < 3; i += 1 ) {
             longestPeriod = 0;
             longestIndex = 0;
             for( j = 0; j < 3; j += 1 ) {
                if( usedFlag[j] == 0 && periods[j] > longestPeriod ) {
                   longestPeriod = periods[j];
                   longestIndex = j;
                }
             }
             usedFlag[longestIndex] = 1;
             sortedPeriods[i] = longestPeriod;
          }
          optInTimePeriod1 = sortedPeriods[2];
          optInTimePeriod2 = sortedPeriods[1];
          optInTimePeriod3 = sortedPeriods[0];
          lookbackTotal = ultOscLookback(optInTimePeriod1, optInTimePeriod2, optInTimePeriod3);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          a1Total = 0;
          b1Total = 0;
          for( i = startIdx - optInTimePeriod1 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             b1Total += trueRange;
          }
          a2Total = 0;
          b2Total = 0;
          for( i = startIdx - optInTimePeriod2 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total += closeMinusTrueLow;
             b2Total += trueRange;
          }
          a3Total = 0;
          b3Total = 0;
          for( i = startIdx - optInTimePeriod3 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total += closeMinusTrueLow;
             b3Total += trueRange;
          }
          today = startIdx;
          outIdx = 0;
          trailingIdx1 = today - optInTimePeriod1 + 1;
          trailingIdx2 = today - optInTimePeriod2 + 1;
          trailingIdx3 = today - optInTimePeriod3 + 1;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[today] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             a2Total += closeMinusTrueLow;
             a3Total += closeMinusTrueLow;
             b1Total += trueRange;
             b2Total += trueRange;
             b3Total += trueRange;
             output = 0.0;
             if( !((-0.00000000000001 < b1Total) && (b1Total < 0.00000000000001)) ) {
                output += 4.0 * (a1Total / b1Total);
             }
             if( !((-0.00000000000001 < b2Total) && (b2Total < 0.00000000000001)) ) {
                output += 2.0 * (a2Total / b2Total);
             }
             if( !((-0.00000000000001 < b3Total) && (b3Total < 0.00000000000001)) ) {
                output += a3Total / b3Total;
             }
             tempLT = inLow[trailingIdx1];
             tempHT = inHigh[trailingIdx1];
             tempCY = inClose[trailingIdx1 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx1] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total -= closeMinusTrueLow;
             b1Total -= trueRange;
             tempLT = inLow[trailingIdx2];
             tempHT = inHigh[trailingIdx2];
             tempCY = inClose[trailingIdx2 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx2] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total -= closeMinusTrueLow;
             b2Total -= trueRange;
             tempLT = inLow[trailingIdx3];
             tempHT = inHigh[trailingIdx3];
             tempCY = inClose[trailingIdx3 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx3] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total -= closeMinusTrueLow;
             b3Total -= trueRange;
             outReal[outIdx] = 100.0 * (output / 7.0);
             outIdx += 1;
             today += 1;
             trailingIdx1 += 1;
             trailingIdx2 += 1;
             trailingIdx3 += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode ultOscUnguarded( int startIdx,
                                       int endIdx,
                                       float inHigh[],
                                       float inLow[],
                                       float inClose[],
                                       int optInTimePeriod1,
                                       int optInTimePeriod2,
                                       int optInTimePeriod3,
                                       MInteger outBegIdx,
                                       MInteger outNBElement,
                                       double outReal[] )
       {
          double a1Total = 0;
          double a2Total = 0;
          double a3Total = 0;
          double b1Total = 0;
          double b2Total = 0;
          double b3Total = 0;
          double trueLow = 0;
          double trueRange = 0;
          double closeMinusTrueLow = 0;
          double tempDouble = 0;
          double output = 0;
          double tempHT = 0;
          double tempLT = 0;
          double tempCY = 0;
          int lookbackTotal = 0;
          int longestPeriod = 0;
          int longestIndex = 0;
          int i = 0;
          int j = 0;
          int today = 0;
          int outIdx = 0;
          int trailingIdx1 = 0;
          int trailingIdx2 = 0;
          int trailingIdx3 = 0;
          int[] usedFlag = new int[3];
          int[] periods = new int[3];
          int[] sortedPeriods = new int[3];
          outBegIdx.value = 0;
          outNBElement.value = 0;
          periods[0] = optInTimePeriod1;
          periods[1] = optInTimePeriod2;
          periods[2] = optInTimePeriod3;
          usedFlag[0] = 0;
          usedFlag[1] = 0;
          usedFlag[2] = 0;
          for( i = 0; i < 3; i += 1 ) {
             longestPeriod = 0;
             longestIndex = 0;
             for( j = 0; j < 3; j += 1 ) {
                if( usedFlag[j] == 0 && periods[j] > longestPeriod ) {
                   longestPeriod = periods[j];
                   longestIndex = j;
                }
             }
             usedFlag[longestIndex] = 1;
             sortedPeriods[i] = longestPeriod;
          }
          optInTimePeriod1 = sortedPeriods[2];
          optInTimePeriod2 = sortedPeriods[1];
          optInTimePeriod3 = sortedPeriods[0];
          lookbackTotal = ultOscLookback(optInTimePeriod1, optInTimePeriod2, optInTimePeriod3);
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             return RetCode.Success ;
          }
          a1Total = 0;
          b1Total = 0;
          for( i = startIdx - optInTimePeriod1 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             b1Total += trueRange;
          }
          a2Total = 0;
          b2Total = 0;
          for( i = startIdx - optInTimePeriod2 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total += closeMinusTrueLow;
             b2Total += trueRange;
          }
          a3Total = 0;
          b3Total = 0;
          for( i = startIdx - optInTimePeriod3 + 1; i < startIdx; i += 1 ) {
             tempLT = inLow[i];
             tempHT = inHigh[i];
             tempCY = inClose[i - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[i] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total += closeMinusTrueLow;
             b3Total += trueRange;
          }
          today = startIdx;
          outIdx = 0;
          trailingIdx1 = today - optInTimePeriod1 + 1;
          trailingIdx2 = today - optInTimePeriod2 + 1;
          trailingIdx3 = today - optInTimePeriod3 + 1;
          while( today <= endIdx ) {
             tempLT = inLow[today];
             tempHT = inHigh[today];
             tempCY = inClose[today - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[today] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total += closeMinusTrueLow;
             a2Total += closeMinusTrueLow;
             a3Total += closeMinusTrueLow;
             b1Total += trueRange;
             b2Total += trueRange;
             b3Total += trueRange;
             output = 0.0;
             if( !((-0.00000000000001 < b1Total) && (b1Total < 0.00000000000001)) ) {
                output += 4.0 * (a1Total / b1Total);
             }
             if( !((-0.00000000000001 < b2Total) && (b2Total < 0.00000000000001)) ) {
                output += 2.0 * (a2Total / b2Total);
             }
             if( !((-0.00000000000001 < b3Total) && (b3Total < 0.00000000000001)) ) {
                output += a3Total / b3Total;
             }
             tempLT = inLow[trailingIdx1];
             tempHT = inHigh[trailingIdx1];
             tempCY = inClose[trailingIdx1 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx1] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a1Total -= closeMinusTrueLow;
             b1Total -= trueRange;
             tempLT = inLow[trailingIdx2];
             tempHT = inHigh[trailingIdx2];
             tempCY = inClose[trailingIdx2 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx2] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a2Total -= closeMinusTrueLow;
             b2Total -= trueRange;
             tempLT = inLow[trailingIdx3];
             tempHT = inHigh[trailingIdx3];
             tempCY = inClose[trailingIdx3 - 1];
             trueLow = Math.min(tempLT, tempCY);
             closeMinusTrueLow = inClose[trailingIdx3] - trueLow;
             trueRange = tempHT - tempLT;
             tempDouble = Math.abs(tempCY - tempHT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             tempDouble = Math.abs(tempCY - tempLT);
             if( tempDouble > trueRange ) {
                trueRange = tempDouble;
             }
             a3Total -= closeMinusTrueLow;
             b3Total -= trueRange;
             outReal[outIdx] = 100.0 * (output / 7.0);
             outIdx += 1;
             today += 1;
             trailingIdx1 += 1;
             trailingIdx2 += 1;
             trailingIdx3 += 1;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *  JV       Jesus Viver <324122@cienz.unizar.es>
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  100502 JV   Speed optimization of the algorithm
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int varianceLookback( int optInTimePeriod, double optInNbDev )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode variance( int startIdx,
                                int endIdx,
                                double inReal[],
                                int optInTimePeriod,
                                double optInNbDev,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double tempReal = 0;
          double periodTotal1 = 0;
          double periodTotal2 = 0;
          double meanValue1 = 0;
          double meanValue2 = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          /* Validate the calculation method type and
           * identify the minimum number of price bar needed
           * to calculate at least one output.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Do the MA calculation using tight loops. */
          /* Add-up the initial periods, except for the last value. */
          periodTotal1 = 0;
          periodTotal2 = 0;
          trailingIdx = startIdx - nbInitialElementNeeded;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                tempReal = inReal[i++];
                periodTotal1 += tempReal;
                tempReal *= tempReal;
                periodTotal2 += tempReal;
             }
          }
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the inReal and
           * outReal to be the same buffer.
           */
          outIdx = 0;
          do {
             tempReal = inReal[i++];
             /* Square and add all the deviation over
              * the same periods.
              */
             periodTotal1 += tempReal;
             tempReal *= tempReal;
             periodTotal2 += tempReal;
             /* Square and add all the deviation over
              * the same period.
              */
             meanValue1 = periodTotal1 / optInTimePeriod;
             meanValue2 = periodTotal2 / optInTimePeriod;
             tempReal = inReal[trailingIdx++];
             periodTotal1 -= tempReal;
             tempReal *= tempReal;
             periodTotal2 -= tempReal;
             outReal[outIdx++] = meanValue2 - meanValue1 * meanValue1;
          } while( i <= endIdx );
          /* All done. Indicate the output limits and return. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode varianceUnguarded( int startIdx,
                                         int endIdx,
                                         double inReal[],
                                         int optInTimePeriod,
                                         double optInNbDev,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double tempReal = 0;
          double periodTotal1 = 0;
          double periodTotal2 = 0;
          double meanValue1 = 0;
          double meanValue2 = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal1 = 0;
          periodTotal2 = 0;
          trailingIdx = startIdx - nbInitialElementNeeded;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                tempReal = inReal[i++];
                periodTotal1 += tempReal;
                tempReal *= tempReal;
                periodTotal2 += tempReal;
             }
          }
          outIdx = 0;
          do {
             tempReal = inReal[i++];
             periodTotal1 += tempReal;
             tempReal *= tempReal;
             periodTotal2 += tempReal;
             meanValue1 = periodTotal1 / optInTimePeriod;
             meanValue2 = periodTotal2 / optInTimePeriod;
             tempReal = inReal[trailingIdx++];
             periodTotal1 -= tempReal;
             tempReal *= tempReal;
             periodTotal2 -= tempReal;
             outReal[outIdx++] = meanValue2 - meanValue1 * meanValue1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode variance( int startIdx,
                                int endIdx,
                                float inReal[],
                                int optInTimePeriod,
                                double optInNbDev,
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          double tempReal = 0;
          double periodTotal1 = 0;
          double periodTotal2 = 0;
          double meanValue1 = 0;
          double meanValue2 = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 5;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          if( optInNbDev == -4e37 ) {
             optInNbDev = 1e0;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal1 = 0;
          periodTotal2 = 0;
          trailingIdx = startIdx - nbInitialElementNeeded;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                tempReal = inReal[i++];
                periodTotal1 += tempReal;
                tempReal *= tempReal;
                periodTotal2 += tempReal;
             }
          }
          outIdx = 0;
          do {
             tempReal = inReal[i++];
             periodTotal1 += tempReal;
             tempReal *= tempReal;
             periodTotal2 += tempReal;
             meanValue1 = periodTotal1 / optInTimePeriod;
             meanValue2 = periodTotal2 / optInTimePeriod;
             tempReal = inReal[trailingIdx++];
             periodTotal1 -= tempReal;
             tempReal *= tempReal;
             periodTotal2 -= tempReal;
             outReal[outIdx++] = meanValue2 - meanValue1 * meanValue1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode varianceUnguarded( int startIdx,
                                         int endIdx,
                                         float inReal[],
                                         int optInTimePeriod,
                                         double optInNbDev,
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          double tempReal = 0;
          double periodTotal1 = 0;
          double periodTotal2 = 0;
          double meanValue1 = 0;
          double meanValue2 = 0;
          int i = 0;
          int outIdx = 0;
          int trailingIdx = 0;
          int nbInitialElementNeeded = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          periodTotal1 = 0;
          periodTotal2 = 0;
          trailingIdx = startIdx - nbInitialElementNeeded;
          i = trailingIdx;
          if( optInTimePeriod > 1 ) {
             while( i < startIdx ) {
                tempReal = inReal[i++];
                periodTotal1 += tempReal;
                tempReal *= tempReal;
                periodTotal2 += tempReal;
             }
          }
          outIdx = 0;
          do {
             tempReal = inReal[i++];
             periodTotal1 += tempReal;
             tempReal *= tempReal;
             periodTotal2 += tempReal;
             meanValue1 = periodTotal1 / optInTimePeriod;
             meanValue2 = periodTotal2 / optInTimePeriod;
             tempReal = inReal[trailingIdx++];
             periodTotal1 -= tempReal;
             tempReal *= tempReal;
             periodTotal2 -= tempReal;
             outReal[outIdx++] = meanValue2 - meanValue1 * meanValue1;
          } while( i <= endIdx );
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     *  112605 MF   Fix outBegIdx when startIdx != 0
     */

       public int wclPriceLookback( )
       {
          /* This function have no lookback needed. */
          return 0 ;

       }
       public RetCode wclPrice( int startIdx,
                                int endIdx,
                                double inHigh[],
                                double inLow[],
                                double inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          /* Weighted Close Price = (High + Low + (Close*2) ) / 4 */
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] * 2.0) / 4.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wclPriceUnguarded( int startIdx,
                                         int endIdx,
                                         double inHigh[],
                                         double inLow[],
                                         double inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] * 2.0) / 4.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wclPrice( int startIdx,
                                int endIdx,
                                float inHigh[],
                                float inLow[],
                                float inClose[],
                                MInteger outBegIdx,
                                MInteger outNBElement,
                                double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] * 2.0) / 4.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wclPriceUnguarded( int startIdx,
                                         int endIdx,
                                         float inHigh[],
                                         float inLow[],
                                         float inClose[],
                                         MInteger outBegIdx,
                                         MInteger outNBElement,
                                         double outReal[] )
       {
          int outIdx = 0;
          int i = 0;
          outIdx = 0;
          for( i = startIdx; i <= endIdx; i += 1 ) {
             outReal[outIdx++] = (inHigh[i] + inLow[i] + inClose[i] * 2.0) / 4.0;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  010802 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int willRLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode willR( int startIdx,
                             int endIdx,
                             double inHigh[],
                             double inLow[],
                             double inClose[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          /* Identify the minimum number of price bar needed
           * to identify at least one output over the specified
           * period.
           */
          nbInitialElementNeeded = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* Initialize 'diff', just to avoid warning. */
          diff = 0.0;
          /* Proceed with the calculation for the requested range.
           * Note that this algorithm allows the input and
           * output to be the same buffer.
           */
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          while( today <= endIdx ) {
             /* Set the lowest low */
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             /* Set the highest high */
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             if( diff != 0.0 ) {
                outReal[outIdx++] = (highest - inClose[today]) / diff;
             } else {
                outReal[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          /* Keep the outBegIdx relative to the
           * caller input before returning.
           */
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode willRUnguarded( int startIdx,
                                      int endIdx,
                                      double inHigh[],
                                      double inLow[],
                                      double inClose[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          diff = 0.0;
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             if( diff != 0.0 ) {
                outReal[outIdx++] = (highest - inClose[today]) / diff;
             } else {
                outReal[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode willR( int startIdx,
                             int endIdx,
                             float inHigh[],
                             float inLow[],
                             float inClose[],
                             int optInTimePeriod,
                             MInteger outBegIdx,
                             MInteger outNBElement,
                             double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 14;
          } else if( optInTimePeriod < 2 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          diff = 0.0;
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             if( diff != 0.0 ) {
                outReal[outIdx++] = (highest - inClose[today]) / diff;
             } else {
                outReal[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
       public RetCode willRUnguarded( int startIdx,
                                      int endIdx,
                                      float inHigh[],
                                      float inLow[],
                                      float inClose[],
                                      int optInTimePeriod,
                                      MInteger outBegIdx,
                                      MInteger outNBElement,
                                      double outReal[] )
       {
          double lowest = 0;
          double highest = 0;
          double tmp = 0;
          double diff = 0;
          int outIdx = 0;
          int nbInitialElementNeeded = 0;
          int trailingIdx = 0;
          int lowestIdx = 0;
          int highestIdx = 0;
          int today = 0;
          int i = 0;
          nbInitialElementNeeded = optInTimePeriod - 1;
          if( startIdx < nbInitialElementNeeded ) {
             startIdx = nbInitialElementNeeded;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          diff = 0.0;
          outIdx = 0;
          today = startIdx;
          trailingIdx = startIdx - nbInitialElementNeeded;
          highestIdx = 0 - 1;
          lowestIdx = highestIdx;
          lowest = 0.0;
          highest = lowest;
          diff = highest;
          while( today <= endIdx ) {
             tmp = inLow[today];
             if( lowestIdx < trailingIdx ) {
                lowestIdx = trailingIdx;
                lowest = inLow[lowestIdx];
                i = lowestIdx;
                while( ++i <= today ) {
                   tmp = inLow[i];
                   if( tmp < lowest ) {
                      lowestIdx = i;
                      lowest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp <= lowest ) {
                lowestIdx = today;
                lowest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             tmp = inHigh[today];
             if( highestIdx < trailingIdx ) {
                highestIdx = trailingIdx;
                highest = inHigh[highestIdx];
                i = highestIdx;
                while( ++i <= today ) {
                   tmp = inHigh[i];
                   if( tmp > highest ) {
                      highestIdx = i;
                      highest = tmp;
                   }
                }
                diff = (highest - lowest) / (0 - 100.0);
             } else if( tmp >= highest ) {
                highestIdx = today;
                highest = tmp;
                diff = (highest - lowest) / (0 - 100.0);
             }
             if( diff != 0.0 ) {
                outReal[outIdx++] = (highest - inClose[today]) / diff;
             } else {
                outReal[outIdx++] = 0.0;
             }
             trailingIdx += 1;
             today += 1;
          }
          outBegIdx.value = startIdx;
          outNBElement.value = outIdx;
          return RetCode.Success ;
       }
    /* List of contributors:
     *
     *  Initial  Name/description
     *  -------------------------------------------------------------------
     *  MF       Mario Fortier
     *
     *
     * Change history:
     *
     *  MMDDYY BY   Description
     *  -------------------------------------------------------------------
     *  112400 MF   Template creation.
     *  052603 MF   Adapt code to compile with .NET Managed C++
     */

       public int wmaLookback( int optInTimePeriod )
       {
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return -1;
          }
          return optInTimePeriod - 1 ;

       }
       public RetCode wma( int startIdx,
                           int endIdx,
                           double inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int i = 0;
          int trailingIdx = 0;
          int divider = 0;
          double periodSum = 0;
          double periodSub = 0;
          double tempReal = 0;
          double trailingValue = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          /* Move up the start index if there is not
           * enough initial data.
           */
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          /* Make sure there is still something to evaluate. */
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          /* To make the rest more efficient, handle exception
           * case where the user is asking for a period of '1'.
           * In that case outputs equals inputs for the requested
           * range.
           */
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outNBElement.value = endIdx - startIdx + 1;
             System.arraycopy(inReal, startIdx, outReal, 0, (int)outNBElement.value * 1);
             return RetCode.Success ;
          }
          /* Calculate the divider (always an integer value).
           * By induction: 1+2+3+4+'n' = n(n+1)/2
           * '>>1' is usually faster than '/2' for unsigned.
           */
          divider = optInTimePeriod * (optInTimePeriod + 1) >> 1;
          /* The algo used here use a very basic property of
           * multiplication/addition: (x*2) = x+x
           *
           * As an example, a 3 period weighted can be
           * interpreted in two way:
           *  (x1*1)+(x2*2)+(x3*3)
           *      OR
           *  x1+x2+x2+x3+x3+x3 (this is the periodSum)
           *
           * When you move forward in the time serie
           * you can quickly adjust the periodSum for the
           * period by substracting:
           *   x1+x2+x3 (This is the periodSub)
           * Making the new periodSum equals to:
           *   x2+x3+x3
           *
           * You can then add the new price bar
           * which is x4+x4+x4 giving:
           *   x2+x3+x3+x4+x4+x4
           *
           * At this point one iteration is completed and you can
           * see that we are back to the step 1 of this example.
           *
           * Why making it so un-intuitive? The number of memory
           * access and floating point operations are kept to a
           * minimum with this algo.
           */
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          /* Evaluate the initial periodSum/periodSub and trailingValue. */
          periodSub = (double)0.0;
          periodSum = periodSub;
          inIdx = trailingIdx;
          i = 1;
          while( inIdx < startIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSum += tempReal * i;
             i += 1;
          }
          trailingValue = 0.0;
          /* Tight loop for the requested range. */
          while( inIdx <= endIdx ) {
             /* Add the current price bar to the sum
              * who are carried through the iterations.
              */
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSub -= trailingValue;
             periodSum += tempReal * optInTimePeriod;
             /* Save the trailing value for being substract at
              * the next iteration.
              * (must be saved here just in case outReal and
              *  inReal are the same buffer).
              */
             trailingValue = inReal[trailingIdx++];
             /* Calculate the WMA for this price bar. */
             outReal[outIdx++] = periodSum / divider;
             /* Prepare the periodSum for the next iteration. */
             periodSum -= periodSub;
          }
          /* Set output limits. */
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wmaUnguarded( int startIdx,
                                    int endIdx,
                                    double inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int i = 0;
          int trailingIdx = 0;
          int divider = 0;
          double periodSum = 0;
          double periodSub = 0;
          double tempReal = 0;
          double trailingValue = 0;
          int lookbackTotal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outNBElement.value = endIdx - startIdx + 1;
             System.arraycopy(inReal, startIdx, outReal, 0, (int)outNBElement.value * 1);
             return RetCode.Success ;
          }
          divider = optInTimePeriod * (optInTimePeriod + 1) >> 1;
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          periodSub = (double)0.0;
          periodSum = periodSub;
          inIdx = trailingIdx;
          i = 1;
          while( inIdx < startIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSum += tempReal * i;
             i += 1;
          }
          trailingValue = 0.0;
          while( inIdx <= endIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSub -= trailingValue;
             periodSum += tempReal * optInTimePeriod;
             trailingValue = inReal[trailingIdx++];
             outReal[outIdx++] = periodSum / divider;
             periodSum -= periodSub;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wma( int startIdx,
                           int endIdx,
                           float inReal[],
                           int optInTimePeriod,
                           MInteger outBegIdx,
                           MInteger outNBElement,
                           double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int i = 0;
          int trailingIdx = 0;
          int divider = 0;
          double periodSum = 0;
          double periodSub = 0;
          double tempReal = 0;
          double trailingValue = 0;
          int lookbackTotal = 0;
          if( startIdx < 0 ) {
             return RetCode.OutOfRangeStartIndex ;
          }
          if( (endIdx < 0) || (endIdx < startIdx)) {
             return RetCode.OutOfRangeEndIndex ;
          }
          if( optInTimePeriod == Integer.MIN_VALUE ) {
             optInTimePeriod = 30;
          } else if( optInTimePeriod < 1 || optInTimePeriod > 100000 ) {
             return RetCode.BadParam;
          }
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outNBElement.value = endIdx - startIdx + 1;
             System.arraycopy(inReal, startIdx, outReal, 0, (int)outNBElement.value * 1);
             return RetCode.Success ;
          }
          divider = optInTimePeriod * (optInTimePeriod + 1) >> 1;
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          periodSub = (double)0.0;
          periodSum = periodSub;
          inIdx = trailingIdx;
          i = 1;
          while( inIdx < startIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSum += tempReal * i;
             i += 1;
          }
          trailingValue = 0.0;
          while( inIdx <= endIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSub -= trailingValue;
             periodSum += tempReal * optInTimePeriod;
             trailingValue = inReal[trailingIdx++];
             outReal[outIdx++] = periodSum / divider;
             periodSum -= periodSub;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
       public RetCode wmaUnguarded( int startIdx,
                                    int endIdx,
                                    float inReal[],
                                    int optInTimePeriod,
                                    MInteger outBegIdx,
                                    MInteger outNBElement,
                                    double outReal[] )
       {
          int inIdx = 0;
          int outIdx = 0;
          int i = 0;
          int trailingIdx = 0;
          int divider = 0;
          double periodSum = 0;
          double periodSub = 0;
          double tempReal = 0;
          double trailingValue = 0;
          int lookbackTotal = 0;
          lookbackTotal = optInTimePeriod - 1;
          if( startIdx < lookbackTotal ) {
             startIdx = lookbackTotal;
          }
          if( startIdx > endIdx ) {
             outBegIdx.value = 0;
             outNBElement.value = 0;
             return RetCode.Success ;
          }
          if( optInTimePeriod == 1 ) {
             outBegIdx.value = startIdx;
             outNBElement.value = endIdx - startIdx + 1;
             System.arraycopy(inReal, startIdx, outReal, 0, (int)outNBElement.value * 1);
             return RetCode.Success ;
          }
          divider = optInTimePeriod * (optInTimePeriod + 1) >> 1;
          outIdx = 0;
          trailingIdx = startIdx - lookbackTotal;
          periodSub = (double)0.0;
          periodSum = periodSub;
          inIdx = trailingIdx;
          i = 1;
          while( inIdx < startIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSum += tempReal * i;
             i += 1;
          }
          trailingValue = 0.0;
          while( inIdx <= endIdx ) {
             tempReal = inReal[inIdx++];
             periodSub += tempReal;
             periodSub -= trailingValue;
             periodSum += tempReal * optInTimePeriod;
             trailingValue = inReal[trailingIdx++];
             outReal[outIdx++] = periodSum / divider;
             periodSum -= periodSub;
          }
          outNBElement.value = outIdx;
          outBegIdx.value = startIdx;
          return RetCode.Success ;
       }
}

public class TaCodegenServe {
    static Core core = new Core();
    static final int MAX_ARRAY_SIZE = 200000;
    static double[] refOpen = new double[MAX_ARRAY_SIZE];
    static double[] refHigh = new double[MAX_ARRAY_SIZE];
    static double[] refLow = new double[MAX_ARRAY_SIZE];
    static double[] refClose = new double[MAX_ARRAY_SIZE];
    static double[] refVolume = new double[MAX_ARRAY_SIZE];
    static double[] refOI = new double[MAX_ARRAY_SIZE];
    static int refN = 0;

    static int jsonInt(String json, String field) {
        int idx = json.indexOf('"' + field + '"');
        if (idx < 0) return 0;
        idx = json.indexOf(':', idx) + 1;
        while (idx < json.length() && json.charAt(idx) == ' ') idx++;
        int end = idx;
        while (end < json.length() && "0123456789-".indexOf(json.charAt(end)) >= 0) end++;
        return Integer.parseInt(json.substring(idx, end));
    }

    static double jsonDouble(String json, String field) {
        int idx = json.indexOf('"' + field + '"');
        if (idx < 0) return 0.0;
        idx = json.indexOf(':', idx) + 1;
        while (idx < json.length() && json.charAt(idx) == ' ') idx++;
        int end = idx;
        while (end < json.length() && "0123456789-.eE+".indexOf(json.charAt(end)) >= 0) end++;
        return Double.parseDouble(json.substring(idx, end));
    }

    static double[] jsonDoubleArray(String json, String field) {
        int idx = json.indexOf('"' + field + '"');
        if (idx < 0) return new double[0];
        idx = json.indexOf('[', idx);
        int end = json.indexOf(']', idx);
        String inner = json.substring(idx + 1, end).trim();
        if (inner.isEmpty()) return new double[0];
        String[] parts = inner.split(",");
        double[] result = new double[parts.length];
        for (int i = 0; i < parts.length; i++)
            result[i] = Double.parseDouble(parts[i].trim());
        return result;
    }

    static String doubleArrayToJson(double[] arr, int count) {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < count; i++) {
            if (i > 0) sb.append(',');
            sb.append(arr[i]);
        }
        sb.append(']');
        return sb.toString();
    }

    static String intArrayToJson(int[] arr, int count) {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < count; i++) {
            if (i > 0) sb.append(',');
            sb.append(arr[i]);
        }
        sb.append(']');
        return sb.toString();
    }

    static String handleRequest(String json) {
        if (json.contains("\"load_data\"")) {
            double[] tmp = jsonDoubleArray(json, "open");
            refN = tmp.length;
            System.arraycopy(tmp, 0, refOpen, 0, refN);
            tmp = jsonDoubleArray(json, "high");
            System.arraycopy(tmp, 0, refHigh, 0, Math.min(tmp.length, MAX_ARRAY_SIZE));
            tmp = jsonDoubleArray(json, "low");
            System.arraycopy(tmp, 0, refLow, 0, Math.min(tmp.length, MAX_ARRAY_SIZE));
            tmp = jsonDoubleArray(json, "close");
            System.arraycopy(tmp, 0, refClose, 0, Math.min(tmp.length, MAX_ARRAY_SIZE));
            tmp = jsonDoubleArray(json, "volume");
            System.arraycopy(tmp, 0, refVolume, 0, Math.min(tmp.length, MAX_ARRAY_SIZE));
            tmp = jsonDoubleArray(json, "openInterest");
            System.arraycopy(tmp, 0, refOI, 0, Math.min(tmp.length, MAX_ARRAY_SIZE));
            return "{\"status\":\"ok\",\"n\":" + refN + "}";
        }
        else if (json.contains("\"TA_ACCBANDS\"")) return handle_ACCBANDS(json);
        else if (json.contains("\"TA_ACOS\"")) return handle_ACOS(json);
        else if (json.contains("\"TA_AD\"")) return handle_AD(json);
        else if (json.contains("\"TA_ADD\"")) return handle_ADD(json);
        else if (json.contains("\"TA_ADOSC\"")) return handle_ADOSC(json);
        else if (json.contains("\"TA_ADX\"")) return handle_ADX(json);
        else if (json.contains("\"TA_ADXR\"")) return handle_ADXR(json);
        else if (json.contains("\"TA_APO\"")) return handle_APO(json);
        else if (json.contains("\"TA_AROON\"")) return handle_AROON(json);
        else if (json.contains("\"TA_AROONOSC\"")) return handle_AROONOSC(json);
        else if (json.contains("\"TA_ASIN\"")) return handle_ASIN(json);
        else if (json.contains("\"TA_ATAN\"")) return handle_ATAN(json);
        else if (json.contains("\"TA_ATR\"")) return handle_ATR(json);
        else if (json.contains("\"TA_AVGDEV\"")) return handle_AVGDEV(json);
        else if (json.contains("\"TA_AVGPRICE\"")) return handle_AVGPRICE(json);
        else if (json.contains("\"TA_BBANDS\"")) return handle_BBANDS(json);
        else if (json.contains("\"TA_BETA\"")) return handle_BETA(json);
        else if (json.contains("\"TA_BOP\"")) return handle_BOP(json);
        else if (json.contains("\"TA_CCI\"")) return handle_CCI(json);
        else if (json.contains("\"TA_CDL2CROWS\"")) return handle_CDL2CROWS(json);
        else if (json.contains("\"TA_CDL3BLACKCROWS\"")) return handle_CDL3BLACKCROWS(json);
        else if (json.contains("\"TA_CDL3INSIDE\"")) return handle_CDL3INSIDE(json);
        else if (json.contains("\"TA_CDL3LINESTRIKE\"")) return handle_CDL3LINESTRIKE(json);
        else if (json.contains("\"TA_CDL3OUTSIDE\"")) return handle_CDL3OUTSIDE(json);
        else if (json.contains("\"TA_CDL3STARSINSOUTH\"")) return handle_CDL3STARSINSOUTH(json);
        else if (json.contains("\"TA_CDL3WHITESOLDIERS\"")) return handle_CDL3WHITESOLDIERS(json);
        else if (json.contains("\"TA_CDLABANDONEDBABY\"")) return handle_CDLABANDONEDBABY(json);
        else if (json.contains("\"TA_CDLADVANCEBLOCK\"")) return handle_CDLADVANCEBLOCK(json);
        else if (json.contains("\"TA_CDLBELTHOLD\"")) return handle_CDLBELTHOLD(json);
        else if (json.contains("\"TA_CDLBREAKAWAY\"")) return handle_CDLBREAKAWAY(json);
        else if (json.contains("\"TA_CDLCLOSINGMARUBOZU\"")) return handle_CDLCLOSINGMARUBOZU(json);
        else if (json.contains("\"TA_CDLCONCEALBABYSWALL\"")) return handle_CDLCONCEALBABYSWALL(json);
        else if (json.contains("\"TA_CDLCOUNTERATTACK\"")) return handle_CDLCOUNTERATTACK(json);
        else if (json.contains("\"TA_CDLDARKCLOUDCOVER\"")) return handle_CDLDARKCLOUDCOVER(json);
        else if (json.contains("\"TA_CDLDOJI\"")) return handle_CDLDOJI(json);
        else if (json.contains("\"TA_CDLDOJISTAR\"")) return handle_CDLDOJISTAR(json);
        else if (json.contains("\"TA_CDLDRAGONFLYDOJI\"")) return handle_CDLDRAGONFLYDOJI(json);
        else if (json.contains("\"TA_CDLENGULFING\"")) return handle_CDLENGULFING(json);
        else if (json.contains("\"TA_CDLEVENINGDOJISTAR\"")) return handle_CDLEVENINGDOJISTAR(json);
        else if (json.contains("\"TA_CDLEVENINGSTAR\"")) return handle_CDLEVENINGSTAR(json);
        else if (json.contains("\"TA_CDLGAPSIDESIDEWHITE\"")) return handle_CDLGAPSIDESIDEWHITE(json);
        else if (json.contains("\"TA_CDLGRAVESTONEDOJI\"")) return handle_CDLGRAVESTONEDOJI(json);
        else if (json.contains("\"TA_CDLHAMMER\"")) return handle_CDLHAMMER(json);
        else if (json.contains("\"TA_CDLHANGINGMAN\"")) return handle_CDLHANGINGMAN(json);
        else if (json.contains("\"TA_CDLHARAMI\"")) return handle_CDLHARAMI(json);
        else if (json.contains("\"TA_CDLHARAMICROSS\"")) return handle_CDLHARAMICROSS(json);
        else if (json.contains("\"TA_CDLHIGHWAVE\"")) return handle_CDLHIGHWAVE(json);
        else if (json.contains("\"TA_CDLHIKKAKE\"")) return handle_CDLHIKKAKE(json);
        else if (json.contains("\"TA_CDLHIKKAKEMOD\"")) return handle_CDLHIKKAKEMOD(json);
        else if (json.contains("\"TA_CDLHOMINGPIGEON\"")) return handle_CDLHOMINGPIGEON(json);
        else if (json.contains("\"TA_CDLIDENTICAL3CROWS\"")) return handle_CDLIDENTICAL3CROWS(json);
        else if (json.contains("\"TA_CDLINNECK\"")) return handle_CDLINNECK(json);
        else if (json.contains("\"TA_CDLINVERTEDHAMMER\"")) return handle_CDLINVERTEDHAMMER(json);
        else if (json.contains("\"TA_CDLKICKING\"")) return handle_CDLKICKING(json);
        else if (json.contains("\"TA_CDLKICKINGBYLENGTH\"")) return handle_CDLKICKINGBYLENGTH(json);
        else if (json.contains("\"TA_CDLLADDERBOTTOM\"")) return handle_CDLLADDERBOTTOM(json);
        else if (json.contains("\"TA_CDLLONGLEGGEDDOJI\"")) return handle_CDLLONGLEGGEDDOJI(json);
        else if (json.contains("\"TA_CDLLONGLINE\"")) return handle_CDLLONGLINE(json);
        else if (json.contains("\"TA_CDLMARUBOZU\"")) return handle_CDLMARUBOZU(json);
        else if (json.contains("\"TA_CDLMATCHINGLOW\"")) return handle_CDLMATCHINGLOW(json);
        else if (json.contains("\"TA_CDLMATHOLD\"")) return handle_CDLMATHOLD(json);
        else if (json.contains("\"TA_CDLMORNINGDOJISTAR\"")) return handle_CDLMORNINGDOJISTAR(json);
        else if (json.contains("\"TA_CDLMORNINGSTAR\"")) return handle_CDLMORNINGSTAR(json);
        else if (json.contains("\"TA_CDLONNECK\"")) return handle_CDLONNECK(json);
        else if (json.contains("\"TA_CDLPIERCING\"")) return handle_CDLPIERCING(json);
        else if (json.contains("\"TA_CDLRICKSHAWMAN\"")) return handle_CDLRICKSHAWMAN(json);
        else if (json.contains("\"TA_CDLRISEFALL3METHODS\"")) return handle_CDLRISEFALL3METHODS(json);
        else if (json.contains("\"TA_CDLSEPARATINGLINES\"")) return handle_CDLSEPARATINGLINES(json);
        else if (json.contains("\"TA_CDLSHOOTINGSTAR\"")) return handle_CDLSHOOTINGSTAR(json);
        else if (json.contains("\"TA_CDLSHORTLINE\"")) return handle_CDLSHORTLINE(json);
        else if (json.contains("\"TA_CDLSPINNINGTOP\"")) return handle_CDLSPINNINGTOP(json);
        else if (json.contains("\"TA_CDLSTALLEDPATTERN\"")) return handle_CDLSTALLEDPATTERN(json);
        else if (json.contains("\"TA_CDLSTICKSANDWICH\"")) return handle_CDLSTICKSANDWICH(json);
        else if (json.contains("\"TA_CDLTAKURI\"")) return handle_CDLTAKURI(json);
        else if (json.contains("\"TA_CDLTASUKIGAP\"")) return handle_CDLTASUKIGAP(json);
        else if (json.contains("\"TA_CDLTHRUSTING\"")) return handle_CDLTHRUSTING(json);
        else if (json.contains("\"TA_CDLTRISTAR\"")) return handle_CDLTRISTAR(json);
        else if (json.contains("\"TA_CDLUNIQUE3RIVER\"")) return handle_CDLUNIQUE3RIVER(json);
        else if (json.contains("\"TA_CDLUPSIDEGAP2CROWS\"")) return handle_CDLUPSIDEGAP2CROWS(json);
        else if (json.contains("\"TA_CDLXSIDEGAP3METHODS\"")) return handle_CDLXSIDEGAP3METHODS(json);
        else if (json.contains("\"TA_CEIL\"")) return handle_CEIL(json);
        else if (json.contains("\"TA_CMO\"")) return handle_CMO(json);
        else if (json.contains("\"TA_CORREL\"")) return handle_CORREL(json);
        else if (json.contains("\"TA_COS\"")) return handle_COS(json);
        else if (json.contains("\"TA_COSH\"")) return handle_COSH(json);
        else if (json.contains("\"TA_DEMA\"")) return handle_DEMA(json);
        else if (json.contains("\"TA_DIV\"")) return handle_DIV(json);
        else if (json.contains("\"TA_DX\"")) return handle_DX(json);
        else if (json.contains("\"TA_EMA\"")) return handle_EMA(json);
        else if (json.contains("\"TA_EXP\"")) return handle_EXP(json);
        else if (json.contains("\"TA_FLOOR\"")) return handle_FLOOR(json);
        else if (json.contains("\"TA_HT_DCPERIOD\"")) return handle_HT_DCPERIOD(json);
        else if (json.contains("\"TA_HT_DCPHASE\"")) return handle_HT_DCPHASE(json);
        else if (json.contains("\"TA_HT_PHASOR\"")) return handle_HT_PHASOR(json);
        else if (json.contains("\"TA_HT_SINE\"")) return handle_HT_SINE(json);
        else if (json.contains("\"TA_HT_TRENDLINE\"")) return handle_HT_TRENDLINE(json);
        else if (json.contains("\"TA_HT_TRENDMODE\"")) return handle_HT_TRENDMODE(json);
        else if (json.contains("\"TA_IMI\"")) return handle_IMI(json);
        else if (json.contains("\"TA_KAMA\"")) return handle_KAMA(json);
        else if (json.contains("\"TA_LINEARREG\"")) return handle_LINEARREG(json);
        else if (json.contains("\"TA_LINEARREG_ANGLE\"")) return handle_LINEARREG_ANGLE(json);
        else if (json.contains("\"TA_LINEARREG_INTERCEPT\"")) return handle_LINEARREG_INTERCEPT(json);
        else if (json.contains("\"TA_LINEARREG_SLOPE\"")) return handle_LINEARREG_SLOPE(json);
        else if (json.contains("\"TA_LN\"")) return handle_LN(json);
        else if (json.contains("\"TA_LOG10\"")) return handle_LOG10(json);
        else if (json.contains("\"TA_MA\"")) return handle_MA(json);
        else if (json.contains("\"TA_MACD\"")) return handle_MACD(json);
        else if (json.contains("\"TA_MACDEXT\"")) return handle_MACDEXT(json);
        else if (json.contains("\"TA_MACDFIX\"")) return handle_MACDFIX(json);
        else if (json.contains("\"TA_MAMA\"")) return handle_MAMA(json);
        else if (json.contains("\"TA_MAVP\"")) return handle_MAVP(json);
        else if (json.contains("\"TA_MAX\"")) return handle_MAX(json);
        else if (json.contains("\"TA_MAXINDEX\"")) return handle_MAXINDEX(json);
        else if (json.contains("\"TA_MEDPRICE\"")) return handle_MEDPRICE(json);
        else if (json.contains("\"TA_MFI\"")) return handle_MFI(json);
        else if (json.contains("\"TA_MIDPOINT\"")) return handle_MIDPOINT(json);
        else if (json.contains("\"TA_MIDPRICE\"")) return handle_MIDPRICE(json);
        else if (json.contains("\"TA_MIN\"")) return handle_MIN(json);
        else if (json.contains("\"TA_MININDEX\"")) return handle_MININDEX(json);
        else if (json.contains("\"TA_MINMAX\"")) return handle_MINMAX(json);
        else if (json.contains("\"TA_MINMAXINDEX\"")) return handle_MINMAXINDEX(json);
        else if (json.contains("\"TA_MINUS_DI\"")) return handle_MINUS_DI(json);
        else if (json.contains("\"TA_MINUS_DM\"")) return handle_MINUS_DM(json);
        else if (json.contains("\"TA_MOM\"")) return handle_MOM(json);
        else if (json.contains("\"TA_MULT\"")) return handle_MULT(json);
        else if (json.contains("\"TA_NATR\"")) return handle_NATR(json);
        else if (json.contains("\"TA_OBV\"")) return handle_OBV(json);
        else if (json.contains("\"TA_PLUS_DI\"")) return handle_PLUS_DI(json);
        else if (json.contains("\"TA_PLUS_DM\"")) return handle_PLUS_DM(json);
        else if (json.contains("\"TA_PPO\"")) return handle_PPO(json);
        else if (json.contains("\"TA_ROC\"")) return handle_ROC(json);
        else if (json.contains("\"TA_ROCP\"")) return handle_ROCP(json);
        else if (json.contains("\"TA_ROCR\"")) return handle_ROCR(json);
        else if (json.contains("\"TA_ROCR100\"")) return handle_ROCR100(json);
        else if (json.contains("\"TA_RSI\"")) return handle_RSI(json);
        else if (json.contains("\"TA_SAR\"")) return handle_SAR(json);
        else if (json.contains("\"TA_SAREXT\"")) return handle_SAREXT(json);
        else if (json.contains("\"TA_SIN\"")) return handle_SIN(json);
        else if (json.contains("\"TA_SINH\"")) return handle_SINH(json);
        else if (json.contains("\"TA_SMA\"")) return handle_SMA(json);
        else if (json.contains("\"TA_SQRT\"")) return handle_SQRT(json);
        else if (json.contains("\"TA_STDDEV\"")) return handle_STDDEV(json);
        else if (json.contains("\"TA_STOCH\"")) return handle_STOCH(json);
        else if (json.contains("\"TA_STOCHF\"")) return handle_STOCHF(json);
        else if (json.contains("\"TA_STOCHRSI\"")) return handle_STOCHRSI(json);
        else if (json.contains("\"TA_SUB\"")) return handle_SUB(json);
        else if (json.contains("\"TA_SUM\"")) return handle_SUM(json);
        else if (json.contains("\"TA_T3\"")) return handle_T3(json);
        else if (json.contains("\"TA_TAN\"")) return handle_TAN(json);
        else if (json.contains("\"TA_TANH\"")) return handle_TANH(json);
        else if (json.contains("\"TA_TEMA\"")) return handle_TEMA(json);
        else if (json.contains("\"TA_TRANGE\"")) return handle_TRANGE(json);
        else if (json.contains("\"TA_TRIMA\"")) return handle_TRIMA(json);
        else if (json.contains("\"TA_TRIX\"")) return handle_TRIX(json);
        else if (json.contains("\"TA_TSF\"")) return handle_TSF(json);
        else if (json.contains("\"TA_TYPPRICE\"")) return handle_TYPPRICE(json);
        else if (json.contains("\"TA_ULTOSC\"")) return handle_ULTOSC(json);
        else if (json.contains("\"TA_VAR\"")) return handle_VAR(json);
        else if (json.contains("\"TA_WCLPRICE\"")) return handle_WCLPRICE(json);
        else if (json.contains("\"TA_WILLR\"")) return handle_WILLR(json);
        else if (json.contains("\"TA_WMA\"")) return handle_WMA(json);
        else if (json.contains("\"list_functions\"")) {
            StringBuilder sb = new StringBuilder("{\"functions\":[");
            sb.append("\"TA_ACCBANDS\"");
            sb.append(",");
            sb.append("\"TA_ACOS\"");
            sb.append(",");
            sb.append("\"TA_AD\"");
            sb.append(",");
            sb.append("\"TA_ADD\"");
            sb.append(",");
            sb.append("\"TA_ADOSC\"");
            sb.append(",");
            sb.append("\"TA_ADX\"");
            sb.append(",");
            sb.append("\"TA_ADXR\"");
            sb.append(",");
            sb.append("\"TA_APO\"");
            sb.append(",");
            sb.append("\"TA_AROON\"");
            sb.append(",");
            sb.append("\"TA_AROONOSC\"");
            sb.append(",");
            sb.append("\"TA_ASIN\"");
            sb.append(",");
            sb.append("\"TA_ATAN\"");
            sb.append(",");
            sb.append("\"TA_ATR\"");
            sb.append(",");
            sb.append("\"TA_AVGDEV\"");
            sb.append(",");
            sb.append("\"TA_AVGPRICE\"");
            sb.append(",");
            sb.append("\"TA_BBANDS\"");
            sb.append(",");
            sb.append("\"TA_BETA\"");
            sb.append(",");
            sb.append("\"TA_BOP\"");
            sb.append(",");
            sb.append("\"TA_CCI\"");
            sb.append(",");
            sb.append("\"TA_CDL2CROWS\"");
            sb.append(",");
            sb.append("\"TA_CDL3BLACKCROWS\"");
            sb.append(",");
            sb.append("\"TA_CDL3INSIDE\"");
            sb.append(",");
            sb.append("\"TA_CDL3LINESTRIKE\"");
            sb.append(",");
            sb.append("\"TA_CDL3OUTSIDE\"");
            sb.append(",");
            sb.append("\"TA_CDL3STARSINSOUTH\"");
            sb.append(",");
            sb.append("\"TA_CDL3WHITESOLDIERS\"");
            sb.append(",");
            sb.append("\"TA_CDLABANDONEDBABY\"");
            sb.append(",");
            sb.append("\"TA_CDLADVANCEBLOCK\"");
            sb.append(",");
            sb.append("\"TA_CDLBELTHOLD\"");
            sb.append(",");
            sb.append("\"TA_CDLBREAKAWAY\"");
            sb.append(",");
            sb.append("\"TA_CDLCLOSINGMARUBOZU\"");
            sb.append(",");
            sb.append("\"TA_CDLCONCEALBABYSWALL\"");
            sb.append(",");
            sb.append("\"TA_CDLCOUNTERATTACK\"");
            sb.append(",");
            sb.append("\"TA_CDLDARKCLOUDCOVER\"");
            sb.append(",");
            sb.append("\"TA_CDLDOJI\"");
            sb.append(",");
            sb.append("\"TA_CDLDOJISTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLDRAGONFLYDOJI\"");
            sb.append(",");
            sb.append("\"TA_CDLENGULFING\"");
            sb.append(",");
            sb.append("\"TA_CDLEVENINGDOJISTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLEVENINGSTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLGAPSIDESIDEWHITE\"");
            sb.append(",");
            sb.append("\"TA_CDLGRAVESTONEDOJI\"");
            sb.append(",");
            sb.append("\"TA_CDLHAMMER\"");
            sb.append(",");
            sb.append("\"TA_CDLHANGINGMAN\"");
            sb.append(",");
            sb.append("\"TA_CDLHARAMI\"");
            sb.append(",");
            sb.append("\"TA_CDLHARAMICROSS\"");
            sb.append(",");
            sb.append("\"TA_CDLHIGHWAVE\"");
            sb.append(",");
            sb.append("\"TA_CDLHIKKAKE\"");
            sb.append(",");
            sb.append("\"TA_CDLHIKKAKEMOD\"");
            sb.append(",");
            sb.append("\"TA_CDLHOMINGPIGEON\"");
            sb.append(",");
            sb.append("\"TA_CDLIDENTICAL3CROWS\"");
            sb.append(",");
            sb.append("\"TA_CDLINNECK\"");
            sb.append(",");
            sb.append("\"TA_CDLINVERTEDHAMMER\"");
            sb.append(",");
            sb.append("\"TA_CDLKICKING\"");
            sb.append(",");
            sb.append("\"TA_CDLKICKINGBYLENGTH\"");
            sb.append(",");
            sb.append("\"TA_CDLLADDERBOTTOM\"");
            sb.append(",");
            sb.append("\"TA_CDLLONGLEGGEDDOJI\"");
            sb.append(",");
            sb.append("\"TA_CDLLONGLINE\"");
            sb.append(",");
            sb.append("\"TA_CDLMARUBOZU\"");
            sb.append(",");
            sb.append("\"TA_CDLMATCHINGLOW\"");
            sb.append(",");
            sb.append("\"TA_CDLMATHOLD\"");
            sb.append(",");
            sb.append("\"TA_CDLMORNINGDOJISTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLMORNINGSTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLONNECK\"");
            sb.append(",");
            sb.append("\"TA_CDLPIERCING\"");
            sb.append(",");
            sb.append("\"TA_CDLRICKSHAWMAN\"");
            sb.append(",");
            sb.append("\"TA_CDLRISEFALL3METHODS\"");
            sb.append(",");
            sb.append("\"TA_CDLSEPARATINGLINES\"");
            sb.append(",");
            sb.append("\"TA_CDLSHOOTINGSTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLSHORTLINE\"");
            sb.append(",");
            sb.append("\"TA_CDLSPINNINGTOP\"");
            sb.append(",");
            sb.append("\"TA_CDLSTALLEDPATTERN\"");
            sb.append(",");
            sb.append("\"TA_CDLSTICKSANDWICH\"");
            sb.append(",");
            sb.append("\"TA_CDLTAKURI\"");
            sb.append(",");
            sb.append("\"TA_CDLTASUKIGAP\"");
            sb.append(",");
            sb.append("\"TA_CDLTHRUSTING\"");
            sb.append(",");
            sb.append("\"TA_CDLTRISTAR\"");
            sb.append(",");
            sb.append("\"TA_CDLUNIQUE3RIVER\"");
            sb.append(",");
            sb.append("\"TA_CDLUPSIDEGAP2CROWS\"");
            sb.append(",");
            sb.append("\"TA_CDLXSIDEGAP3METHODS\"");
            sb.append(",");
            sb.append("\"TA_CEIL\"");
            sb.append(",");
            sb.append("\"TA_CMO\"");
            sb.append(",");
            sb.append("\"TA_CORREL\"");
            sb.append(",");
            sb.append("\"TA_COS\"");
            sb.append(",");
            sb.append("\"TA_COSH\"");
            sb.append(",");
            sb.append("\"TA_DEMA\"");
            sb.append(",");
            sb.append("\"TA_DIV\"");
            sb.append(",");
            sb.append("\"TA_DX\"");
            sb.append(",");
            sb.append("\"TA_EMA\"");
            sb.append(",");
            sb.append("\"TA_EXP\"");
            sb.append(",");
            sb.append("\"TA_FLOOR\"");
            sb.append(",");
            sb.append("\"TA_HT_DCPERIOD\"");
            sb.append(",");
            sb.append("\"TA_HT_DCPHASE\"");
            sb.append(",");
            sb.append("\"TA_HT_PHASOR\"");
            sb.append(",");
            sb.append("\"TA_HT_SINE\"");
            sb.append(",");
            sb.append("\"TA_HT_TRENDLINE\"");
            sb.append(",");
            sb.append("\"TA_HT_TRENDMODE\"");
            sb.append(",");
            sb.append("\"TA_IMI\"");
            sb.append(",");
            sb.append("\"TA_KAMA\"");
            sb.append(",");
            sb.append("\"TA_LINEARREG\"");
            sb.append(",");
            sb.append("\"TA_LINEARREG_ANGLE\"");
            sb.append(",");
            sb.append("\"TA_LINEARREG_INTERCEPT\"");
            sb.append(",");
            sb.append("\"TA_LINEARREG_SLOPE\"");
            sb.append(",");
            sb.append("\"TA_LN\"");
            sb.append(",");
            sb.append("\"TA_LOG10\"");
            sb.append(",");
            sb.append("\"TA_MA\"");
            sb.append(",");
            sb.append("\"TA_MACD\"");
            sb.append(",");
            sb.append("\"TA_MACDEXT\"");
            sb.append(",");
            sb.append("\"TA_MACDFIX\"");
            sb.append(",");
            sb.append("\"TA_MAMA\"");
            sb.append(",");
            sb.append("\"TA_MAVP\"");
            sb.append(",");
            sb.append("\"TA_MAX\"");
            sb.append(",");
            sb.append("\"TA_MAXINDEX\"");
            sb.append(",");
            sb.append("\"TA_MEDPRICE\"");
            sb.append(",");
            sb.append("\"TA_MFI\"");
            sb.append(",");
            sb.append("\"TA_MIDPOINT\"");
            sb.append(",");
            sb.append("\"TA_MIDPRICE\"");
            sb.append(",");
            sb.append("\"TA_MIN\"");
            sb.append(",");
            sb.append("\"TA_MININDEX\"");
            sb.append(",");
            sb.append("\"TA_MINMAX\"");
            sb.append(",");
            sb.append("\"TA_MINMAXINDEX\"");
            sb.append(",");
            sb.append("\"TA_MINUS_DI\"");
            sb.append(",");
            sb.append("\"TA_MINUS_DM\"");
            sb.append(",");
            sb.append("\"TA_MOM\"");
            sb.append(",");
            sb.append("\"TA_MULT\"");
            sb.append(",");
            sb.append("\"TA_NATR\"");
            sb.append(",");
            sb.append("\"TA_OBV\"");
            sb.append(",");
            sb.append("\"TA_PLUS_DI\"");
            sb.append(",");
            sb.append("\"TA_PLUS_DM\"");
            sb.append(",");
            sb.append("\"TA_PPO\"");
            sb.append(",");
            sb.append("\"TA_ROC\"");
            sb.append(",");
            sb.append("\"TA_ROCP\"");
            sb.append(",");
            sb.append("\"TA_ROCR\"");
            sb.append(",");
            sb.append("\"TA_ROCR100\"");
            sb.append(",");
            sb.append("\"TA_RSI\"");
            sb.append(",");
            sb.append("\"TA_SAR\"");
            sb.append(",");
            sb.append("\"TA_SAREXT\"");
            sb.append(",");
            sb.append("\"TA_SIN\"");
            sb.append(",");
            sb.append("\"TA_SINH\"");
            sb.append(",");
            sb.append("\"TA_SMA\"");
            sb.append(",");
            sb.append("\"TA_SQRT\"");
            sb.append(",");
            sb.append("\"TA_STDDEV\"");
            sb.append(",");
            sb.append("\"TA_STOCH\"");
            sb.append(",");
            sb.append("\"TA_STOCHF\"");
            sb.append(",");
            sb.append("\"TA_STOCHRSI\"");
            sb.append(",");
            sb.append("\"TA_SUB\"");
            sb.append(",");
            sb.append("\"TA_SUM\"");
            sb.append(",");
            sb.append("\"TA_T3\"");
            sb.append(",");
            sb.append("\"TA_TAN\"");
            sb.append(",");
            sb.append("\"TA_TANH\"");
            sb.append(",");
            sb.append("\"TA_TEMA\"");
            sb.append(",");
            sb.append("\"TA_TRANGE\"");
            sb.append(",");
            sb.append("\"TA_TRIMA\"");
            sb.append(",");
            sb.append("\"TA_TRIX\"");
            sb.append(",");
            sb.append("\"TA_TSF\"");
            sb.append(",");
            sb.append("\"TA_TYPPRICE\"");
            sb.append(",");
            sb.append("\"TA_ULTOSC\"");
            sb.append(",");
            sb.append("\"TA_VAR\"");
            sb.append(",");
            sb.append("\"TA_WCLPRICE\"");
            sb.append(",");
            sb.append("\"TA_WILLR\"");
            sb.append(",");
            sb.append("\"TA_WMA\"");
            sb.append("]}");
            return sb.toString();
        }
        else if (json.contains("\"set_unstable_period\"")) {
            int id = jsonInt(json, "id");
            int period = jsonInt(json, "period");
            if (id >= 0 && id < core.unstablePeriod.length) {
                core.unstablePeriod[id] = period;
                return "{\"status\":\"ok\"}"; 
            }
            return "{\"error\":\"Invalid id\"}"; 
        }
        else if (json.contains("\"set_compatibility\"")) {
            int mode = jsonInt(json, "mode");
            core.compatibility = (mode == 1) ? Compatibility.Metastock : Compatibility.Default;
            return "{\"status\":\"ok\"}";
        }
        else {
            return "{\"error\":\"Unknown method\"}";
        }
    }

    static String handle_ACCBANDS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        double[] outArr2 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.accbands(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.accbandsUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"outReal2\":").append(doubleArrayToJson(outArr2, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ACOS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.acos(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.acosUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_AD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        double[] inVolume = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
            System.arraycopy(refVolume, 0, inVolume, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
            double[] _tmp_inVolume = jsonDoubleArray(json, "inVolume");
            inVolume = _tmp_inVolume;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ad(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.adUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ADD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.add(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.addUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ADOSC(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        double[] inVolume = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
            System.arraycopy(refVolume, 0, inVolume, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
            double[] _tmp_inVolume = jsonDoubleArray(json, "inVolume");
            inVolume = _tmp_inVolume;
        }
        int optInFastPeriod = jsonInt(json, "optInFastPeriod");
        int optInSlowPeriod = jsonInt(json, "optInSlowPeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.adOsc(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            optInFastPeriod,
            optInSlowPeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.adOscUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            optInFastPeriod,
            optInSlowPeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ADX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[0] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.adx(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.adxUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ADXR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[1] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.adxr(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.adxrUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_APO(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInFastPeriod = jsonInt(json, "optInFastPeriod");
        int optInSlowPeriod = jsonInt(json, "optInSlowPeriod");
        MAType optInMAType = MAType.values()[jsonInt(json, "optInMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.apo(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.apoUnguarded(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_AROON(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.aroon(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.aroonUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_AROONOSC(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.aroonOsc(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.aroonOscUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ASIN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.asin(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.asinUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ATAN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.atan(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.atanUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ATR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[2] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.atr(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.atrUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_AVGDEV(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.avgDev(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.avgDevUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_AVGPRICE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.avgPrice(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.avgPriceUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_BBANDS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double optInNbDevUp = jsonDouble(json, "optInNbDevUp");
        double optInNbDevDn = jsonDouble(json, "optInNbDevDn");
        MAType optInMAType = MAType.values()[jsonInt(json, "optInMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        double[] outArr2 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.bbands(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDevUp,
            optInNbDevDn,
            optInMAType,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.bbandsUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDevUp,
            optInNbDevDn,
            optInMAType,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"outReal2\":").append(doubleArrayToJson(outArr2, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_BETA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.beta(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.betaUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_BOP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.bop(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.bopUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CCI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cci(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cciUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL2CROWS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl2Crows(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl2CrowsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3BLACKCROWS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3BlackCrows(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3BlackCrowsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3INSIDE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3Inside(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3InsideUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3LINESTRIKE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3LineStrike(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3LineStrikeUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3OUTSIDE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3Outside(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3OutsideUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3STARSINSOUTH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3StarsInSouth(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3StarsInSouthUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDL3WHITESOLDIERS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdl3WhiteSoldiers(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdl3WhiteSoldiersUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLABANDONEDBABY(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlAbandonedBaby(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlAbandonedBabyUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLADVANCEBLOCK(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlAdvanceBlock(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlAdvanceBlockUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLBELTHOLD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlBeltHold(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlBeltHoldUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLBREAKAWAY(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlBreakaway(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlBreakawayUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLCLOSINGMARUBOZU(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlClosingMarubozu(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlClosingMarubozuUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLCONCEALBABYSWALL(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlConcealBabysWall(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlConcealBabysWallUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLCOUNTERATTACK(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlCounterAttack(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlCounterAttackUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLDARKCLOUDCOVER(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlDarkCloudCover(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlDarkCloudCoverUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLDOJI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlDoji(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlDojiUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLDOJISTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlDojiStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlDojiStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLDRAGONFLYDOJI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlDragonflyDoji(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlDragonflyDojiUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLENGULFING(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlEngulfing(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlEngulfingUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLEVENINGDOJISTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlEveningDojiStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlEveningDojiStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLEVENINGSTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlEveningStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlEveningStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLGAPSIDESIDEWHITE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlGapSideSideWhite(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlGapSideSideWhiteUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLGRAVESTONEDOJI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlGravestoneDoji(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlGravestoneDojiUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHAMMER(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHammer(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHammerUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHANGINGMAN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHangingMan(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHangingManUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHARAMI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHarami(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHaramiUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHARAMICROSS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHaramiCross(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHaramiCrossUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHIGHWAVE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHignWave(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHignWaveUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHIKKAKE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHikkake(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHikkakeUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHIKKAKEMOD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHikkakeMod(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHikkakeModUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLHOMINGPIGEON(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlHomingPigeon(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlHomingPigeonUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLIDENTICAL3CROWS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlIdentical3Crows(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlIdentical3CrowsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLINNECK(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlInNeck(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlInNeckUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLINVERTEDHAMMER(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlInvertedHammer(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlInvertedHammerUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLKICKING(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlKicking(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlKickingUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLKICKINGBYLENGTH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlKickingByLength(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlKickingByLengthUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLLADDERBOTTOM(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlLadderBottom(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlLadderBottomUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLLONGLEGGEDDOJI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlLongLeggedDoji(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlLongLeggedDojiUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLLONGLINE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlLongLine(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlLongLineUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLMARUBOZU(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlMarubozu(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlMarubozuUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLMATCHINGLOW(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlMatchingLow(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlMatchingLowUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLMATHOLD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlMatHold(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlMatHoldUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLMORNINGDOJISTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlMorningDojiStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlMorningDojiStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLMORNINGSTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double optInPenetration = jsonDouble(json, "optInPenetration");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlMorningStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlMorningStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            optInPenetration,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLONNECK(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlOnNeck(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlOnNeckUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLPIERCING(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlPiercing(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlPiercingUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLRICKSHAWMAN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlRickshawMan(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlRickshawManUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLRISEFALL3METHODS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlRiseFall3Methods(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlRiseFall3MethodsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSEPARATINGLINES(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlSeperatingLines(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlSeperatingLinesUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSHOOTINGSTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlShootingStar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlShootingStarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSHORTLINE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlShortLine(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlShortLineUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSPINNINGTOP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlSpinningTop(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlSpinningTopUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSTALLEDPATTERN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlStalledPattern(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlStalledPatternUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLSTICKSANDWICH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlStickSandwich(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlStickSandwichUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLTAKURI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlTakuri(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlTakuriUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLTASUKIGAP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlTasukiGap(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlTasukiGapUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLTHRUSTING(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlThrusting(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlThrustingUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLTRISTAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlTristar(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlTristarUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLUNIQUE3RIVER(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlUnique3River(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlUnique3RiverUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLUPSIDEGAP2CROWS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlUpsideGap2Crows(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlUpsideGap2CrowsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CDLXSIDEGAP3METHODS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cdlXSideGap3Methods(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cdlXSideGap3MethodsUnguarded(
            startIdx, endIdx,
            inOpen,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CEIL(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ceil(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.ceilUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CMO(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[3] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cmo(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cmoUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_CORREL(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.correl(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.correlUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_COS(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cos(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.cosUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_COSH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.cosh(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.coshUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_DEMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.dema(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.demaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_DIV(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.div(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.divUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_DX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[4] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.dx(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.dxUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_EMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[5] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ema(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.emaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_EXP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.exp(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.expUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_FLOOR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.floor(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.floorUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_DCPERIOD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[6] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htDcPeriod(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htDcPeriodUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_DCPHASE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[7] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htDcPhase(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htDcPhaseUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_PHASOR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[8] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htPhasor(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htPhasorUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_SINE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[9] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htSine(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htSineUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_TRENDLINE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[10] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htTrendline(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htTrendlineUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_HT_TRENDMODE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        core.unstablePeriod[11] = jsonInt(json, "unstablePeriod");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.htTrendMode(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.htTrendModeUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_IMI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inOpen = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refOpen, 0, inOpen, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inOpen = jsonDoubleArray(json, "inOpen");
            inOpen = _tmp_inOpen;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[12] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.imi(
            startIdx, endIdx,
            inOpen,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.imiUnguarded(
            startIdx, endIdx,
            inOpen,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_KAMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[13] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.kama(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.kamaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LINEARREG(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.linearReg(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.linearRegUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LINEARREG_ANGLE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.linearRegAngle(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.linearRegAngleUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LINEARREG_INTERCEPT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.linearRegIntercept(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.linearRegInterceptUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LINEARREG_SLOPE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.linearRegSlope(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.linearRegSlopeUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ln(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.lnUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_LOG10(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.log10(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.log10Unguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        MAType optInMAType = MAType.values()[jsonInt(json, "optInMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.movingAverage(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.movingAverageUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MACD(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInFastPeriod = jsonInt(json, "optInFastPeriod");
        int optInSlowPeriod = jsonInt(json, "optInSlowPeriod");
        int optInSignalPeriod = jsonInt(json, "optInSignalPeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        double[] outArr2 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.macd(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInSignalPeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.macdUnguarded(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInSignalPeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"outReal2\":").append(doubleArrayToJson(outArr2, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MACDEXT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInFastPeriod = jsonInt(json, "optInFastPeriod");
        MAType optInFastMAType = MAType.values()[jsonInt(json, "optInFastMAType")];
        int optInSlowPeriod = jsonInt(json, "optInSlowPeriod");
        MAType optInSlowMAType = MAType.values()[jsonInt(json, "optInSlowMAType")];
        int optInSignalPeriod = jsonInt(json, "optInSignalPeriod");
        MAType optInSignalMAType = MAType.values()[jsonInt(json, "optInSignalMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        double[] outArr2 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.macdExt(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInFastMAType,
            optInSlowPeriod,
            optInSlowMAType,
            optInSignalPeriod,
            optInSignalMAType,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.macdExtUnguarded(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInFastMAType,
            optInSlowPeriod,
            optInSlowMAType,
            optInSignalPeriod,
            optInSignalMAType,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"outReal2\":").append(doubleArrayToJson(outArr2, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MACDFIX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInSignalPeriod = jsonInt(json, "optInSignalPeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        double[] outArr2 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.macdFix(
            startIdx, endIdx,
            inReal,
            optInSignalPeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.macdFixUnguarded(
            startIdx, endIdx,
            inReal,
            optInSignalPeriod,
            outBegIdx, outNBElement, outArr0, outArr1, outArr2);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"outReal2\":").append(doubleArrayToJson(outArr2, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MAMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double optInFastLimit = jsonDouble(json, "optInFastLimit");
        double optInSlowLimit = jsonDouble(json, "optInSlowLimit");
        core.unstablePeriod[14] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.mama(
            startIdx, endIdx,
            inReal,
            optInFastLimit,
            optInSlowLimit,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.mamaUnguarded(
            startIdx, endIdx,
            inReal,
            optInFastLimit,
            optInSlowLimit,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MAVP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        int optInMinPeriod = jsonInt(json, "optInMinPeriod");
        int optInMaxPeriod = jsonInt(json, "optInMaxPeriod");
        MAType optInMAType = MAType.values()[jsonInt(json, "optInMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.movingAverageVariablePeriod(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInMinPeriod,
            optInMaxPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.movingAverageVariablePeriodUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            optInMinPeriod,
            optInMaxPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MAX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.max(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.maxUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MAXINDEX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.maxIndex(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.maxIndexUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MEDPRICE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.medPrice(
            startIdx, endIdx,
            inHigh,
            inLow,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.medPriceUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MFI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        double[] inVolume = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
            System.arraycopy(refVolume, 0, inVolume, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
            double[] _tmp_inVolume = jsonDoubleArray(json, "inVolume");
            inVolume = _tmp_inVolume;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[15] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.mfi(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.mfiUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            inVolume,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MIDPOINT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.midPoint(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.midPointUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MIDPRICE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.midPrice(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.midPriceUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MIN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.min(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MININDEX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.minIndex(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minIndexUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MINMAX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.minMax(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minMaxUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MINMAXINDEX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        int[] outArr0 = new int[endIdx - startIdx + 1];
        int[] outArr1 = new int[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.minMaxIndex(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minMaxIndexUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outInteger\":").append(intArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outInteger1\":").append(intArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MINUS_DI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[16] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.minusDI(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minusDIUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MINUS_DM(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[17] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.minusDM(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.minusDMUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MOM(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.mom(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.momUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_MULT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.mult(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.multUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_NATR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[18] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.natr(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.natrUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_OBV(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        double[] inVolume = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
            System.arraycopy(refVolume, 0, inVolume, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
            double[] _tmp_inVolume = jsonDoubleArray(json, "inVolume");
            inVolume = _tmp_inVolume;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.obv(
            startIdx, endIdx,
            inReal,
            inVolume,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.obvUnguarded(
            startIdx, endIdx,
            inReal,
            inVolume,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_PLUS_DI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[19] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.plusDI(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.plusDIUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_PLUS_DM(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[20] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.plusDM(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.plusDMUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_PPO(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInFastPeriod = jsonInt(json, "optInFastPeriod");
        int optInSlowPeriod = jsonInt(json, "optInSlowPeriod");
        MAType optInMAType = MAType.values()[jsonInt(json, "optInMAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ppo(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.ppoUnguarded(
            startIdx, endIdx,
            inReal,
            optInFastPeriod,
            optInSlowPeriod,
            optInMAType,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ROC(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.roc(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.rocUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ROCP(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.rocP(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.rocPUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ROCR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.rocR(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.rocRUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ROCR100(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.rocR100(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.rocR100Unguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_RSI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        core.unstablePeriod[21] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.rsi(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.rsiUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        double optInAcceleration = jsonDouble(json, "optInAcceleration");
        double optInMaximum = jsonDouble(json, "optInMaximum");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sar(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInAcceleration,
            optInMaximum,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sarUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInAcceleration,
            optInMaximum,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SAREXT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
        }
        double optInStartValue = jsonDouble(json, "optInStartValue");
        double optInOffsetOnReverse = jsonDouble(json, "optInOffsetOnReverse");
        double optInAccelerationInitLong = jsonDouble(json, "optInAccelerationInitLong");
        double optInAccelerationLong = jsonDouble(json, "optInAccelerationLong");
        double optInAccelerationMaxLong = jsonDouble(json, "optInAccelerationMaxLong");
        double optInAccelerationInitShort = jsonDouble(json, "optInAccelerationInitShort");
        double optInAccelerationShort = jsonDouble(json, "optInAccelerationShort");
        double optInAccelerationMaxShort = jsonDouble(json, "optInAccelerationMaxShort");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sarExt(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInStartValue,
            optInOffsetOnReverse,
            optInAccelerationInitLong,
            optInAccelerationLong,
            optInAccelerationMaxLong,
            optInAccelerationInitShort,
            optInAccelerationShort,
            optInAccelerationMaxShort,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sarExtUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            optInStartValue,
            optInOffsetOnReverse,
            optInAccelerationInitLong,
            optInAccelerationLong,
            optInAccelerationMaxLong,
            optInAccelerationInitShort,
            optInAccelerationShort,
            optInAccelerationMaxShort,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SIN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sin(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sinUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SINH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sinh(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sinhUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sma(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.smaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SQRT(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sqrt(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sqrtUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_STDDEV(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double optInNbDev = jsonDouble(json, "optInNbDev");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.stdDev(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDev,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.stdDevUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDev,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_STOCH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInFastK_Period = jsonInt(json, "optInFastK_Period");
        int optInSlowK_Period = jsonInt(json, "optInSlowK_Period");
        MAType optInSlowK_MAType = MAType.values()[jsonInt(json, "optInSlowK_MAType")];
        int optInSlowD_Period = jsonInt(json, "optInSlowD_Period");
        MAType optInSlowD_MAType = MAType.values()[jsonInt(json, "optInSlowD_MAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.stoch(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInFastK_Period,
            optInSlowK_Period,
            optInSlowK_MAType,
            optInSlowD_Period,
            optInSlowD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.stochUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInFastK_Period,
            optInSlowK_Period,
            optInSlowK_MAType,
            optInSlowD_Period,
            optInSlowD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_STOCHF(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInFastK_Period = jsonInt(json, "optInFastK_Period");
        int optInFastD_Period = jsonInt(json, "optInFastD_Period");
        MAType optInFastD_MAType = MAType.values()[jsonInt(json, "optInFastD_MAType")];
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.stochF(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInFastK_Period,
            optInFastD_Period,
            optInFastD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.stochFUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInFastK_Period,
            optInFastD_Period,
            optInFastD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_STOCHRSI(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        int optInFastK_Period = jsonInt(json, "optInFastK_Period");
        int optInFastD_Period = jsonInt(json, "optInFastD_Period");
        MAType optInFastD_MAType = MAType.values()[jsonInt(json, "optInFastD_MAType")];
        core.unstablePeriod[22] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        double[] outArr1 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.stochRsi(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInFastK_Period,
            optInFastD_Period,
            optInFastD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.stochRsiUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInFastK_Period,
            optInFastD_Period,
            optInFastD_MAType,
            outBegIdx, outNBElement, outArr0, outArr1);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"outReal1\":").append(doubleArrayToJson(outArr1, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SUB(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal0 = new double[MAX_ARRAY_SIZE];
        double[] inReal1 = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal0, 0, refN);
            System.arraycopy(refHigh, 0, inReal1, 0, refN);
        } else {
            double[] _tmp_inReal0 = jsonDoubleArray(json, "inReal0");
            inReal0 = _tmp_inReal0;
            double[] _tmp_inReal1 = jsonDoubleArray(json, "inReal1");
            inReal1 = _tmp_inReal1;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sub(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.subUnguarded(
            startIdx, endIdx,
            inReal0,
            inReal1,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_SUM(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.sum(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.sumUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_T3(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double optInVFactor = jsonDouble(json, "optInVFactor");
        core.unstablePeriod[23] = jsonInt(json, "unstablePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.t3(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInVFactor,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.t3Unguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInVFactor,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TAN(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.tan(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.tanUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TANH(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.tanh(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.tanhUnguarded(
            startIdx, endIdx,
            inReal,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TEMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.tema(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.temaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TRANGE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.trueRange(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.trueRangeUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TRIMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.trima(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.trimaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TRIX(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.trix(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.trixUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TSF(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.tsf(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.tsfUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_TYPPRICE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.typPrice(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.typPriceUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_ULTOSC(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod1 = jsonInt(json, "optInTimePeriod1");
        int optInTimePeriod2 = jsonInt(json, "optInTimePeriod2");
        int optInTimePeriod3 = jsonInt(json, "optInTimePeriod3");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.ultOsc(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod1,
            optInTimePeriod2,
            optInTimePeriod3,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.ultOscUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod1,
            optInTimePeriod2,
            optInTimePeriod3,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_VAR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double optInNbDev = jsonDouble(json, "optInNbDev");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.variance(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDev,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.varianceUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            optInNbDev,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_WCLPRICE(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.wclPrice(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.wclPriceUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_WILLR(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inHigh = new double[MAX_ARRAY_SIZE];
        double[] inLow = new double[MAX_ARRAY_SIZE];
        double[] inClose = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refHigh, 0, inHigh, 0, refN);
            System.arraycopy(refLow, 0, inLow, 0, refN);
            System.arraycopy(refClose, 0, inClose, 0, refN);
        } else {
            double[] _tmp_inHigh = jsonDoubleArray(json, "inHigh");
            inHigh = _tmp_inHigh;
            double[] _tmp_inLow = jsonDoubleArray(json, "inLow");
            inLow = _tmp_inLow;
            double[] _tmp_inClose = jsonDoubleArray(json, "inClose");
            inClose = _tmp_inClose;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.willR(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.willRUnguarded(
            startIdx, endIdx,
            inHigh,
            inLow,
            inClose,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    static String handle_WMA(String json) {
        int startIdx = jsonInt(json, "startIdx");
        int endIdx = jsonInt(json, "endIdx");
        int use_preloaded = jsonInt(json, "use_preloaded");
        int bench_iters = jsonInt(json, "iters");
        if (bench_iters < 1) bench_iters = 1;
        double[] inReal = new double[MAX_ARRAY_SIZE];
        if (use_preloaded != 0 && refN > 0) {
            System.arraycopy(refClose, 0, inReal, 0, refN);
        } else {
            double[] _tmp_inReal = jsonDoubleArray(json, "inReal");
            inReal = _tmp_inReal;
        }
        int optInTimePeriod = jsonInt(json, "optInTimePeriod");
        double[] outArr0 = new double[endIdx - startIdx + 1];
        MInteger outBegIdx = new MInteger();
        MInteger outNBElement = new MInteger();
        RetCode rc = RetCode.Success;
        long startNs = System.nanoTime();
        for (int _bi = 0; _bi < bench_iters; _bi++) {
        rc = core.wma(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNs = (System.nanoTime() - startNs) / bench_iters;
        long startNsUng = System.nanoTime();
        for (int _biu = 0; _biu < bench_iters; _biu++) {
        rc = core.wmaUnguarded(
            startIdx, endIdx,
            inReal,
            optInTimePeriod,
            outBegIdx, outNBElement, outArr0);
        }
        long elapsedNsUng = (System.nanoTime() - startNsUng) / bench_iters;
        StringBuilder sb = new StringBuilder();
        sb.append("{\"retCode\":").append(rc.toInt());
        sb.append(",\"outBegIdx\":").append(outBegIdx.value);
        sb.append(",\"outNBElement\":").append(outNBElement.value);
        sb.append(",\"outReal\":").append(doubleArrayToJson(outArr0, outNBElement.value));
        sb.append(",\"timing_ns\":").append(elapsedNs);
        sb.append(",\"timing_ns_unguarded\":").append(elapsedNsUng);
        sb.append("}");
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.trim().isEmpty()) continue;
            System.out.println(handleRequest(line));
            System.out.flush();
        }
    }
}
