📄 techenergy.cpp.svn-base
字号:
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;
}
BOOL CVROC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
{
return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
}
//////////////////////////////////////////////////////////////////////
// COBV
COBV::COBV( )
{
SetDefaultParameters( );
}
COBV::COBV( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
COBV::~COBV()
{
Clear( );
}
void COBV::SetDefaultParameters( )
{
m_itsDeviateOnBottom = ITS_BUY;
m_itsDeviateOnTop = ITS_SELL;
}
void COBV::AttachParameters( COBV & src )
{
m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
m_itsDeviateOnTop = src.m_itsDeviateOnTop;
}
BOOL COBV::IsValidParameters( )
{
return ( VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop) );
}
void COBV::Clear( )
{
CTechnique::Clear( );
}
int COBV::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
PrepareCache( 0, -1, FALSE );
if( IsDeviateOnBottom( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 底背离
if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
return m_itsDeviateOnBottom;
}
if( IsDeviateOnTop( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 顶背离
if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
return m_itsDeviateOnTop;
}
return ITS_NOTHING;
}
BOOL COBV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
}
/***
当日收盘价比前一日收盘价高,其成交量记为正数
当日收盘价较前一日收盘价低,其成交量记为负数
累计每日之正或负成交量,即得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;
}
//////////////////////////////////////////////////////////////////////
// CMOBV
CMOBV::CMOBV( )
{
SetDefaultParameters( );
}
CMOBV::CMOBV( CKData * pKData )
: COBV( pKData )
{
SetDefaultParameters( );
}
CMOBV::~CMOBV()
{
Clear( );
}
void CMOBV::SetDefaultParameters( )
{
COBV::SetDefaultParameters();
m_nDays1 = 12;
m_nDays2 = 26;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CMOBV::AttachParameters( CMOBV & src )
{
COBV::AttachParameters( src );
m_nDays1 = src.m_nDays1;
m_nDays2 = src.m_nDays2;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CMOBV::IsValidParameters( )
{
return ( COBV::IsValidParameters()
&& VALID_DAYS(m_nDays1) && VALID_DAYS(m_nDays2)
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CMOBV::Clear( )
{
CTechnique::Clear( );
}
int CMOBV::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
if( !m_pKData || nIndex < 0 || nIndex >= m_pKData->GetSize() )
return ITS_NOTHING;
PrepareCache( 0, -1, FALSE );
int nMaxDays = max( m_nDays1 , m_nDays2 );
double dLiminalLow = 0, dLiminalHigh = 0;
if( !IntensityPreparePrice( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.5, 0.5 ) )
return ITS_NOTHING;
double dPriceNow = m_pKData->MaindataAt(nIndex);
if( dPriceNow < dLiminalLow
&& ( IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) || IsGoldenFork( nIndex, m_pdCache2, m_pdCache3 ) ) )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dPriceNow > dLiminalHigh
&& ( IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) || IsDeadFork( nIndex, m_pdCache2, m_pdCache3 ) ) )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CMOBV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
}
/***
*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;
}
//////////////////////////////////////////////////////////////////////
// CMFI
CMFI::CMFI( )
{
SetDefaultParameters( );
}
CMFI::CMFI( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CMFI::~CMFI()
{
Clear( );
}
void CMFI::SetDefaultParameters( )
{
m_nDays = 10;
m_itsLong = ITS_BUY;
m_itsShort = ITS_SELL;
}
void CMFI::AttachParameters( CMFI & src )
{
m_nDays = src.m_nDays;
m_itsLong = src.m_itsLong;
m_itsShort = src.m_itsShort;
}
BOOL CMFI::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
}
void CMFI::Clear( )
{
CTechnique::Clear( );
}
int CMFI::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
double dValue = 0;
if( !Calculate( &dValue, nIndex, FALSE ) )
return ITS_NOTHING;
if( dValue <= 20 )
{ // 低位
if( pnCode ) *pnCode = ITSC_LONG;
return m_itsLong;
}
if( dValue >= 80 )
{ // 高位
if( pnCode ) *pnCode = ITSC_SHORT;
return m_itsShort;
}
return ITS_NOTHING;
}
BOOL CMFI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
if( pdMin ) *pdMin = 0;
if( pdMax ) *pdMax = 100;
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;
}
//////////////////////////////////////////////////////////////////////
// CVMACD
CVMACD::CVMACD( )
{
SetDefaultParameters( );
}
CVMACD::CVMACD( CKData * pKData )
: CMACD( pKData )
{
SetDefaultParameters( );
}
CVMACD::~CVMACD()
{
Clear( );
}
/***
成交量的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;
}
//////////////////////////////////////////////////////////////////////
// CWVAD
CWVAD::CWVAD( )
{
SetDefaultParameters( );
}
CWVAD::CWVAD( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CWVAD::~CWVAD()
{
Clear( );
}
void CWVAD::SetDefaultParameters( )
{
m_nDays = 24;
m_itsLong = ITS_BUY;
m_itsShort = ITS_SELL;
}
void CWVAD::AttachParameters( CWVAD & src )
{
m_nDays = src.m_nDays;
m_itsLong = src.m_itsLong;
m_itsShort = src.m_itsShort;
}
BOOL CWVAD::IsValidParameters( )
{
return ( VALID_DAYS( m_nDays )
&& VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
}
void CWVAD::Clear( )
{
CTechnique::Clear( );
}
int CWVAD::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
int nMaxDays = m_nDays;
double dLiminalLow = 0, dLiminalHigh = 0;
if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
return ITS_NOTHING;
if( nIndex <= 0 )
return ITS_NOTHING;
double dLast, dNow;
if( !Calculate( &dLast, nIndex-1, FALSE )
|| !Calculate( &dNow, nIndex, FALSE ) )
return ITS_NOTHING;
if( dNow < dLiminalLow )
{ // 低位
if( pnCode ) *pnCode = ITSC_LONG;
return m_itsLong;
}
if( dNow > dLiminalHigh )
{ // 高位
if( pnCode ) *pnCode = ITSC_SHORT;
return m_itsShort;
}
return ITS_NOTHING;
}
BOOL CWVAD::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -