⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 techswing.cpp

📁 股软 通达信行情接收接口, 包括美元汇率
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*
	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 + -