📄 techswing.cpp
字号:
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CMTM::Clear( )
{
CTechnique::Clear( );
}
int CMTM::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
int nMaxDays = m_nDays + m_nMADays;
double dLiminalLow = 0, dLiminalHigh = 0;
if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.3, 0.6 ) )
return ITS_NOTHING;
double dMTM, dMA;
if( !Calculate( &dMTM, &dMA, nIndex, FALSE ) )
return ITS_NOTHING;
if( dMTM < dLiminalLow && dMA < dLiminalLow && IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dMTM > dLiminalHigh && dMA > dLiminalHigh && IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CMTM::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
}
/***
MTM = C/Cn
其中:C为当日收市价,Cn为N日前收市价,
N为设定参数,一般选设10日,亦可在6日至14日之间选择。
*/
BOOL CMTM::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->MaindataAt(nIndex-m_nDays) > 0 )
{
if( pValue )
*pValue = 100. * m_pKData->MaindataAt(nIndex) / m_pKData->MaindataAt(nIndex-m_nDays);
StoreToCache( nIndex, pValue );
return TRUE;
}
return FALSE;
}
BOOL CMTM::Calculate( double * pValue, double *pMA, int nIndex, BOOL bUseLast )
{
return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
}
//////////////////////////////////////////////////////////////////////
// CDMI
CDMI::CDMI( )
{
SetDefaultParameters( );
m_pdDMICache = NULL;
m_pnDMICacheIndex = NULL;
m_nDMICacheCurrent = -1;
}
CDMI::CDMI( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
m_pdDMICache = NULL;
m_pnDMICacheIndex = NULL;
m_nDMICacheCurrent = -1;
}
CDMI::~CDMI()
{
Clear( );
}
void CDMI::SetDefaultParameters( )
{
m_nDays = 7;
}
void CDMI::AttachParameters( CDMI & src )
{
m_nDays = src.m_nDays;
}
BOOL CDMI::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) );
}
void CDMI::Clear( )
{
CTechnique::Clear( );
if( m_pdDMICache )
{
delete [] m_pdDMICache;
m_pdDMICache = NULL;
}
if( m_pnDMICacheIndex )
{
delete [] m_pnDMICacheIndex;
m_pnDMICacheIndex = NULL;
}
m_nDMICacheCurrent = -1;
}
/***
求出真正波幅TR,TR是下列三者中绝对值最大的一个:
昨收盘-今 最高、昨收盘-今最低、今最高-今最低
+DM = 今最高-昨最高
-DM = 昨最低-今最低
*/
BOOL CDMI::CalculateDM( double *pDMPlus, double *pDMMinus, double *pTR, int nIndex )
{
STT_ASSERT_CALCULATE1( m_pKData, nIndex );
if( nIndex < 1 )
return FALSE;
double dDMPlus = 0, dDMMinus = 0, dTR = 0;
KDATA kdNow = m_pKData->ElementAt(nIndex);
KDATA kdLast = m_pKData->ElementAt(nIndex-1);
dDMPlus = max( 0, ((double)kdNow.m_fHigh) - kdLast.m_fHigh );
dDMMinus = max( 0, ((double)kdLast.m_fLow) - kdNow.m_fLow );
dTR = max( fabs(((double)kdNow.m_fClose)-kdNow.m_fLow), fabs(((double)kdNow.m_fHigh)-kdLast.m_fClose) );
dTR = max( dTR, fabs(((double)kdNow.m_fLow)-kdLast.m_fClose) );
if( pDMPlus ) *pDMPlus = dDMPlus;
if( pDMMinus ) *pDMMinus = dDMMinus;
if( pTR ) *pTR = dTR;
return TRUE;
}
/***
TRn = N天TR之和
+DMn = N天+DM之和
-DMn = N天-DM之和
+DI = (+DMn ÷ TRn)×100
-DI = (-DMn ÷ TRn)×100
DI差 = +DI-(-DI)
DI和 = +DI+(-DI)
DX = (DI差÷DI和)×100
*/
BOOL CDMI::CalculateDIDX( double *pDIPlus, double *pDIMinus, double *pDX, int nIndex, int nDays )
{
STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
if( m_nDays > nIndex )
return FALSE;
double dDX, dADX = 0;
double dDIPlus = 0, dDIMinus = 0, dTRSum = 0;
int nCount = 0;
for( int k=nIndex; k>=1; k-- )
{
double dDMPlus = 0, dDMMinus = 0, dTR = 0;
if( !CalculateDM( &dDMPlus, &dDMMinus, &dTR, k ) )
return FALSE;
dDIPlus += dDMPlus;
dDIMinus += dDMMinus;
dTRSum += dTR;
nCount ++;
if( nCount == nDays )
{
if( fabs(dTRSum) < 1e-4 || fabs(dDIPlus+dDIMinus) < 1e-4 )
return FALSE;
dDIPlus = (dDIPlus * 100/dTRSum);
dDIMinus = (dDIMinus * 100/dTRSum);
dDX = fabs(dDIPlus-dDIMinus) * 100 / (dDIPlus+dDIMinus);
if( pDIPlus ) *pDIPlus = dDIPlus;
if( pDIMinus ) *pDIMinus = dDIMinus;
if( pDX ) *pDX = dDX;
return TRUE;
}
}
return FALSE;
}
int CDMI::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
/* PrepareCache( 0, -1, FALSE );
if( nIndex <= 0 )
return ITS_NOTHING;
double dDIPlus, dDIMinus, dADX, dADXR;
double dDIPlusLast, dDIMinusLast, dADXLast, dADXRLast;
if( !Calculate( &dDIPlusLast, &dDIMinusLast, &dADXLast, &dADXRLast, nIndex-1, FALSE )
|| !Calculate( &dDIPlus, &dDIMinus, &dADX, &dADXR, nIndex, FALSE ) )
return ITS_NOTHING;
if( dDIPlusLast < dDIMinusLast && dDIPlus > dDIMinus )
{
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dDIMinusLast < dDIPlusLast && dDIMinus > dDIPlus )
{
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
*/
// 无买卖信号
return ITS_NOTHING;
}
BOOL CDMI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo4( nStart, nEnd, pdMin, pdMax, this );
}
/***
求出真正波幅TR,TR是下列三者中绝对值最大的一个:
昨收盘-今 最高、昨收盘-今最低、今最高-今最低
+DM = 今最高-昨最高
-DM = 昨最低-今最低
TRn = N天TR之和
+DMn = N天+DM之和
-DMn = N天-DM之和
+DI = (+DMn ÷ TRn)×100
-DI = (-DMn ÷ TRn)×100
DI差 = +DI-(-DI)
DI和 = +DI+(-DI)
DX = (DI差÷DI和)×100
ADX = DX的平滑均值
ADXR = ADX的均值
*/
BOOL CDMI::Calculate( double * pDIPlus, double * pDIMinus, double *pADX, double *pADXR, int nIndex, BOOL bUseLast )
{
STT_ASSERT_CALCULATE1( m_pKData, nIndex );
if( m_nDays > nIndex )
return FALSE;
if( LoadFromCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR ) )
return TRUE;
double dDX = 0, dADX = 0, dADXR = 0;
if( !CalculateDIDX( pDIPlus, pDIMinus, &dDX, nIndex, m_nDays ) )
return FALSE;
if( NULL == m_pdDMICache )
{
m_pdDMICache = new double[m_nDays];
m_pnDMICacheIndex = new int[m_nDays];
if( NULL == m_pdDMICache || NULL == m_pnDMICacheIndex )
return FALSE;
for( int i=0; i<m_nDays; i++ )
m_pnDMICacheIndex[i] = -1;
m_nDMICacheCurrent = -1;
}
if( bUseLast && pADX )
{
// Calculate ADX and ADXR
dADX = ( (m_nDays-1)*(*pADX) + dDX ) / m_nDays;
for( int i=0; i<m_nDays; i++ )
{
if( m_pnDMICacheIndex[i] == nIndex-m_nDays )
{
dADXR = (m_pdDMICache[i] + dADX) / 2;
break;
}
}
// Save ADX to cache
m_nDMICacheCurrent ++;
if( m_nDMICacheCurrent < 0 || m_nDMICacheCurrent >= m_nDays )
m_nDMICacheCurrent = 0;
m_pdDMICache[m_nDMICacheCurrent] = dADX;
m_pnDMICacheIndex[m_nDMICacheCurrent] = nIndex;
if( pADX ) *pADX = dADX;
if( pADXR ) *pADXR = dADXR;
StoreToCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR );
return TRUE;
}
else
{
double factor = 1;
int k;
for( k=nIndex; k > 0; k-- )
{
factor *= ((double)(m_nDays-1))/m_nDays;
if( factor < 0.001 )
break;
}
double dADXLast = 0;
BOOL bHasADXR = FALSE;
for( ; k<=nIndex; k++ )
{
if( !CalculateDIDX( NULL, NULL, &dDX, k, m_nDays ) )
continue;
// Calculate ADX and ADXR
dADX = ( (m_nDays-1)*dADX + dDX )/m_nDays;
if( k == nIndex-m_nDays )
{
dADXLast = dADX;
bHasADXR = TRUE;
}
// Save ADX to cache
m_nDMICacheCurrent ++;
if( m_nDMICacheCurrent < 0 || m_nDMICacheCurrent >= m_nDays )
m_nDMICacheCurrent = 0;
m_pdDMICache[m_nDMICacheCurrent] = dADX;
m_pnDMICacheIndex[m_nDMICacheCurrent] = k;
}
dADXR = (dADX + dADXLast) / 2;
if( pADX ) *pADX = dADX;
if( pADXR && bHasADXR ) *pADXR = dADXR;
StoreToCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR );
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CROC
CROC::CROC( )
{
SetDefaultParameters( );
}
CROC::CROC( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CROC::~CROC()
{
Clear( );
}
void CROC::SetDefaultParameters( )
{
m_nDays = 10;
m_nMADays = 10;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CROC::AttachParameters( CROC & src )
{
m_nDays = src.m_nDays;
m_nMADays = src.m_nMADays;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CROC::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CROC::Clear( )
{
CTechnique::Clear( );
}
int CROC::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
int nMaxDays = m_nDays + m_nMADays;
double dLiminalLow = 0, dLiminalHigh = 0;
if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.309, 0.6 ) )
return ITS_NOTHING;
double dROC, dMA;
if( !Calculate( &dROC, &dMA, nIndex, FALSE ) )
return ITS_NOTHING;
if( dROC < dLiminalLow && dMA < dLiminalLow && IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dROC > dLiminalHigh && dMA > dLiminalHigh && IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CROC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
}
/***
ROC=(今收盘-前N日收盘)÷前N日的收盘×100
*/
BOOL CROC::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->MaindataAt(nIndex-m_nDays) <= 0
|| m_pKData->MaindataAt(nIndex) <= 0 )
return FALSE;
double x = m_pKData->MaindataAt(nIndex);
double y = m_pKData->MaindataAt(nIndex-m_nDays);
if( pValue )
*pValue = (x - y) * 100 / y;
StoreToCache( nIndex, pValue );
return TRUE;
}
BOOL CROC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
{
return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
}
//////////////////////////////////////////////////////////////////////
// CCCI
CCCI::CCCI( )
{
SetDefaultParameters( );
}
CCCI::CCCI( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CCCI::~CCCI()
{
Clear( );
}
void CCCI::SetDefaultParameters( )
{
m_nDays = 14;
m_dQuotiety = 0.015;
m_nMADays = 10;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CCCI::AttachParameters( CCCI & src )
{
m_nDays = src.m_nDays;
m_dQuotiety = src.m_dQuotiety;
m_nMADays = src.m_nMADays;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CCCI::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) && m_dQuotiety > 0 && VALID_DAYS(m_nMADays)
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CCCI::Clear( )
{
CTechnique::Clear( );
}
int CCCI::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
double dCCI;
if( !Calculate( &dCCI, nIndex, FALSE ) )
return ITS_NOTHING;
int nForkSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
if( dCCI < -100 && nForkSignal == m_itsGoldenFork )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dCCI > 100 && nForkSignal == m_itsDeadFork )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CCCI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
}
/***
TP = 收盘价+收盘价+最高价+最低价
A是TP的N日均值
D是TP与A的离差均值
CCI=(C-D)/(0.015D)
*/
BOOL CCCI::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 dTP = 0, dMATP = 0, dD = 0;
int nCount = 0, k=0;
for( k=nIndex; k>=0; k-- )
{
KDATA kd = m_pKData->ElementAt(k);
double dTemp = (kd.m_fHigh+kd.m_fClose+kd.m_fClose+kd.m_fLow)/4;
if( nIndex == k )
dTP = dTemp;
dMATP += dTemp;
nCount ++;
if( nCount == m_nDays )
break;
}
dMATP = dMATP / m_nDays;
nCount = 0;
for( k=nIndex; k>=0; k-- )
{
KDATA kd = m_pKData->ElementAt(k);
double dTemp = (kd.m_fHigh+kd.m_fClose+kd.m_fClose+kd.m_fLow)/4;
dD += fabs(dTemp-dMATP);
nCount ++;
if( nCount == m_nDays )
break;
}
dD = dD / m_nDays;
if( fabs(dD) < 1e-4 )
return FALSE;
if( pValue )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -