📄 techswing.cpp
字号:
/*
Cross Platform Core Code.
Copyright(R) 2001-2002 Balang Software.
All rights reserved.
*/
#include "StdAfx.h"
#include "Stock.h"
#include "Technique.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CKDJ
CKDJ::CKDJ( )
{
SetDefaultParameters( );
}
CKDJ::CKDJ( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CKDJ::~CKDJ()
{
Clear( );
}
void CKDJ::SetDefaultParameters( )
{
m_nRSVDays = 9;
m_nKDays = 3;
m_nDDays = 3;
m_nJ = 1;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CKDJ::AttachParameters( CKDJ & src )
{
m_nRSVDays = src.m_nRSVDays;
m_nKDays = src.m_nKDays;
m_nDDays = src.m_nDDays;
m_nJ = src.m_nJ;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CKDJ::IsValidParameters( )
{
return ( VALID_DAYS(m_nRSVDays) && VALID_DAYS(m_nKDays)
&& VALID_DAYS(m_nDDays) && VALID_DAYS(m_nJ)
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CKDJ::Clear( )
{
CTechnique::Clear( );
}
// 计算RSV值
BOOL CKDJ::CalculateRSV( double * pValue, int nIndex )
{
STT_ASSERT_CALCULATE1( m_pKData, nIndex );
double dH = 0, dL = 0, dRSV = 0;
int nCount = 0;
for( int k=nIndex; k>=0; k-- )
{
if( nIndex == k )
{
dH = m_pKData->ElementAt(k).m_fHigh;
dL = m_pKData->ElementAt(k).m_fLow;
}
if( dH < m_pKData->ElementAt(k).m_fHigh )
dH = m_pKData->ElementAt(k).m_fHigh;
if( dL > m_pKData->ElementAt(k).m_fLow )
dL = m_pKData->ElementAt(k).m_fLow;
nCount ++;
if( nCount == m_nRSVDays )
{
if( dH-dL < 1e-4 )
dRSV = 100;
else
dRSV = (m_pKData->ElementAt(nIndex).m_fClose - dL) * 100 / (dH - dL);
if( pValue ) *pValue = dRSV;
return TRUE;
}
}
return FALSE;
}
int CKDJ::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
if( !PrepareCache( 0, -1, FALSE ) )
return ITS_NOTHING;
double dK, dD, dJ;
if( !Calculate( &dK, &dD, &dJ, nIndex, FALSE ) )
return ITS_NOTHING;
if( dK < 25 && dD < 25 && IsGoldenFork(nIndex, m_pdCache1, m_pdCache2) )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dK > 75 && dD > 75 && IsDeadFork(nIndex, m_pdCache1, m_pdCache2) )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CKDJ::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
}
/***
AX = 今天的收盘价 - N天中的最低价
BX = N天中的最高价 - N天中的最低价
RSV = (AX ÷ BX)× 100%
NK = K计算天数,一般取3
ND = D计算天数,一般取3
K = 前一日K×(NK-1)/NK + RSV×1/NK
D = 前一日D×(ND-1)/ND + K×1/3
J = 3D - 2K (或 J = 3K - 2D)
第一次计算时,前一日的K、D值皆以50代替。
*/
BOOL CKDJ::Calculate( double *pValue1, double *pValue2, double *pValue3, int nIndex, BOOL bUseLast )
{
STT_ASSERT_CALCULATE1( m_pKData, nIndex );
if( m_nRSVDays > nIndex+1 )
return FALSE;
if( LoadFromCache( nIndex, pValue1, pValue2, pValue3 ) )
return TRUE;
double dRSV = 0;
double dK = 50, dD = 50, dJ = 50;
if( bUseLast && pValue1 && pValue2 )
{
if( CalculateRSV( &dRSV, nIndex ) )
{
dK = (m_nKDays-1)*(*pValue1)/m_nKDays + dRSV/m_nKDays;
dD = (m_nDDays-1)*(*pValue2)/m_nDDays + dK/m_nDDays;
if( mode3K2D == m_nJ )
dJ = 3 * dK - 2 * dD;
else
dJ = 3 * dD - 2 * dK;
if( pValue1 ) *pValue1 = dK;
if( pValue2 ) *pValue2 = dD;
if( pValue3 ) *pValue3 = dJ;
StoreToCache( nIndex, pValue1, pValue2, pValue3 );
return TRUE;
}
}
else
{
double factor1 = 1, factor2 = 1;
int k;
for( k=nIndex; k > 0; k-- )
{
factor1 *= ((double)(m_nKDays-1))/m_nKDays;
factor2 *= ((double)(m_nDDays-1))/m_nDDays;
if( factor1 < 0.001 && factor2 < 0.001 )
break;
}
for( ; k<=nIndex; k++ )
{
if( CalculateRSV( &dRSV, k ) )
{
dK = (m_nKDays-1)*(dK)/m_nKDays + dRSV/m_nKDays;
dD = (m_nDDays-1)*(dD)/m_nDDays + dK/m_nDDays;
if( mode3K2D == m_nJ )
dJ = 3 * dK - 2 * dD;
else
dJ = 3 * dD - 2 * dK;
if( nIndex == k )
{
if( pValue1 ) *pValue1 = dK;
if( pValue2 ) *pValue2 = dD;
if( pValue3 ) *pValue3 = dJ;
StoreToCache( nIndex, pValue1, pValue2, pValue3 );
return TRUE;
}
}
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CR
CR::CR( )
{
SetDefaultParameters( );
}
CR::CR( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CR::~CR()
{
Clear( );
}
void CR::SetDefaultParameters( )
{
m_nDays = 20;
}
void CR::AttachParameters( CR & src )
{
m_nDays = src.m_nDays;
}
BOOL CR::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) );
}
void CR::Clear( )
{
CTechnique::Clear( );
}
int CR::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
/* double dR;
if( !Calculate( &dR, nIndex, FALSE ) )
return ITS_NOTHING;
if( dR > 80 )
{
if( pnCode ) *pnCode = ITSC_OVERSOLD;
return m_itsSold;
}
if( dR < 20 )
{
if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
return m_itsBought;
}
*/
// 无买卖信号
return ITS_NOTHING;
}
BOOL CR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
if( pdMin ) *pdMin = 0;
if( pdMax ) *pdMax = 100;
return TRUE;
}
/***
H - C
W%R指标值= ———— ×100
H - L
H = N日内最高价 L = N日内最低价 C = 当天收盘价
*/
BOOL CR::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 dH = 0, dL = 0, dR = 0;
int nCount = 0;
for( int k=nIndex; k>=0; k-- )
{
if( nIndex == k )
{
dH = m_pKData->ElementAt(k).m_fHigh;
dL = m_pKData->ElementAt(k).m_fLow;
}
if( dH < m_pKData->ElementAt(k).m_fHigh )
dH = m_pKData->ElementAt(k).m_fHigh;
if( dL > m_pKData->ElementAt(k).m_fLow )
dL = m_pKData->ElementAt(k).m_fLow;
nCount ++;
if( nCount == m_nDays )
{
if( dH-dL < 1e-4 )
dR = 100;
else
dR = (dH - m_pKData->ElementAt(nIndex).m_fClose) * 100 / (dH - dL);
if( pValue ) *pValue = dR;
StoreToCache( nIndex, pValue );
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CRSI
CRSI::CRSI( )
{
SetDefaultParameters( );
}
CRSI::CRSI( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CRSI::~CRSI()
{
Clear( );
}
void CRSI::SetDefaultParameters( )
{
m_adwDays.RemoveAll();
m_adwDays.Add( 10 );
m_adwDays.Add( 20 );
m_itsSold = ITS_BUY;
m_itsGoldenFork = ITS_BUYINTENSE;
m_itsDeadFork = ITS_SELLINTENSE;
}
void CRSI::AttachParameters( CRSI & src )
{
m_adwDays.Copy( src.m_adwDays );
m_itsSold = src.m_itsSold;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CRSI::IsValidParameters( )
{
STT_VALID_DAYSARRAY( m_adwDays );
return ( VALID_ITS(m_itsSold) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CRSI::Clear( )
{
CTechnique::Clear( );
}
int CRSI::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
if( nIndex <= 0 )
return ITS_NOTHING;
int nForkSignal = GetForkSignal(nIndex, m_adwDays, m_itsGoldenFork, m_itsDeadFork, pnCode );
for( int k=0; k<m_adwDays.GetSize(); k++ )
{
double dRSI, dRSILast;
if( !Calculate( &dRSILast, nIndex-1, m_adwDays[k], FALSE )
|| !Calculate( &dRSI, nIndex, m_adwDays[k], FALSE ) )
return ITS_NOTHING;
if( dRSI < 20 )
{ // 超卖
if( pnCode ) *pnCode = ITSC_OVERSOLD;
return m_itsSold;
}
if( dRSI < 40 && nForkSignal == m_itsGoldenFork )
{ // 低位金叉
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dRSI > 60 && nForkSignal == m_itsDeadFork )
{ // 高位死叉
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
}
return ITS_NOTHING;
}
BOOL CRSI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
if( pdMin ) *pdMin = 0;
if( pdMax ) *pdMax = 100;
return TRUE;
}
/***
RSI =(N日内上涨幅度累计÷N日内上涨及下跌幅度累计)×100%
*/
BOOL CRSI::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
{
STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
if( nDays > nIndex )
return FALSE;
double dUC = 0, dDC = 0, dRSI = 0;
int nCount = 0;
for( int k=nIndex; k>=1; k-- )
{
if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) )
dUC += ( m_pKData->MaindataAt(k) - m_pKData->MaindataAt(k-1) );
else
dDC += ( m_pKData->MaindataAt(k-1) - m_pKData->MaindataAt(k) );
nCount ++;
if( nCount == nDays )
{
if( dUC+dDC < 1e-4 )
dRSI = 100;
else
dRSI = 100*dUC/(dUC+dDC);
if( pValue ) *pValue = dRSI;
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CBIAS
CBIAS::CBIAS( )
{
SetDefaultParameters( );
}
CBIAS::CBIAS( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CBIAS::~CBIAS()
{
Clear( );
}
void CBIAS::SetDefaultParameters( )
{
m_nDays = 10;
m_itsSold = ITS_BUY;
m_itsBought = ITS_SELL;
}
void CBIAS::AttachParameters( CBIAS & src )
{
m_nDays = src.m_nDays;
m_itsSold = src.m_itsSold;
m_itsBought = src.m_itsBought;
}
BOOL CBIAS::IsValidParameters( )
{
return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
}
void CBIAS::Clear( )
{
CTechnique::Clear( );
}
int CBIAS::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
double dBIAS;
if( !Calculate( &dBIAS, nIndex, FALSE ) )
return ITS_NOTHING;
if( dBIAS < -10 )
{ // 超卖
if( pnCode ) *pnCode = ITSC_OVERSOLD;
return m_itsSold;
}
if( dBIAS > 5 )
{ // 超买
if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
return m_itsBought;
}
return ITS_NOTHING;
}
BOOL CBIAS::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
}
/***
当日收盘价-N日移动平均值
N日乖离率 = —————————————— ×100%
N日移动平均值
*/
BOOL CBIAS::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 dMA = 0;
int nCount = 0;
for( int k=nIndex; k>=0; k -- )
{
dMA += m_pKData->MaindataAt(k);
nCount ++;
if( nCount == m_nDays )
{
double dResult = 0;
dMA = dMA / m_nDays;
if( dMA > 1e-4 )
dResult = 100. * ( m_pKData->MaindataAt(nIndex) - dMA ) / dMA;
if( pValue ) *pValue = dResult;
StoreToCache( nIndex, pValue );
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CMTM
CMTM::CMTM( )
{
SetDefaultParameters( );
}
CMTM::CMTM( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CMTM::~CMTM()
{
Clear( );
}
void CMTM::SetDefaultParameters( )
{
m_nDays = 10;
m_nMADays = 10;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CMTM::AttachParameters( CMTM & src )
{
m_nDays = m_nDays;
m_nMADays = m_nMADays;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CMTM::IsValidParameters( )
{
return ( VALID_DAYS( m_nDays ) && VALID_DAYS( m_nMADays )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -