📄 strategy.cpp
字号:
// 操作记录数组,加入记录
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 + -