📄 techkline.cpp.svn-base
字号:
&& VALID_ITS(m_itsBuy) && VALID_ITS(m_itsSell) );
}
void CSAR::Clear( )
{
CTechnique::Clear( );
}
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;
}
int CSAR::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
Clear( );
double dValue;
if( !Calculate( &dValue, nIndex, FALSE ) )
return ITS_NOTHING;
if( m_bTurn && !m_bCurUp )
{ // 反转向上
if( pnCode ) *pnCode = ITSC_LONG;
return m_itsBuy;
}
if( m_bTurn && m_bCurUp )
{ // 反转向下
if( pnCode ) *pnCode = ITSC_SHORT;
return m_itsSell;
}
return ITS_NOTHING;
}
BOOL CSAR::GetMinMaxInfo(int nStart, int nEnd,
double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
}
/***
计算SAR值
先选定时间,判断价格是在上涨还是在下跌。
若是看涨,则进场第一天的SAR必须是近期内的最低价,是看跌 则进场第一天的SAR必须是近期内的最高价。
本处为缺省定义为看涨。
进场第二天的SAR则为第一天的最高价(看涨时)或最低价(看跌时)与第一天的SAR的差距乘上调整系数,
再加上第一天的SAR就可求得。
按逐步递推的方法,每日的SAR可归纳如下: SAR(N)= SAR(N-1)+ AF * [ EP(N-1)-SAR(N-1)]
其中SAR(N)为第N日的SAR值,AF是调整系数,EP为极点价
第一个调整系数AF为0.02,若每隔一天的最高价比前一天的最高价还高,则AF递增0.02,若未创新高,
则AF沿用前一天的数值,但调整系数最高不超过0.2。
若是买进期间,计算出某日的SAR比当日或前一日的最低价还高,则应以当日或者前一日的最低价为某日之SAR,
卖出期间也对应服从类似原则。
*/
BOOL CSAR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
{
if( LoadFromCache( nIndex, pValue ) )
return TRUE;
if( bUseLast && pValue && nIndex > 0 )
{
if( CalculateSAR( pValue, nIndex, bUseLast ) )
{
StoreToCache( nIndex, pValue );
return TRUE;
}
return FALSE;
}
else
{
double dResult;
BOOL bHasLast = FALSE;
for( int k=0; k<=nIndex; k++ )
{
if( CalculateSAR( &dResult, k, bHasLast ) )
{
bHasLast = TRUE;
StoreToCache( k, &dResult );
}
}
if( !bHasLast )
return FALSE;
if( pValue )
*pValue = dResult;
return TRUE;
}
}
//////////////////////////////////////////////////////////////////////
// CDJ
CStock CDJ::m_stockSha;
CStock CDJ::m_stockSzn;
CSPString CDJ::m_strCodeOrg;
CDJ::CDJ( )
{
SetDefaultParameters( );
}
CDJ::CDJ( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CDJ::~CDJ()
{
Clear( );
}
void CDJ::SetDefaultParameters( )
{
m_strCodeSha = STKLIB_CODE_MAIN;
m_strCodeSzn = STKLIB_CODE_MAINSZN;
}
void CDJ::AttachParameters( CDJ & src )
{
m_strCodeSha = src.m_strCodeSha;
m_strCodeSzn = src.m_strCodeSzn;
}
BOOL CDJ::IsValidParameters( )
{
return ( m_strCodeSha.GetLength() > 0 && m_strCodeSzn.GetLength() > 0 );
}
void CDJ::Clear( )
{
CTechnique::Clear( );
}
/***
K线叠加图,准备叠加K线的数据
*/
BOOL CDJ::PrepareStockData(CStDatabase * pDatabase, const char * szCodeOrg,
int nCurKType, int nCurKFormat, int nCurMaindataType,
DWORD dwAutoResumeDRBegin, int nAutoResumeDRLimit )
{
SP_ASSERT( pDatabase );
// bReload and kdayMain
BOOL bReload = (NULL!=szCodeOrg && 0!=strncmp(szCodeOrg,m_strCodeOrg,m_strCodeOrg.GetLength()) );
m_strCodeOrg = szCodeOrg;
// m_stockSha
m_stockSha.SetStockCode( CStock::marketSHSE, m_strCodeSha );
AfxPrepareStockData( pDatabase, m_stockSha, nCurKType, nCurKFormat, nCurMaindataType, FALSE, bReload );
// m_stockSzn
m_stockSzn.SetStockCode( CStock::marketSZSE, m_strCodeSzn );
AfxPrepareStockData( pDatabase, m_stockSzn, nCurKType, nCurKFormat, nCurMaindataType, FALSE, bReload );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CCW
CCW::CCW( )
{
SetDefaultParameters( );
}
CCW::CCW( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CCW::~CCW()
{
Clear( );
}
void CCW::SetDefaultParameters( )
{
m_dChangeHand = 1.5;
}
void CCW::AttachParameters( CCW & src )
{
m_dChangeHand = src.m_dChangeHand;
}
BOOL CCW::IsValidParameters( )
{
return ( m_dChangeHand > 0 );
}
void CCW::Clear( )
{
CTechnique::Clear( );
}
/***
根据换手率m_dChangeHand和终止日,计算起始日
*/
BOOL CCW::GetRange( int & nStart, int & nEnd, CStockInfo & info )
{
if( !m_pKData || m_pKData->GetSize() <= 0 )
return FALSE;
if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
nEnd = m_pKData->GetSize()-1;
BOOL bIndex = FALSE;
double dShareCurrency = 0;
if( !info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6 )
bIndex = TRUE;
if( bIndex )
dShareCurrency = 100 * m_dChangeHand;
else
dShareCurrency *= m_dChangeHand;
double dVol = 0;
int k;
for( k=nEnd; k>=0; k-- )
{
if( bIndex )
dVol += 1;
else
dVol += m_pKData->ElementAt(k).m_fVolume;
if( dVol > dShareCurrency )
break;
}
nStart = k;
if( nStart < 0 )
nStart = 0;
return TRUE;
}
BOOL CCW::GetMinMaxInfo(int nStart, int nEnd, double dMinPrice, double dMaxPrice, double dStep,
double *pdMinVolume, double *pdMaxVolume )
{
STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
if( dMinPrice >= dMaxPrice || dStep < 1e-4 )
return FALSE;
double dMinVolume = 0, dMaxVolume = 0, dVolume = 0;
BOOL bFirst = TRUE;
for( double dPrice = dMinPrice; dPrice < dMaxPrice; dPrice += dStep )
{
if( CalculateCW( &dVolume, nStart, nEnd, dPrice, dStep ) )
{
if( bFirst || dVolume < dMinVolume ) dMinVolume = dVolume;
if( bFirst || dVolume > dMaxVolume ) dMaxVolume = dVolume;
bFirst = FALSE;
}
}
dMinVolume -= fabs(dMinVolume)*0.01;
dMaxVolume += fabs(dMaxVolume)*0.01;
if( dMaxVolume - dMinVolume < 3 )
dMaxVolume = dMinVolume + 3;
if( pdMinVolume ) *pdMinVolume = dMinVolume;
if( pdMaxVolume ) *pdMaxVolume = dMaxVolume;
return !bFirst;
}
/***
筹码分布图,计算价格区间包括dPrice的日线的成交量
*/
BOOL CCW::CalculateCW( double *pdVolume, int nStart, int nEnd, double dPrice, double dStep )
{
STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
double dVolume = 0;
for( int k=nStart; k<=nEnd; k++ )
{
KDATA kd = m_pKData->ElementAt(k);
if( kd.m_fHigh-kd.m_fLow > 1e-4
&& kd.m_fLow < dPrice && kd.m_fHigh > dPrice )
{
// 均匀分布 dVolAve
double dVolAve = kd.m_fVolume;
if( dStep < kd.m_fHigh-kd.m_fLow )
dVolAve = kd.m_fVolume * dStep / (kd.m_fHigh-kd.m_fLow);
// 三角分布
double dFactor = min(dPrice-kd.m_fLow, kd.m_fHigh-dPrice);
dVolume += dVolAve * dFactor * 4 / (kd.m_fHigh-kd.m_fLow);
}
}
if( pdVolume )
*pdVolume = dVolume;
return TRUE;
}
/***
筹码分布图计算,计算筹码分布
*/
BOOL CCW::CalculateCW( int nStart, int nEnd, CStockInfo & info, double dStep,
CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
{
STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
if( dStep < 1e-4 )
return FALSE;
float dMinPrice = 0, dMaxPrice = 0;
if( !m_pKData->GetMinMaxInfo( nStart, nEnd, &dMinPrice, &dMaxPrice ) )
return FALSE;
// Calculate
int nMaxCount = (int)((dMaxPrice-dMinPrice)/dStep) + 10;
adwPrice.SetSize( 0, nMaxCount );
adwVolume.SetSize( 0, nMaxCount );
double dMinVolume = 0, dMaxVolume = 0, dTotalVolume = 0, dVolume = 0;
BOOL bFirst = TRUE;
for( double dPrice = dMinPrice; dPrice < dMaxPrice; dPrice += dStep )
{
if( CalculateCW( &dVolume, nStart, nEnd, dPrice, dStep ) )
{
if( bFirst || dVolume < dMinVolume ) dMinVolume = dVolume;
if( bFirst || dVolume > dMaxVolume ) dMaxVolume = dVolume;
adwPrice.Add( DWORD(dPrice * 1000) );
adwVolume.Add( DWORD(dVolume) );
dTotalVolume += dVolume;
bFirst = FALSE;
}
}
// Return
// Min Max
dMinVolume -= fabs(dMinVolume)*0.01;
dMaxVolume += fabs(dMaxVolume)*0.01;
if( dMaxVolume - dMinVolume < 3 )
dMaxVolume = dMinVolume + 3;
if( pdMinVolume ) *pdMinVolume = dMinVolume;
if( pdMaxVolume ) *pdMaxVolume = dMaxVolume;
if( pdTotalVolume ) *pdTotalVolume = dTotalVolume;
// VolPercent
double dVolPercent = 1.0;
double dShareCurrency = 0;
if( (!info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6) && nEnd-nStart+1 > 0 )
dShareCurrency = dTotalVolume * 100 / (nEnd-nStart+1);
if( dShareCurrency > 1e-4 )
dVolPercent = dTotalVolume / (dShareCurrency*m_dChangeHand);
if( dVolPercent > 1.0 ) dVolPercent = 1.0;
if( dVolPercent < 0.0 ) dVolPercent = 0.0;
if( pdVolPercent ) *pdVolPercent = dVolPercent;
return adwPrice.GetSize() > 0;
}
/***
筹码分布图计算,计算最近nDays天内的筹码分布
*/
BOOL CCW::CalculateRecentCW(int nEnd, int nDays, CStockInfo & info, double dStep,
CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
{
// Prepare
if( !m_pKData || m_pKData->GetSize() <= 0 )
return FALSE;
if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
nEnd = m_pKData->GetSize()-1;
int nStart = nEnd - nDays + 1;
if( nStart < 0 || nStart >= m_pKData->GetSize() )
return FALSE;
return CalculateCW( nStart, nEnd, info, dStep, adwPrice, adwVolume, pdMinVolume, pdMaxVolume, pdTotalVolume, pdVolPercent );
}
/***
筹码分布图计算,计算nDays天前内的筹码分布
*/
BOOL CCW::CalculatePastCW(int nEnd, int nDays, CStockInfo & info, double dStep,
CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
{
// Prepare
if( !m_pKData || m_pKData->GetSize() <= 0 )
return FALSE;
if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
nEnd = m_pKData->GetSize()-1;
int nStart = nEnd - nDays;
if( nStart < 0 || nStart >= m_pKData->GetSize() )
return FALSE;
nEnd = nStart;
if( !GetRange( nStart, nEnd, info ) )
return FALSE;
BOOL bOK = CalculateCW( nStart, nEnd, info, dStep, adwPrice, adwVolume, pdMinVolume, pdMaxVolume, pdTotalVolume, pdVolPercent );
// TotalVolumeRecent
double dTotalVolumeRecent = 0;
for( int k=nEnd+1; k<=nEnd+nDays && k<m_pKData->GetSize(); k ++ )
dTotalVolumeRecent += m_pKData->ElementAt(k).m_fVolume;
// VolPercent
double dVolPercent = 1.0;
double dShareCurrency = 0;
if( (!info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6) && nDays > 0 )
dShareCurrency = dTotalVolumeRecent * 100 / nDays;
if( dShareCurrency > 1e-4 )
dVolPercent = dTotalVolumeRecent / (dShareCurrency*m_dChangeHand);
dVolPercent = 1.0 - dVolPercent;
if( dVolPercent > 1.0 ) dVolPercent = 1.0;
if( dVolPercent < 0.0 ) dVolPercent = 0.0;
if( pdVolPercent ) *pdVolPercent = dVolPercent;
return bOK;
}
/***
筹码分布图统计,获利比例统计
*/
BOOL CCW::StatGainPercent( double *pdGainPercent, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume, double dPriceSel )
{
double dTotalVolume = 0;
double dGainVolume = 0;
for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
{
dTotalVolume += adwVolume[k];
if( adwPrice[k] * 0.001 <= dPriceSel )
dGainVolume += adwVolume[k];
}
double dGainPercent = 0;
if( dTotalVolume > 1e-4 )
dGainPercent = dGainVolume / dTotalVolume;
if( pdGainPercent ) *pdGainPercent = dGainPercent;
return TRUE;
}
/***
筹码分布图统计,平均成本统计
*/
BOOL CCW::StatCostAverage( double *pdCostAve, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume )
{
double dTotalVolume = 0;
double dTotalCost = 0;
for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
{
dTotalVolume += adwVolume[k];
dTotalCost += 0.001 * adwPrice[k] * adwVolume[k];
}
double dCostAve = 0;
if( dTotalVolume > 1e-4 )
dCostAve = dTotalCost / dTotalVolume;
if( pdCostAve ) *pdCostAve = dCostAve;
return TRUE;
}
/***
筹码分布图统计,集中度统计
*/
BOOL CCW::StatMass( double *pdLower, double *pdUpper, double *pdMassPrice, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume, double dMassVol )
{
if( adwPrice.GetSize() != adwVolume.GetSize() || dMassVol < 0 || dMassVol > 1 )
return FALSE;
double dTotalVolume = 0;
for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
dTotalVolume += adwVolume[k];
if( dTotalVolume > 1e-4 )
{
double dUpperVolume = dTotalVolume * (1-dMassVol) * 0.5;
double dLowerVolume = dUpperVolume;
int nLower = 0, nUpper = adwPrice.GetSize()-1;
int k;
for( k=0; k<adwPrice.GetSize(); k++ )
{
dLowerVolume -= (double)adwVolume[k];
if( dLowerVolume < 0 )
break;
}
nLower = k;
for( k=adwPrice.GetSize()-1; k>=0; k-- )
{
dUpperVolume -= (double)adwVolume[k];
if( dUpperVolume < 0 )
break;
}
nUpper = k;
if( nLower < 0 || nLower > nUpper || nUpper >= adwPrice.GetSize() )
return FALSE;
double dLower = 0.001 * adwPrice[nLower];
double dUpper = 0.001 * adwPrice[nUpper];
if( pdLower ) *pdLower = dLower;
if( pdUpper ) *pdUpper = dUpper;
if( pdMassPrice && adwPrice.GetSize() >= 2 )
{
double dPriceRange = 0.001 * ((double)adwPrice[adwPrice.GetSize()-1] - (double)adwPrice[0]);
if( dPriceRange > 1e-4 )
*pdMassPrice = (dUpper-dLower)/dPriceRange;
if( *pdMassPrice < 0 ) *pdMassPrice = 0;
if( *pdMassPrice > 1 ) *pdMassPrice = 1;
}
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -