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

📄 strategy.cpp

📁 股软 通达信行情接收接口, 包括美元汇率
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 操作记录数组,加入记录
int COpRecordContainer::AddRecord(long lOpType, CSPTime tm, const char *szCode,
								   DWORD dwShare, double dSharePrice, double dRateCost )
{
	SP_ASSERT( NULL != szCode && strlen(szCode) > 0 );
	if( NULL == szCode || strlen(szCode) <= 0 )
		return -1;

	OPRECORD	record;
	memset( &record, 0, sizeof(record) );

	record.lOpType		=	lOpType;
	record.time			=	tm.GetTime();
	strncpy( record.szCode, szCode, min(sizeof(record.szCode)-1,strlen(szCode)) );
	record.dwShare		=	dwShare;
	record.dSharePrice	=	dSharePrice;
	record.dRateCost	=	dRateCost;
	record.dwMarket		=	CStock::marketUnknown;
	return Add( record );
}

// 操作记录数组,加入记录,记录中如果已经有该股票的记录,更改为现在的信息
int COpRecordContainer::AddRecordUniqueStock(long lOpType, CSPTime tm, const char *szCode,
								   DWORD dwShare, double dSharePrice, double dRateCost )
{
	SP_ASSERT( NULL != szCode && strlen(szCode) > 0 );
	if( NULL == szCode || strlen(szCode) <= 0 )
		return -1;

	OPRECORD	record;
	memset( &record, 0, sizeof(record) );

	for( int i=0; i<GetSize(); i++ )
	{
		if( 0 == strncmp( ElementAt(i).szCode, szCode, sizeof(record.szCode) ) )
		{
			ElementAt(i).lOpType		=	lOpType;
			ElementAt(i).time			=	tm.GetTime();
			strncpy( ElementAt(i).szCode, szCode, min(sizeof(ElementAt(i).szCode)-1,strlen(szCode)) );
			ElementAt(i).dwShare		=	dwShare;
			ElementAt(i).dSharePrice	=	dSharePrice;
			ElementAt(i).dRateCost		=	dRateCost;
			ElementAt(i).dwMarket		=	CStock::marketUnknown;
			return i;
		}
	}

	record.lOpType		=	lOpType;
	record.time			=	tm.GetTime();
	strncpy( record.szCode, szCode, min(sizeof(record.szCode)-1,strlen(szCode)) );
	record.dwShare		=	dwShare;
	record.dSharePrice	=	dSharePrice;
	record.dRateCost	=	dRateCost;
	record.dwMarket		=	CStock::marketUnknown;
	return Add( record );
}

// 操作记录数组,得到买入记录数
int COpRecordContainer::GetBuyRecordCount()
{
	int	nCount	=	0;
	for( int i=0; i<GetSize(); i++ )
	{
		OPRECORD & record	=	ElementAt(i);
		if( STRATEGY_OPTYPE_BUY == record.lOpType )
			nCount	++;
	}
	return nCount;
}

// 操作记录数组,是否有szCode股票的买入记录
BOOL COpRecordContainer::HasBuyStock( const char * szCode )
{
	if( NULL == szCode || strlen(szCode) < 0 )
		return FALSE;

	for( int i=0; i<GetSize(); i++ )
	{
		OPRECORD & record	=	ElementAt(i);
		if( STRATEGY_OPTYPE_BUY == record.lOpType )
		{
			if( 0 == strncmp( record.szCode, szCode, min(sizeof(record.szCode),strlen(szCode)) ) )
				return TRUE;
		}
	}
	return FALSE;
}

// 操作记录数组,统计结果:操作次数,成功次数,最大收益,最低收益
BOOL COpRecordContainer::StatResults( int *pnTimes, int *pnVictoryTimes, double *pdYieldMax, double *pdYieldMin )
{
	int	nTimes = 0, nVictoryTimes = 0;
	double	dYieldMax = 0, dYieldMin = 0;

	for( int i=0; i<GetSize(); i++ )
	{
		OPRECORD & record	=	ElementAt(i);
		if( STRATEGY_OPTYPE_BUY != record.lOpType )
			continue;

		// 查找当前买入操作的对应卖出操作
		for( int j=i+1; j<GetSize(); j++ )
		{
			OPRECORD & record2	=	ElementAt(j);
			if( STRATEGY_OPTYPE_SELL == record2.lOpType && 0 == strncmp(record.szCode,record2.szCode,sizeof(record.szCode)) )
			{	// 如果是卖出操作,根据买入价格和卖出价格计算收益率
				if( record.dwShare > 0 && record2.dwShare > 0 )
				{
					double	dBuy	=	record.dSharePrice + record.dRateCost/record.dwShare;
					double	dSell	=	record2.dSharePrice - record2.dRateCost/record2.dwShare;
					if( dBuy > 1e-4 )
					{
						double	dYield	=	(dSell - dBuy)/dBuy;
						nTimes	++;
						if( dYield > 0 )	nVictoryTimes	++;
						if( 1 == nTimes )	dYieldMax	=	dYieldMin	=	dYield;
						if( dYieldMax < dYield )	dYieldMax	=	dYield;
						if( dYieldMin > dYield )	dYieldMin	=	dYield;
					}
				}
				break;
			}
		}
	}
	if( pnTimes )			*pnTimes		=	nTimes;
	if( pnVictoryTimes )	*pnVictoryTimes	=	nVictoryTimes;
	if( pdYieldMax )		*pdYieldMax		=	dYieldMax;
	if( pdYieldMin )		*pdYieldMin		=	dYieldMin;
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CAssetSerialContainer 
// 资产序列数组,按时间排序插入
BOOL CAssetSerialContainer::SortInsert( ASSETSERIAL serial )
{
	BOOL	bAdded	=	FALSE;
	for( int i=GetSize()-1; i>=0; i-- )
	{
		ASSETSERIAL & se	=	ElementAt(i);
		if( se.time == serial.time )
		{
			se.dAsset	=	serial.dAsset;
			se.dCash	=	serial.dCash;
			bAdded		=	TRUE;
			break;
		}
		else if( se.time < serial.time )
		{
			InsertAt( i+1, serial );
			bAdded		=	TRUE;
			break;
		}
	}
	if( !bAdded )
		InsertAt( 0, serial );
	return TRUE;
}

// 资产序列数组,获得资产序列标准差
BOOL CAssetSerialContainer::GetStdDev( double *pdStdDev, double *pdXiapu )
{
	if( GetSize() <= 0 )
		return FALSE;
	double	dInit	=	ElementAt(0).dAsset;
	if( dInit < 1e-4 )
		return FALSE;

	double	dSum = 0., dSquareSum = 0.;
	for( int k = 0; k<GetSize(); k++ )
	{
		double	dNow	=	(ElementAt(k).dAsset - dInit) / dInit;
		dSum	+=	dNow;
		dSquareSum	+=	dNow*dNow;
	}

	double	dAverage	=	dSum / GetSize();
	if( dAverage < 1e-4 )
		return FALSE;
	double	dStdDev	=	dSquareSum / GetSize() - ( dAverage*dAverage );
	if( dStdDev > 0 )
		dStdDev	=	sqrt( dStdDev );
	if( pdStdDev )	*pdStdDev	=	dStdDev;
	if( pdXiapu )	*pdXiapu	=	(dStdDev / dAverage);
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CTechStock

CTechStock::CTechStock( )
{
	m_bAutoDelete	=	TRUE;

	m_kdata.SetKType(CKData::ktypeDay);
	m_kdataLong.SetKType(CKData::ktypeDay);
}

CTechStock::CTechStock( const CTechStock & src )
{
	*this	=	src;
}

CTechStock & CTechStock::operator = ( const CTechStock &src )
{
	m_bAutoDelete	=	FALSE;

	m_info		=	src.m_info;
	m_kdata		=	src.m_kdata;
	m_kdataLong	=	src.m_kdataLong;
	m_techs.Copy( src.m_techs );
	m_techsLong.Copy( src.m_techsLong );
	return *this;
}

void CTechStock::SetAutoDelete( BOOL bAutoDelete )
{
	m_bAutoDelete	=	bAutoDelete;
}

CTechStock::~CTechStock( )
{
	Clear( );
}

// 清除内存
void CTechStock::Clear( )
{
	if( m_bAutoDelete )
	{
		int i=0;
		for(  i=0; i<m_techs.GetSize(); i++ )
		{
			CTechnique * pTech	=	(CTechnique *)m_techs.ElementAt(i);
			if( pTech )
				delete	pTech;
		}
		for(  i=0; i<m_techsLong.GetSize(); i++ )
		{
			CTechnique * pTech	=	(CTechnique *)m_techsLong.ElementAt(i);
			if( pTech )
				delete	pTech;
		}
	}
	m_techs.RemoveAll();
	m_techsLong.RemoveAll();
}

// 指定日期,指定操作,指定委托价格,得到股票的成交价格
BOOL CTechStock::GetPriceOK( long lOpType, CSPTime tmCur, DWORD dwShare, double dSharePrice, double *pdPriceOK )
{
	double	dPriceOK = dSharePrice;

	CSPTime	sptimeCur(tmCur.GetTime());
	DWORD	dwDate	=	sptimeCur.ToStockTimeDay();
	int nIndex = m_kdata.GetIndexByDate( dwDate );
	if( -1 == nIndex )
		return FALSE;

	KDATA	&	kd	=	m_kdata.ElementAt(nIndex);
	if( STRATEGY_OPTYPE_BUY == lOpType )
	{
		if( dSharePrice < kd.m_fLow )
			return FALSE;
		if( dSharePrice > kd.m_fOpen )
			dPriceOK	=	kd.m_fOpen;
		else
			dPriceOK	=	dSharePrice;
	}
	else if( STRATEGY_OPTYPE_SELL == lOpType )
	{
		if( dSharePrice > kd.m_fHigh )
			return FALSE;
		if( dSharePrice < kd.m_fOpen )
			dPriceOK	=	kd.m_fOpen;
		else
			dPriceOK	=	dSharePrice;
	}
	else
		return FALSE;

	if( pdPriceOK )	*pdPriceOK	=	dPriceOK;
	return TRUE;
}

// 指定日期是否停牌
BOOL CTechStock::IsStopTrading( CSPTime tmCur )
{
	CSPTime	sptimeCur(tmCur.GetTime());
	DWORD	dwDate	=	sptimeCur.ToStockTimeDay();
	int nIndex = m_kdata.GetIndexByDate( dwDate );
	if( -1 == nIndex )
	{
		if( -1 != m_kdata.GetAboutIndexByDate( dwDate ) )
			return TRUE;
		return FALSE;
	}

	KDATA	&	kd	=	m_kdata.ElementAt(nIndex);
	float	fLastClose	=	kd.m_fOpen;
	if( nIndex > 0 )
		fLastClose	=	m_kdata.ElementAt(nIndex-1).m_fClose;

	if( fabs(kd.m_fOpen-kd.m_fClose) < 1e-4 && fabs(kd.m_fOpen-kd.m_fHigh) < 1e-4
		&& fabs(kd.m_fOpen-kd.m_fLow) < 1e-4 && fabs(kd.m_fOpen-fLastClose) < 1e-4 )
		return TRUE;
	return FALSE;
}

// 得到股票的收盘价
BOOL CTechStock::GetClosePrice( CSPTime tmCur, double *pdPrice )
{
	CSPTime	sptimeCur(tmCur.GetTime());
	DWORD	dwDate	=	sptimeCur.ToStockTimeDay();
	int nIndex = m_kdata.GetAboutIndexByDate( dwDate );
	if( -1 == nIndex )
	{
		SP_ASSERT( FALSE );
		return FALSE;
	}

	KDATA	&	kd	=	m_kdata.ElementAt(nIndex);
	if( pdPrice )	*pdPrice	=	kd.m_fClose;
	return TRUE;
}

// 得到股票的收盘价涨幅%
BOOL CTechStock::GetCloseDiffPercent( CSPTime tmCur, double *pdDiffPercent )
{
	if( pdDiffPercent ) *pdDiffPercent = 0;

	CSPTime	sptimeCur(tmCur.GetTime());
	DWORD	dwDate	=	sptimeCur.ToStockTimeDay();
	int nIndex = m_kdata.GetIndexByDate( dwDate );
	if( -1 == nIndex || nIndex <= 0 )
	{
		return FALSE;
	}

	KDATA	&	kd		=	m_kdata.ElementAt(nIndex);
	KDATA	&	kdLast	=	m_kdata.ElementAt(nIndex-1);
	if( pdDiffPercent && kdLast.m_fClose > 1e-4 )
	{
		*pdDiffPercent	=	100. * (kd.m_fClose-kdLast.m_fClose)/kdLast.m_fClose;
	}
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CTechStockContainer

CTechStockContainer::~CTechStockContainer( )
{
	Clear( );
}

void CTechStockContainer::Clear( )
{
	m_infoIndex.Clear();
	m_kdataIndex.Clear();
	m_kdataIndex.SetKType(CKData::ktypeDay);

	int i=0;
	for(  i=0; i<m_techsIndex.GetSize(); i++ )
	{
		CTechnique * pTech	=	(CTechnique *)m_techsIndex.ElementAt(i);
		if( pTech )
			delete	pTech;
	}
	m_techsIndex.RemoveAll();

	for(  i=0; i<GetSize(); i++ )
	{
		CTechStock	&	stock	=	ElementAt(i);
		stock.Clear( );
	}
	RemoveAll();
}

// 给定CTechStock,日期tmCur,资金dCash,交易费率rate,操作条件opparam,
// 现在拥有股票数量nOwnedStockCount,计算需要买入的股票数量和委托价格及委托时间,
// 如果不需要买入,返回FALSE
BOOL CTechStockContainer::GetShouldBuyShare( CTechStock & techstock, CSPTime tmCur, double dCash, CRateParam &rate, COpParam &opparam, int nOwnedStockCount,
									CSPTime *ptmOp, DWORD *pdwShare, double *pdSharePrice )
{
	CSPTime	tmOp = tmCur;
	DWORD	dwShare = 0;
	double	dSharePrice = 0;

	CSPTime	sptimeCur(tmCur.GetTime());
	DWORD	dwDate	=	sptimeCur.ToStockTimeDay();
	int nIndex = techstock.m_kdata.GetIndexByDate( dwDate );	// 得到nIndex,指向techstock.m_kdata数组的当前日期位置
	if( -1 == nIndex )
		return FALSE;
	double	dPriceNow	=	techstock.m_kdata.ElementAt(nIndex).m_fClose;	// 当前价

	// 买入判断
	BOOL	bBuy	=	TRUE;
	if( COpParam::logicOr == opparam.m_nBuyLogic )	// 全部条件还是任一条件
		bBuy	=	FALSE;
	for( int i=0; i<techstock.m_techs.GetSize(); i++ )	// 每一个设定指标,分别判断
	{
		CTechnique * pTech	=	(CTechnique *)techstock.m_techs.ElementAt(i);	// 技术指标
		SP_ASSERT( NULL != pTech );
		if( NULL == pTech )
			continue;

		int nIntensity	=	pTech->GetSignal( nIndex );		// 当前买卖信号
		if( COpParam::logicOr == opparam.m_nBuyLogic )
		{
			if( nIntensity >= opparam.m_nBuyLimit )			// 买卖信号是否达到所需条件
				bBuy	=	TRUE;
		}
		else
		{
			if( nIntensity < opparam.m_nBuyLimit )
				bBuy	=	FALSE;
		}
	}

	// Long and Index Trend
	if( bBuy )
	{
		// 如果技术指标判断为买入,判断是否满足长周期趋势和指数趋势
		if( opparam.m_bLongTrend )	// 长周期趋势
		{
			int	nIndexLong	=	techstock.m_kdataLong.GetAboutIndexByDate( dwDate );
			if( opparam.m_nKTypeLong > opparam.m_nKType )
				nIndexLong	--;
			if( nIndexLong >= 0 )
			{
				for( int i=0; i<techstock.m_techsLong.GetSize(); i++ )
				{
					CTechnique * pTech	=	(CTechnique *)techstock.m_techsLong.ElementAt(i);
					SP_ASSERT( NULL != pTech );
					if( NULL == pTech )
						continue;
					pTech->ClearLastIntensity();
					int nIntensity	=	pTech->GetIntensity( nIndexLong );	// 得到当前趋势
					if( !ITS_ISBUY(nIntensity) )
						bBuy	=	FALSE;
				}
			}
		}
		if( opparam.m_bIndexTrend )	// 指数趋势
		{
			int	nIndexIndex	=	m_kdataIndex.GetAboutIndexByDate( dwDate );
			if( opparam.m_nKTypeIndex > opparam.m_nKType )
				nIndexIndex	--;
			if( nIndexIndex >= 0 )
			{
				for( int i=0; i<m_techsIndex.GetSize(); i++ )
				{
					CTechnique * pTech	=	(CTechnique *)m_techsIndex.ElementAt(i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -