/*** VP = N日内成交量增加日的总成交量 VQ = N日内成交量减少日的总成交量 VRSI = 100 * VP / (VP+VQ) */ BOOL CNVRSI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dUV = 0, dV = 0, dResult = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { if( m_pKData->ElementAt(k).m_fVolume > m_pKData->ElementAt(k-1).m_fVolume ) dUV += m_pKData->ElementAt(k).m_fVolume; dV += m_pKData->ElementAt(k).m_fVolume; nCount ++; if( nCount == m_nDays ) { if( dV < 1e-4 ) dResult = 50; else dResult = 100. * dUV / dV; if( pValue ) *pValue = dResult; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** A = 当天收盘价 - 当天开盘价 B = 当天最高价 - 当天最低价 C = A÷B×V(成交量) WVAD = 累计n天的C值 */ BOOL CWVAD::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; int nCount = 0; double dResult = 0; for( int k=nIndex; k>=0; k-- ) { KDATA kd = m_pKData->ElementAt(k); if( kd.m_fHigh > kd.m_fLow ) dResult += (((double)kd.m_fClose) - kd.m_fOpen)*kd.m_fVolume/(((double)kd.m_fHigh)-kd.m_fLow); nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dResult; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** 布林带是以股价平均线MA为中心线,上方阻力线MA+αSn和下方支撑线MA-αSn之间的带状区域 其中 Sn为n日收盘价的标准差 */ BOOL CBOLL::Calculate( double * pdMA, double * pdUp, double * pdDown, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nMADays < 2 ) return FALSE; if( LoadFromCache( nIndex, pdMA, pdUp, pdDown ) ) return TRUE; double dMA = 0, dUp = 0, dDown = 0, dS = 0; if( !m_pKData->GetMA( &dMA, nIndex, m_nMADays ) ) return FALSE; int nCount = 0; for( int k=nIndex; k>=0; k-- ) { dS += (m_pKData->MaindataAt(k) - dMA) * (m_pKData->MaindataAt(k) - dMA); nCount ++; if( nCount == m_nMADays ) break; } dS = sqrt( dS / (m_nMADays-1) ); dUp = dMA + m_dMultiUp * dS; dDown = dMA - m_dMultiDown * dS; if( pdMA ) *pdMA = dMA; if( pdUp ) *pdUp = dUp; if( pdDown ) *pdDown = dDown; StoreToCache( nIndex, pdMA, pdUp, pdDown ); return TRUE; }
/*** PV就是当日成交均价,成交额除以成交量 */ BOOL CPV::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( LoadFromCache( nIndex, pValue ) ) return TRUE; KDATA kd = m_pKData->ElementAt(nIndex); if( kd.m_fVolume <= 1e-4 || kd.m_fAmount <= 1e-4 ) return FALSE; int nCount = 0; double average = ((double)(kd.m_fAmount)) / kd.m_fVolume; while( average < kd.m_fLow && nCount < 10 ) { average *= 10; nCount ++; } while( average > kd.m_fHigh && nCount < 20 ) { average /= 10; nCount ++; } if( average < kd.m_fLow ) // 说明是指数 average = (kd.m_fOpen+kd.m_fHigh+kd.m_fLow+kd.m_fClose)/4; double dPV = average; if( pValue ) *pValue = dPV; StoreToCache( nIndex, pValue ); return TRUE; }
/*** TR 为以下三者中的最大值 最高价-最低价,(昨日收盘价-今日最高价)的绝对值,昨日收盘价-昨日最低价 ATR = TR的N日平均 */ BOOL CATR::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dATR = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { KDATA kd = m_pKData->ElementAt(k); KDATA kdLast = m_pKData->ElementAt(k-1); double dTR = fabs(((double)kd.m_fHigh)-kd.m_fLow); if( fabs(((double)kdLast.m_fClose)-kd.m_fHigh) > dTR ) dTR = fabs(((double)kdLast.m_fClose)-kd.m_fHigh); if( fabs(((double)kdLast.m_fClose)-kdLast.m_fLow) > dTR ) dTR = fabs(((double)kdLast.m_fClose)-kdLast.m_fLow); dATR += dTR; nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dATR/m_nDays; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** BBI = 4 个 不同日期的MA 的平均值 */ BOOL CBBI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dResult = 0; double dTemp = 0; if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA1Days ) ) return FALSE; dResult += dTemp; if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA2Days ) ) return FALSE; dResult += dTemp; if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA3Days ) ) return FALSE; dResult += dTemp; if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA4Days ) ) return FALSE; dResult += dTemp; dResult = dResult / 4; if( pValue ) *pValue = dResult; StoreToCache( nIndex, pValue ); return TRUE; }
/*** A = 当日最高价 - 当日最低价 B = 2 * 当日收盘价 - 当日最高价 - 当日最低价 C = 当日成交量 * B / A AD = N日内C的总和 */ BOOL CAD::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dAD = 0; int nCount = 0; for( int k=nIndex; k>=0; k-- ) { KDATA kd = m_pKData->ElementAt(k); if( kd.m_fHigh-kd.m_fLow > 1e-4 ) dAD += kd.m_fVolume * (((double)kd.m_fClose)-kd.m_fLow-kd.m_fHigh+kd.m_fClose)/(((double)kd.m_fHigh)-kd.m_fLow); nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dAD; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** CI = (当日收盘价 - 当日开盘价)/(当日最高价 - 当日最低价) */ BOOL CCI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( LoadFromCache( nIndex, pValue ) ) return TRUE; KDATA kd = m_pKData->ElementAt(nIndex); if( kd.m_fHigh-kd.m_fLow < 1e-4) return FALSE; double dCI = (((double)kd.m_fClose)-kd.m_fOpen)/(((double)kd.m_fHigh)-kd.m_fLow); /* if( nIndex > 0 ) { KDATA kdLast = m_pKData->ElementAt(nIndex-1); if( max(kd.m_fOpen,kd.m_fClose) > kdLast.m_fClose*1.08 && kd.m_fHigh>kdLast.m_fClose) dCI += (2.*kd.m_fClose-kd.m_fLow-kdLast.m_fClose)/(((double)kd.m_fHigh)-kdLast.m_fClose); if( kd.m_fOpen < kdLast.m_fClose*0.92 ) dCI += (2.*kd.m_fLow-kd.m_fHigh-kdLast.m_fClose)/(((double)kd.m_fClose)-kd.m_fLow); } */ dCI = kd.m_fVolume * dCI; if( pValue ) *pValue = dCI; StoreToCache( nIndex, pValue ); return TRUE; }
/*** TP = (收盘价+收盘价+最高价+最低价)/4 HLC = N日TP平均值 */ BOOL CHLC::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dMATP = 0; int nCount = 0; for( int k=nIndex; k>=0; k-- ) { KDATA kd = m_pKData->ElementAt(k); double dTP = (kd.m_fHigh+kd.m_fLow+kd.m_fClose*2)/4.; dMATP += dTP; nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dMATP / m_nDays; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** DMH = N日内最高价大于昨日最高价日的 (最高价-昨日最高价) DML = N日内最低价小于昨日最低价日的 (昨日最低价-最低价) DMKI = DMH / (DMH+DML) */ BOOL CDMKI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dDMH = 0, dDML = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { KDATA kd = m_pKData->ElementAt(k); KDATA kdLast = m_pKData->ElementAt(k-1); if( kd.m_fHigh > kdLast.m_fHigh ) dDMH += (((double)kd.m_fHigh)-kdLast.m_fHigh); if( kd.m_fLow < kdLast.m_fLow ) dDML += (((double)kdLast.m_fLow)-kd.m_fLow); nCount ++; if( nCount == m_nDays ) { if( fabs(dDMH + dDML) < 1e-4 ) return FALSE; if( pValue ) *pValue = dDMH / (dDMH+dDML); StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** n日中上涨日成交量+1/2最近n日总成交量 VR = ————————————---------—- ×100 n日中下跌日成交量+1/2最近n日总成交量 */ BOOL CVR::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dINTV = 0, dDETV = 0, dTV = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { double dAmount = m_pKData->ElementAt(k).m_fVolume; if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) ) dINTV += dAmount; if( m_pKData->MaindataAt(k) < m_pKData->MaindataAt(k-1) ) dDETV += dAmount; dTV += dAmount; nCount ++; if( nCount == m_nDays ) { if( dDETV + dTV/2 < 1e-4 ) return FALSE; if( pValue ) *pValue = (dINTV + dTV/2) * 100 /(dDETV + dTV/2); StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** A = (今天最高 + 今天最低)÷ 2 B = (前一天最高 + 前一天最低)÷2 C = 今天最高 - 今天最低 EM = (A-B)×C÷今天成交额 EMV = 累计n天的EM值 */ BOOL CEMV::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dEMV = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { KDATA kd = m_pKData->ElementAt(k); KDATA kdLast = m_pKData->ElementAt(k-1); if( 0 == kd.m_fVolume ) return FALSE; double dDIF = 0; dDIF = (kd.m_fHigh+kd.m_fLow)/2 - (((double)kdLast.m_fHigh)+kdLast.m_fLow)/2; dEMV += dDIF * (kd.m_fHigh-kd.m_fLow) / kd.m_fVolume; nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dEMV / m_nDays; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
// 计算指标值和均值 BOOL CTechnique::CalculateMA( double * pValue, double * pMA, int nIndex, BOOL bUseLast, int nMADays ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( nMADays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue, pMA ) ) return TRUE; double dValue = 0, dMA = 0; int nCount = 0; for( int k=nIndex; k>=0; k-- ) { double dTemp = 0; if( Calculate( &dTemp, k, FALSE ) ) { if( nIndex == k ) dValue = dTemp; dMA += dTemp; nCount ++; if( nCount == nMADays ) { dMA = dMA / nMADays; if( pValue ) *pValue = dValue; if( pMA ) *pMA = dMA; StoreToCache( nIndex, pValue, pMA ); return TRUE; } } } return FALSE; }
/*** A = 今最高 - 昨收盘 B = 今最低 - 昨最低 C = 今最高 - 昨最低 D = 昨收盘 - 昨开盘 E = 今收盘 - 昨收盘 F = 今收盘 - 昨开盘 G = 昨收盘 - 昨开盘 X = E + 1/(2F) + G K = A、B二者之间较大者 比较A、B、C三者的大小 若A大,则R = A+1/(2B)+1/(4D) 若B大,则R = B+1/(2A)+1/(4D) 若C大,则R = C+1/(4D) L = 3 SI = 50·X·K/(R·L) ASI = N日SI之和 */ BOOL CASI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dASI = 0; double A, B, C, D, E, F, G; double R, X, K, SI; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { KDATA kd = m_pKData->ElementAt(k); KDATA kdLast = m_pKData->ElementAt(k-1); A = fabs(((double)kd.m_fHigh) - kdLast.m_fClose); B = fabs(((double)kd.m_fLow) - kdLast.m_fClose); C = fabs(((double)kd.m_fHigh) - kdLast.m_fLow); D = fabs(((double)kdLast.m_fClose) - kdLast.m_fOpen); E = ((double)kd.m_fClose) - kdLast.m_fClose; F = ((double)kd.m_fClose) - kd.m_fOpen; G = ((double)kdLast.m_fClose) - kdLast.m_fOpen; if( fabs(A) < 1e-4 || fabs(B) < 1e-4 || fabs(D) < 1e-4 || fabs(F) < 1e-4 ) continue; if( A >= B && A >= C ) R = A + 1/(2*B) + 1/(4*D); else if( B >= A && B >= C ) R = B + 1/(2*A) + 1/(4*D); else R = C + 1/(4*D); if( fabs(R) < 1e-4 ) continue; X = E + 1/(2*F) + G; K = ( A > B ? A : B ); SI = X * K * 50 / (3*R); dASI += SI; nCount ++; if( nCount == m_nDays ) { if( pValue ) *pValue = dASI; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
// 是否顶背离 BOOL CTechnique::IsDeviateOnTop( int nIndex, double * pdValue1, double * pdValue2 ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( !m_pKData->IsNewValue( nIndex, TRUE, ITS_DAYS_DEVIATE ) ) return FALSE; if( IsNewValue( nIndex, TRUE, ITS_DAYS_DEVIATE, pdValue1, pdValue2 ) ) return FALSE; return TRUE; }
/*** 成交量的MACD EMA = 短期移动均值 EMA2 = 长期移动均值 DIF = 短期移动均值 - 长期移动均值 DEA = DIF的移动平滑值 柱状线值 = DIF - DEA */ BOOL CVMACD::Calculate( double *pdEMA1, double *pdEMA2, double *pdDIF, double *pdDEA, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nEMA1Days > nIndex+1 || m_nEMA2Days > nIndex+1 || m_nDIFDays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pdEMA1, pdEMA2, pdDIF, pdDEA ) ) return TRUE; // Calculate EMA1, EMA2, DIF, DEA double dEMA1New = 0, dEMA2New = 0, dDIFNew = 0, dDEANew = 0; if( bUseLast && pdEMA1 && pdEMA2 && pdDEA ) { dEMA1New = (*pdEMA1)*(m_nEMA1Days-1)/(m_nEMA1Days+1) + 2 * m_pKData->ElementAt(nIndex).m_fVolume/(m_nEMA1Days+1); dEMA2New = (*pdEMA2)*(m_nEMA2Days-1)/(m_nEMA2Days+1) + 2 * m_pKData->ElementAt(nIndex).m_fVolume/(m_nEMA2Days+1); dDIFNew = dEMA1New-dEMA2New; dDEANew = (*pdDEA)*(m_nDIFDays-1)/(m_nDIFDays+1) + 2 * dDIFNew/(m_nDIFDays+1); } else { double factor1 = 1, factor2 = 1; int k; for( k=nIndex; k > 0; k-- ) { factor1 *= ((double)(m_nEMA1Days-1))/(m_nEMA1Days+1); factor2 *= ((double)(m_nEMA2Days-1))/(m_nEMA2Days+1); if( factor1 < 0.001 && factor2 < 0.001 ) // 太久以前的数据影响很小,忽略不计 break; } dEMA1New = m_pKData->ElementAt(k).m_fVolume; dEMA2New = m_pKData->ElementAt(k).m_fVolume; dDIFNew = dEMA1New - dEMA2New; dDEANew = dDIFNew; for( ; k<=nIndex; k++ ) { dEMA1New = dEMA1New * (m_nEMA1Days-1)/(m_nEMA1Days+1) + 2 * m_pKData->ElementAt(k).m_fVolume/(m_nEMA1Days+1); dEMA2New = dEMA2New * (m_nEMA2Days-1)/(m_nEMA2Days+1) + 2 * m_pKData->ElementAt(k).m_fVolume/(m_nEMA2Days+1); dDIFNew = dEMA1New - dEMA2New; dDEANew = dDEANew * (m_nDIFDays-1)/(m_nDIFDays+1) + 2 * dDIFNew / (m_nDIFDays+1); } } if( pdEMA1 ) *pdEMA1 = dEMA1New; if( pdEMA2 ) *pdEMA2 = dEMA2New; if( pdDIF ) *pdDIF = dDIFNew; if( pdDEA ) *pdDEA = dDEANew; StoreToCache( nIndex, pdEMA1, pdEMA2, pdDIF, pdDEA ); return TRUE; }
/*** NVI初值 = 100 如果今天成交量比昨日小 NVI = 前一日NVI + 100 * 涨跌幅 否则,NVI = 前一天NVI */ BOOL CNVI::Calculate( double * pValue, double *pMA, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); // Calculate if( m_nMADays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue, pMA ) ) return TRUE; double dValueNew = 0, dMANew = 0; if( bUseLast && pValue && pMA ) { if( 0 == nIndex ) dValueNew = 100; else if( m_pKData->ElementAt(nIndex).m_fVolume < m_pKData->ElementAt(nIndex-1).m_fVolume && m_pKData->MaindataAt(nIndex-1) > 1e-4 && m_pKData->MaindataAt(nIndex) > 1e-4 ) dValueNew = (*pValue) * m_pKData->MaindataAt(nIndex) / m_pKData->MaindataAt(nIndex-1); else dValueNew = *pValue; dMANew = (*pMA) * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1); StoreToCache( nIndex, &dValueNew, &dMANew ); } else { for( int k=0; k<=nIndex; k++ ) { if( 0 == k ) dValueNew = 100; else if( m_pKData->ElementAt(k).m_fVolume < m_pKData->ElementAt(k-1).m_fVolume && m_pKData->MaindataAt(k-1) > 1e-4 && m_pKData->MaindataAt(k) > 1e-4 ) dValueNew = dValueNew * m_pKData->MaindataAt(k) / m_pKData->MaindataAt(k-1); if( 0 == k ) dMANew = dValueNew; else dMANew = dMANew * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1); StoreToCache( k, &dValueNew, &dMANew ); } } if( pValue ) *pValue = dValueNew; if( pMA ) *pMA = dMANew; return TRUE; }
/*** DIF1 = 今日最高价 - 2日前最高价 DIF2 = 今日最低价 - 2日前最低价 A = N日内除满足以下情况日的(DIF1+DIF2)之和 1. 2日前最高价 小于 7日前收盘价 2. 2日前最高价 小于 8日前收盘价 3. 今日前最高价 小于 5日前最低价 4. 今日前最高价 小于 6日前最低价 5. 2日前最低价 小于 7日前收盘价 6. 2日前最低价 小于 8日前收盘价 7. 今日前最低价 小于 5日前最高价 8. 今日前最低价 小于 6日前最高价 REIA = N日的DIF1绝对值之和 + N日的DIF2绝对值之和 REI = A / REIA */ BOOL CREI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays+7 > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dREI = 0, dREIA = 0; int nCount = 0; for( int k=nIndex; k>=8; k-- ) { double dDIF1 = 0, dDIF2 = 0; int num1 = 1, num2 = 1; dDIF1 = ((double)m_pKData->ElementAt(k).m_fHigh) - m_pKData->ElementAt(k-2).m_fHigh; dDIF2 = ((double)m_pKData->ElementAt(k).m_fLow) - m_pKData->ElementAt(k-2).m_fLow; if( m_pKData->ElementAt(k-2).m_fHigh < m_pKData->ElementAt(k-7).m_fClose && m_pKData->ElementAt(k-2).m_fHigh < m_pKData->ElementAt(k-8).m_fClose && m_pKData->ElementAt(k).m_fHigh < m_pKData->ElementAt(k-5).m_fLow && m_pKData->ElementAt(k).m_fHigh < m_pKData->ElementAt(k-6).m_fLow ) num1 = 0; if( m_pKData->ElementAt(k-2).m_fLow > m_pKData->ElementAt(k-7).m_fClose && m_pKData->ElementAt(k-2).m_fLow > m_pKData->ElementAt(k-8).m_fClose && m_pKData->ElementAt(k).m_fLow > m_pKData->ElementAt(k-5).m_fHigh && m_pKData->ElementAt(k).m_fLow > m_pKData->ElementAt(k-6).m_fHigh ) num2 = 0; dREI += (dDIF1+dDIF2) * num1 * num2; dREIA += fabs(dDIF1) + fabs(dDIF2); nCount ++; if( nCount == m_nDays ) { if( fabs(dREIA) < 1e-4 ) return FALSE; if( pValue ) *pValue = dREI / dREIA; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** TP = (昨日收盘价+昨日收盘价+昨日最高价+昨日最低价)/4 AH = TP + 昨日最高价 - 昨日最低价 AL = TP - 最日最高价 + 昨日最低价 NH = TP + TP - 最日最低价 NL = TP + TP - 最日最高价 */ BOOL CCDP::Calculate( double * pAH, double * pNH, double * pAL, double * pNL, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( nIndex < 1 ) return FALSE; if( LoadFromCache( nIndex, pAH, pNH, pAL, pNL ) ) return TRUE; KDATA kdLast = m_pKData->ElementAt(nIndex-1); double dTP = (kdLast.m_fHigh+kdLast.m_fLow+kdLast.m_fClose*2)/4.; if( pAH ) *pAH = (dTP + kdLast.m_fHigh - kdLast.m_fLow); if( pNH ) *pNH = (dTP + dTP - kdLast.m_fLow); if( pAL ) *pAL = (dTP - kdLast.m_fHigh + kdLast.m_fLow); if( pNL ) *pNL = (dTP - kdLast.m_fHigh + dTP); StoreToCache( nIndex, pAH, pNH, pAL, pNL ); return TRUE; }
/*** *pValue1 = 当日OBV *pValue2 = m_nDays1日OBV平均值 *pValue3 = m_nDays2日OBV平均值 */ BOOL CMOBV::Calculate( double * pValue1, double * pValue2, double * pValue3, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); int nMaxDays = max(m_nDays1,m_nDays2); if( nMaxDays > nIndex+1 ) return FALSE; if( LoadFromCache( nIndex, pValue1, pValue2, pValue3 ) ) return TRUE; double dOBV = 0, dMOBV1 = 0, dMOBV2 = 0; int nCount = 0; BOOL bHasLast = bUseLast; for( int k=nIndex; k>=0; k-- ) { double dTemp = 0; if( bUseLast && nIndex == k && pValue1 ) dTemp = *pValue1; if( COBV::Calculate( &dTemp, k, bUseLast && nIndex == k && pValue1 ) ) { if( nIndex == k ) dOBV = dTemp; if( nCount < m_nDays1 ) dMOBV1 += dTemp; if( nCount < m_nDays2 ) dMOBV2 += dTemp; nCount ++; if( nCount >= m_nDays1 && nCount >= m_nDays2 ) { if( pValue1 ) *pValue1 = dOBV; if( pValue2 ) *pValue2 = dMOBV1 / m_nDays1; if( pValue3 ) *pValue3 = dMOBV2 / m_nDays2; StoreToCache( nIndex, pValue1, pValue2, pValue3 ); return TRUE; } } } return FALSE; }
/*** VP = N日内成交量增加日的平均成交量 VQ = N日内成交量减少日的平均成交量 VRSI = 100 * VP / (VP+VQ) */ BOOL CVRSI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dVP = 0, dVQ = 0, dResult = 0; int nCount = 0, p = 0, q = 0; for( int k=nIndex; k>=1; k-- ) { if( m_pKData->MaindataAt(k) >= m_pKData->MaindataAt(k-1) ) { dVP += m_pKData->ElementAt(k).m_fVolume; p ++; } else { dVQ += m_pKData->ElementAt(k).m_fVolume; q ++; } nCount ++; if( nCount == m_nDays ) { if( p > 0 ) dVP = dVP / p; if( q > 0 ) dVQ = dVQ / q; if( dVQ < 1e-4 ) dResult = 100; else dResult = 100 - 100. / (1 + dVP / dVQ); if( pValue ) *pValue = dResult; StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
/*** 今日成交量-n日前成交量 VROC = ---------------------- * 100 今日成交量 */ BOOL CVROC::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; if( m_pKData->ElementAt(nIndex-m_nDays).m_fVolume <= 0 || m_pKData->ElementAt(nIndex).m_fVolume <= 0 ) return FALSE; double x = m_pKData->ElementAt(nIndex).m_fVolume; double y = m_pKData->ElementAt(nIndex-m_nDays).m_fVolume; if( pValue ) *pValue = (x - y) * 100 / y; StoreToCache( nIndex, pValue ); return TRUE; }
/*** 当日收盘价比前一日收盘价高,其成交量记为正数 当日收盘价较前一日收盘价低,其成交量记为负数 累计每日之正或负成交量,即得OBV值 */ BOOL COBV::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( LoadFromCache( nIndex, pValue ) ) return TRUE; // Calculate double dValueNew = 0; if( bUseLast && pValue ) { if( 0 == nIndex ) dValueNew = m_pKData->ElementAt(nIndex).m_fVolume; else if( m_pKData->MaindataAt(nIndex) > m_pKData->MaindataAt(nIndex-1) ) dValueNew = *pValue + m_pKData->ElementAt(nIndex).m_fVolume; else if( m_pKData->MaindataAt(nIndex) < m_pKData->MaindataAt(nIndex-1) ) dValueNew = *pValue - m_pKData->ElementAt(nIndex).m_fVolume; else dValueNew = *pValue; StoreToCache( nIndex, &dValueNew ); } else { for( int k=0; k<=nIndex; k++ ) { if( 0 == k ) dValueNew = m_pKData->ElementAt(k).m_fVolume; else if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) ) dValueNew += m_pKData->ElementAt(k).m_fVolume; else if( m_pKData->MaindataAt(k) < m_pKData->MaindataAt(k-1) ) dValueNew -= m_pKData->ElementAt(k).m_fVolume; StoreToCache( k, &dValueNew ); } } if( pValue ) *pValue = dValueNew; return TRUE; }
/*** 今日收盘 - N日前收盘 PCNT = ———————————— × 100% 昨日收盘 */ BOOL CPCNT::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( LoadFromCache( nIndex, pValue ) ) return TRUE; int nDays = 1; // same as ROC with m_nDays==1 if( nDays > nIndex ) return FALSE; double dROC = 0; if( m_pKData->MaindataAt(nIndex-nDays) <= 0 || m_pKData->MaindataAt(nIndex) <= 0 ) return FALSE; double x = m_pKData->MaindataAt(nIndex); double y = m_pKData->MaindataAt(nIndex-nDays); if( pValue ) *pValue = (x - y) * 100 / y; StoreToCache( nIndex, pValue ); return TRUE; }
/*** PMF 和 NMF 如下计算: TP = (High+Low+Close)/3 当日的中间价 PMF = n日内,TP上涨日的 (TP*成交量) 之和。 NMF = n日内,TP下降日的 (TP*成交量) 之和。 MFI = 100 * PMF / (PMF + NMF) 备注:MR = PMF/NMF */ BOOL CMFI::Calculate( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nDays > nIndex ) return FALSE; if( LoadFromCache( nIndex, pValue ) ) return TRUE; double dPMF = 0, dNMF = 0; int nCount = 0; for( int k=nIndex; k>=1; k-- ) { KDATA kd = m_pKData->ElementAt(k); KDATA kdLast = m_pKData->ElementAt(k-1); double dTP = (kd.m_fHigh+kd.m_fLow+kd.m_fClose)/3.; double dTPLast = (kdLast.m_fHigh+kdLast.m_fLow+kdLast.m_fClose)/3.; if( dTP > dTPLast ) dPMF += dTP * kd.m_fVolume; if( dTPLast > dTP ) dNMF += dTP * kd.m_fVolume; nCount ++; if( nCount == m_nDays ) { if( fabs(dPMF+dNMF) < 1e-4 ) return FALSE; if( pValue ) *pValue = 100 * dPMF / (dPMF + dNMF); StoreToCache( nIndex, pValue ); return TRUE; } } return FALSE; }
BOOL CSAR::CalculateSAR( double * pValue, int nIndex, BOOL bUseLast ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nInitDays > nIndex + 1 ) return FALSE; double dResult = 0; if( bUseLast && pValue && nIndex > 0 && !m_bTurn ) { KDATA kd = m_pKData->ElementAt(nIndex-1); if( m_bCurUp ) { dResult = (*pValue) + m_dCurAF * (kd.m_fHigh - (*pValue) ); if( kd.m_fHigh > m_dCurHigh ) { m_dCurHigh = kd.m_fHigh; m_dCurAF = m_dCurAF + m_dAFStep; if( m_dCurAF > m_dAFMax ) m_dCurAF = m_dAFMax; } if( m_pKData->ElementAt(nIndex).m_fLow < dResult ) m_bTurn = TRUE; } else { dResult = (*pValue) - m_dCurAF * ((*pValue) - kd.m_fLow ); if( kd.m_fLow < m_dCurLow ) { m_dCurLow = kd.m_fLow; m_dCurAF = m_dCurAF + m_dAFStep; if( m_dCurAF > m_dAFMax ) m_dCurAF = m_dAFMax; } if( m_pKData->ElementAt(nIndex).m_fHigh > dResult ) m_bTurn = TRUE; } } else { for( int k=nIndex; k>=nIndex-m_nInitDays+1; k-- ) { KDATA kd = m_pKData->ElementAt(k); if( nIndex == k ) { m_dCurHigh = kd.m_fHigh; m_dCurLow = kd.m_fLow; } else if( kd.m_fHigh > m_dCurHigh ) m_dCurHigh = kd.m_fHigh; else if( kd.m_fLow < m_dCurLow ) m_dCurLow = kd.m_fLow; } if( m_bTurn ) m_bCurUp = ! m_bCurUp; else m_bCurUp = m_bFirstUp; m_bTurn = FALSE; m_dCurAF = m_dAFStep; if( m_bCurUp ) dResult = m_dCurLow; else dResult = m_dCurHigh; } if( pValue ) *pValue = dResult; return TRUE; }
// 将计算好的数据保存至缓冲区 BOOL CTechnique::StoreToCache( int nIndex, double * pValue1, double *pValue2, double *pValue3, double * pValue4, double * pValue5 ) { STT_ASSERT_CALCULATE1( m_pKData, nIndex ); if( m_nLength <= 0 || m_nIndexStart < 0 ) { m_nLength = ( NULL!=m_pKData ? m_pKData->GetSize() : 0 ); if( m_nLength > 0 ) m_nIndexStart = 0; } if( m_nLength <= 0 || m_nIndexStart < 0 ) return FALSE; // Realocate if( pValue1 ) { if( !m_pdCache1 ) m_pdCache1 = new double[m_nLength]; if( !m_pbHasCache1 ) { m_pbHasCache1 = new BOOL[m_nLength]; if( !m_pbHasCache1 ) return FALSE; for( int i=0; i<m_nLength; i++ ) m_pbHasCache1[i] = FALSE; } if( NULL == m_pbHasCache1 || NULL == m_pdCache1 ) return FALSE; } if( pValue2 ) { if( !m_pdCache2 ) m_pdCache2 = new double[m_nLength]; if( !m_pbHasCache2 ) { m_pbHasCache2 = new BOOL[m_nLength]; if( !m_pbHasCache2 ) return FALSE; for( int i=0; i<m_nLength; i++ ) m_pbHasCache2[i] = FALSE; } if( NULL == m_pbHasCache2 || NULL == m_pdCache2 ) return FALSE; } if( pValue3 ) { if( !m_pdCache3 ) m_pdCache3 = new double[m_nLength]; if( !m_pbHasCache3 ) { m_pbHasCache3 = new BOOL[m_nLength]; if( !m_pbHasCache3 ) return FALSE; for( int i=0; i<m_nLength; i++ ) m_pbHasCache3[i] = FALSE; } if( NULL == m_pbHasCache3 || NULL == m_pdCache3 ) return FALSE; } if( pValue4 ) { if( !m_pdCache4 ) m_pdCache4 = new double[m_nLength]; if( !m_pbHasCache4 ) { m_pbHasCache4 = new BOOL[m_nLength]; if( !m_pbHasCache4 ) return FALSE; for( int i=0; i<m_nLength; i++ ) m_pbHasCache4[i] = FALSE; } if( NULL == m_pbHasCache4 || NULL == m_pdCache4 ) return FALSE; } if( pValue5 ) { if( !m_pdCache5 ) m_pdCache5 = new double[m_nLength]; if( !m_pbHasCache5 ) { m_pbHasCache5 = new BOOL[m_nLength]; if( !m_pbHasCache5 ) return FALSE; for( int i=0; i<m_nLength; i++ ) m_pbHasCache5[i] = FALSE; } if( NULL == m_pbHasCache5 || NULL == m_pdCache5 ) return FALSE; } if( nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength ) return FALSE; // Store if( pValue1 && m_pdCache1 && m_pbHasCache1 ) { m_pdCache1[nIndex-m_nIndexStart] = *pValue1; m_pbHasCache1[nIndex-m_nIndexStart] = TRUE; } if( pValue2 && m_pdCache2 && m_pbHasCache2 ) { m_pdCache2[nIndex-m_nIndexStart] = *pValue2; m_pbHasCache2[nIndex-m_nIndexStart] = TRUE; } if( pValue3 && m_pdCache3 && m_pbHasCache3 ) { m_pdCache3[nIndex-m_nIndexStart] = *pValue3; m_pbHasCache3[nIndex-m_nIndexStart] = TRUE; } if( pValue4 && m_pdCache4 && m_pbHasCache4 ) { m_pdCache4[nIndex-m_nIndexStart] = *pValue4; m_pbHasCache4[nIndex-m_nIndexStart] = TRUE; } if( pValue5 && m_pdCache5 && m_pbHasCache5 ) { m_pdCache5[nIndex-m_nIndexStart] = *pValue5; m_pbHasCache5[nIndex-m_nIndexStart] = TRUE; } return TRUE; }