/* This function is suppose to fill the buffer * with values going from 0 to 'size'. * The filling is done using the CIRCBUF macros. */ static TA_RetCode circBufferFillFrom0ToSize( int size, int *buffer ) { CIRCBUF_PROLOG(MyBuf,int,4); int i, value; int outIdx; CIRCBUF_CONSTRUCT(MyBuf,int,size); outIdx = 0; // 1st Loop: Fill MyBuf with initial values // (must be done). value = 0; for( i=0; i < size; i++ ) { MyBuf[MyBuf_Idx] = value++; CIRCBUF_NEXT(MyBuf); } // 2nd Loop: Get and Add subsequent values // in MyBuf (optional) for( i=0; i < 3; i++ ) { buffer[outIdx++] = MyBuf[MyBuf_Idx]; MyBuf[MyBuf_Idx] = value++; CIRCBUF_NEXT(MyBuf); } // 3rd Loop: Empty MyBuf (optional) for( i=0; i < size; i++ ) { buffer[outIdx++] = MyBuf[MyBuf_Idx]; CIRCBUF_NEXT(MyBuf); } CIRCBUF_DESTROY(MyBuf); return TA_SUCCESS; }
TA_RetCode TA_MFI( TA_Integer startIdx, TA_Integer endIdx, const TA_Real inHigh_0[], const TA_Real inLow_0[], const TA_Real inClose_0[], const TA_Integer inVolume_0[], TA_Integer optInTimePeriod_0, /* From 2 to TA_INTEGER_MAX */ TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Real outReal_0[] ) /**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/ { /* insert local variable here */ TA_Real posSumMF, negSumMF, prevValue; TA_Real tempValue1, tempValue2; int lookbackTotal, outIdx, i, today; CIRCBUF_PROLOG( mflow, MoneyFlow, 50 ); /* Id, Type, Static Size */ /**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/ #ifndef TA_FUNC_NO_RANGE_CHECK /* Validate the requested output range. */ if( startIdx < 0 ) return TA_OUT_OF_RANGE_START_INDEX; if( (endIdx < 0) || (endIdx < startIdx)) return TA_OUT_OF_RANGE_END_INDEX; /* Validate the parameters. */ /* Verify required price component. */ if(!inHigh_0||!inLow_0||!inClose_0||!inVolume_0) return TA_BAD_PARAM; /* min/max are checked for optInTimePeriod_0. */ if( (TA_Integer)optInTimePeriod_0 == TA_INTEGER_DEFAULT ) optInTimePeriod_0 = 14; else if( ((TA_Integer)optInTimePeriod_0 < 2) || ((TA_Integer)optInTimePeriod_0 > 2147483647) ) return TA_BAD_PARAM; if( outReal_0 == NULL ) return TA_BAD_PARAM; #endif /* TA_FUNC_NO_RANGE_CHECK */ /**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/ /* Insert TA function code here. */ CIRCBUF_CONSTRUCT( mflow, MoneyFlow, optInTimePeriod_0 ); *outBegIdx = 0; *outNbElement = 0; /* Adjust startIdx to account for the lookback period. */ lookbackTotal = optInTimePeriod_0 + TA_Globals.unstablePeriod[TA_FUNC_UNST_MFI]; if( startIdx < lookbackTotal ) startIdx = lookbackTotal; /* Make sure there is still something to evaluate. */ if( startIdx > endIdx ) { CIRCBUF_DESTROY(mflow); return TA_SUCCESS; } outIdx = 0; /* Index into the output. */ /* Accumulate the positive and negative money flow * among the initial period. */ today = startIdx-lookbackTotal; prevValue = (inHigh_0[today]+inLow_0[today]+inClose_0[today])/3.0; posSumMF = 0.0; negSumMF = 0.0; today++; for( i=optInTimePeriod_0; i > 0; i-- ) { tempValue1 = (inHigh_0[today]+inLow_0[today]+inClose_0[today])/3.0; tempValue2 = tempValue1 - prevValue; prevValue = tempValue1; tempValue1 *= inVolume_0[today++]; if( tempValue2 < 0 ) { mflow[mflow_Idx].negative = tempValue1; negSumMF += tempValue1; mflow[mflow_Idx].positive = 0.0; } else { mflow[mflow_Idx].positive = tempValue1; posSumMF += tempValue1; mflow[mflow_Idx].negative = 0.0; } CIRCBUF_NEXT(mflow); } /* 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 ) outReal_0[outIdx++] = 100.0*(posSumMF/(posSumMF+negSumMF)); else { /* Skip the unstable period. Do the processing * but do not write it in the output. */ while( today < startIdx ) { posSumMF -= mflow[mflow_Idx].positive; negSumMF -= mflow[mflow_Idx].negative; tempValue1 = (inHigh_0[today]+inLow_0[today]+inClose_0[today])/3.0; tempValue2 = tempValue1 - prevValue; prevValue = tempValue1; tempValue1 *= inVolume_0[today++]; if( tempValue2 < 0 ) { mflow[mflow_Idx].negative = tempValue1; negSumMF += tempValue1; mflow[mflow_Idx].positive = 0.0; } else { mflow[mflow_Idx].positive = tempValue1; posSumMF += tempValue1; mflow[mflow_Idx].negative = 0.0; } CIRCBUF_NEXT(mflow); } } /* Unstable period skipped... now continue * processing if needed. */ while( today <= endIdx ) { posSumMF -= mflow[mflow_Idx].positive; negSumMF -= mflow[mflow_Idx].negative; tempValue1 = (inHigh_0[today]+inLow_0[today]+inClose_0[today])/3.0; tempValue2 = tempValue1 - prevValue; prevValue = tempValue1; tempValue1 *= inVolume_0[today++]; if( tempValue2 < 0 ) { mflow[mflow_Idx].negative = tempValue1; negSumMF += tempValue1; mflow[mflow_Idx].positive = 0.0; } else { mflow[mflow_Idx].positive = tempValue1; posSumMF += tempValue1; mflow[mflow_Idx].negative = 0.0; } outReal_0[outIdx++] = 100.0*(posSumMF/(posSumMF+negSumMF)); CIRCBUF_NEXT(mflow); } CIRCBUF_DESTROY(mflow); *outBegIdx = startIdx; *outNbElement = outIdx; return TA_SUCCESS; }