📄 techkline.cpp.svn-base
字号:
/*
Cross Platform Core Code.
Copyright(R) 2001-2002 Balang Software.
All rights reserved.
*/
#include "StdAfx.h"
#include "../Include/Stock.h"
#include "../Include/Technique.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CKLine
CKLine::CKLine( )
{
SetDefaultParameters( );
}
CKLine::CKLine( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CKLine::~CKLine()
{
Clear( );
}
void CKLine::SetDefaultParameters( )
{
}
void CKLine::AttachParameters( CKLine & src )
{
}
BOOL CKLine::IsValidParameters( )
{
return TRUE;
}
void CKLine::Clear( )
{
CTechnique::Clear( );
}
/***
得到K线价格的从nStart到nEnd的最小值和最大值
*/
BOOL CKLine::GetMinMaxInfo( int nStart, int nEnd, double *pdMin, double *pdMax )
{
STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
double dMin = -1;
double dMax = 1;
for( int k=nStart; k<=nEnd; k++ )
{
KDATA & kd = m_pKData->ElementAt(k);
if( nStart == k || dMin > kd.m_fLow ) dMin = (double)kd.m_fLow;
if( nStart == k || dMax < kd.m_fHigh ) dMax = (double)kd.m_fHigh;
}
dMin -= fabs(dMin) * 0.01;
dMax += fabs(dMax) * 0.01;
if( dMin <= 0 )
dMin = 0;
if( dMax - dMin < 0.03 )
dMax = dMin + 0.03;
if( pdMin ) *pdMin = dMin;
if( pdMax ) *pdMax = dMax;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CMA
CMA::CMA( )
{
SetDefaultParameters( );
}
CMA::CMA( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CMA::~CMA()
{
Clear( );
}
void CMA::SetDefaultParameters( )
{
m_nType = typeMA;
m_adwMADays.RemoveAll();
m_adwMADays.Add( 5 );
m_adwMADays.Add( 10 );
m_adwMADays.Add( 20 );
m_itsGoldenFork = ITS_BUYINTENSE;
m_itsDeadFork = ITS_SELLINTENSE;
m_itsLong = ITS_BUY;
m_itsShort = ITS_SELL;
}
void CMA::AttachParameters( CMA & src )
{
m_nType = src.m_nType;
m_adwMADays.Copy( src.m_adwMADays );
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
m_itsLong = src.m_itsLong;
m_itsShort = src.m_itsShort;
}
BOOL CMA::IsValidParameters( )
{
STT_VALID_DAYSARRAY( m_adwMADays );
return ( (typeMA == m_nType || typeEXPMA == m_nType)
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork)
&& VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
}
void CMA::Clear( )
{
CTechnique::Clear( );
}
int CMA::GetSignal( int nIndex, UINT * pnCode )
{
// 金叉或者死叉
int nSignal = GetForkSignal( nIndex, m_adwMADays, m_itsGoldenFork, m_itsDeadFork, pnCode );
if( ITS_ISBUY(nSignal) || ITS_ISSELL(nSignal) )
return nSignal;
// 趋势
return GetTrendIntensity( nIndex, m_adwMADays, m_itsLong, m_itsShort, pnCode );
}
BOOL CMA::GetMinMaxInfo(int nStart, int nEnd,
double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo( nStart, nEnd, pdMin, pdMax, this, m_adwMADays );
}
/***
两种:
1. MA
MA = n日收盘价的平均值
2. EXPMA
EXPMA(1) = CLOSE(1)
EXPMA(i) = (1-α)EXPMA(i-1) + αCLOSE(i)
其中 α = 2 / (n+1)
*/
BOOL CMA::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
{
STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
int nCount = 0;
if( nDays > nIndex+1 )
return FALSE;
double dResult = 0;
int k = 0;
switch( m_nType )
{
case typeMA:
return m_pKData->GetMA( pValue, nIndex, nDays );
break;
case typeEXPMA:
if( bUseLast && pValue )
{
if( 0 == nIndex )
dResult = m_pKData->MaindataAt(nIndex);
else
dResult = (*pValue)*(nDays-1)/(nDays+1) + m_pKData->MaindataAt(nIndex) * 2./(nDays+1);
}
else
{
for( k=0; k<=nIndex; k++ )
{
if( 0 == k )
dResult = m_pKData->MaindataAt(k);
else
dResult = dResult*(nDays-1)/(nDays+1) + m_pKData->MaindataAt(k) * 2./(nDays+1);
}
}
if( pValue )
*pValue = dResult;
break;
default:
SP_ASSERT( FALSE );
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CBBI
CBBI::CBBI( )
{
SetDefaultParameters( );
}
CBBI::CBBI( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CBBI::~CBBI()
{
Clear( );
}
void CBBI::SetDefaultParameters( )
{
m_nMA1Days = 3;
m_nMA2Days = 6;
m_nMA3Days = 12;
m_nMA4Days = 24;
m_itsGoldenFork = ITS_BUY;
m_itsDeadFork = ITS_SELL;
}
void CBBI::AttachParameters( CBBI & src )
{
m_nMA1Days = src.m_nMA1Days;
m_nMA2Days = src.m_nMA2Days;
m_nMA3Days = src.m_nMA3Days;
m_nMA4Days = src.m_nMA4Days;
m_itsGoldenFork = src.m_itsGoldenFork;
m_itsDeadFork = src.m_itsDeadFork;
}
BOOL CBBI::IsValidParameters( )
{
return ( VALID_DAYS( m_nMA1Days ) && VALID_DAYS( m_nMA2Days )
&& VALID_DAYS( m_nMA3Days ) && VALID_DAYS( m_nMA4Days )
&& VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
}
void CBBI::Clear( )
{
CTechnique::Clear( );
}
int CBBI::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
if( nIndex <= 0 )
return ITS_NOTHING;
double dLiminalLow = 0, dLiminalHigh = 0;
if( !IntensityPreparePrice( nIndex, pnCode, 0, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.4, 0.6 ) )
return ITS_NOTHING;
double dBBINow = 0, dBBILast = 0;
if( !Calculate( &dBBILast, nIndex-1, FALSE )
|| !Calculate( &dBBINow, nIndex, FALSE ) )
return ITS_NOTHING;
double dNowHigh = m_pKData->ElementAt(nIndex).m_fHigh;
double dNowLow = m_pKData->ElementAt(nIndex).m_fLow;
double dNowClose = m_pKData->ElementAt(nIndex).m_fClose;
double dLastHigh = m_pKData->ElementAt(nIndex-1).m_fHigh;
double dLastLow = m_pKData->ElementAt(nIndex-1).m_fLow;
double dLastClose = m_pKData->ElementAt(nIndex-1).m_fClose;
if( dNowClose < dLiminalLow && dLastLow < dBBILast && dNowLow > dBBINow )
{ // 低位趋势向上
if( pnCode ) *pnCode = ITSC_GOLDENFORK;
return m_itsGoldenFork;
}
if( dNowClose > dLiminalHigh && dLastHigh > dBBILast && dNowHigh < dBBINow )
{ // 高位趋势向下
if( pnCode ) *pnCode = ITSC_DEADFORK;
return m_itsDeadFork;
}
return ITS_NOTHING;
}
BOOL CBBI::GetMinMaxInfo(int nStart, int nEnd,
double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
}
/***
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;
}
//////////////////////////////////////////////////////////////////////
// CBOLL
CBOLL::CBOLL( )
{
SetDefaultParameters( );
}
CBOLL::CBOLL( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CBOLL::~CBOLL()
{
Clear( );
}
void CBOLL::SetDefaultParameters( )
{
m_dMultiUp = 2;
m_dMultiDown = 2;
m_nMADays = 20;
m_itsSupport = ITS_BUY;
m_itsResistance = ITS_SELL;
}
void CBOLL::AttachParameters( CBOLL & src )
{
m_dMultiUp = src.m_dMultiUp;
m_dMultiDown = src.m_dMultiDown;
m_nMADays = src.m_nMADays;
m_itsSupport = src.m_itsSupport;
m_itsResistance = src.m_itsResistance;
}
BOOL CBOLL::IsValidParameters( )
{
return ( m_dMultiUp > 0 && m_dMultiDown > 0 && VALID_DAYS( m_nMADays )
&& VALID_ITS(m_itsSupport) && VALID_ITS(m_itsResistance) );
}
void CBOLL::Clear( )
{
CTechnique::Clear( );
}
int CBOLL::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
double dMA = 0, dUp = 0, dDown = 0;
if( !Calculate( &dMA, &dUp, &dDown, nIndex, FALSE ) )
return ITS_NOTHING;
double dClose = m_pKData->ElementAt(nIndex).m_fClose;
if( dClose < dDown )
{ // 跌破支撑位
if( pnCode ) *pnCode = ITSC_SUPPORT;
return m_itsSupport;
}
if( dClose > dUp )
{ // 涨过阻力位
if( pnCode ) *pnCode = ITSC_RESISTANCE;
return m_itsResistance;
}
return ITS_NOTHING;
}
BOOL CBOLL::GetMinMaxInfo(int nStart, int nEnd,
double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
}
/***
布林带是以股价平均线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;
}
//////////////////////////////////////////////////////////////////////
// CPV
CPV::CPV( )
{
SetDefaultParameters( );
}
CPV::CPV( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
}
CPV::~CPV()
{
Clear( );
}
void CPV::SetDefaultParameters( )
{
}
void CPV::AttachParameters( CPV & src )
{
}
BOOL CPV::IsValidParameters( )
{
return TRUE;
}
void CPV::Clear( )
{
CTechnique::Clear( );
}
int CPV::GetSignal( int nIndex, UINT * pnCode )
{
if( pnCode ) *pnCode = ITSC_NOTHING;
// 无买卖信号
return ITS_NOTHING;
}
BOOL CPV::GetMinMaxInfo(int nStart, int nEnd,
double *pdMin, double *pdMax )
{
return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
}
/***
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;
}
//////////////////////////////////////////////////////////////////////
// CSAR
CSAR::CSAR( )
{
SetDefaultParameters( );
}
CSAR::CSAR( CKData * pKData )
: CTechnique( pKData )
{
SetDefaultParameters( );
m_bCurUp = m_bFirstUp;
m_bTurn = FALSE;
m_dCurAF = m_dAFStep;
m_dCurHigh = -1;
m_dCurLow = -1;
}
CSAR::~CSAR()
{
Clear( );
}
void CSAR::SetDefaultParameters( )
{
m_nInitDays = 4;
m_bFirstUp = TRUE;
m_dAFStep = 0.02;
m_dAFMax = 0.2;
m_itsBuy = ITS_BUY;
m_itsSell = ITS_SELL;
}
void CSAR::AttachParameters( CSAR & src )
{
m_nInitDays = src.m_nInitDays;
m_bFirstUp = src.m_bFirstUp;
m_dAFStep = src.m_dAFStep;
m_dAFMax = src.m_dAFMax;
m_itsBuy = src.m_itsBuy;
m_itsSell = src.m_itsSell;
}
BOOL CSAR::IsValidParameters( )
{
return ( VALID_DAYS(m_nInitDays) && m_bFirstUp >= 0 && m_dAFStep > 0 && m_dAFMax > 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -