📄 strategy.cpp
字号:
AfxGetDB().GetTimeLocalRange( &tmLatest, NULL, NULL );
m_RealBeginTime = tmLatest;
m_RealCurrentTime = tmLatest;
m_RealCurrentCash = m_opparam.m_nStartAmount;
m_RealOpRecord.RemoveAll();
m_RealNextOp.RemoveAll();
m_RealStockOwn.RemoveAll();
m_RealAssetSerial.RemoveAll();
SP_ASSERT( m_opparam.IsValid() );
}
// 策略实战:下一个交易时间
BOOL CStrategy::RealGotoNextTime( )
{
CSPTime tmNext;
if( m_techstocks.GetNextExistTradeTime( RealGetCurrentTime(), tmNext ) )
{
m_RealCurrentTime = tmNext;
return TRUE;
}
return FALSE;
}
// 策略实战:开始时间
CSPTime CStrategy::RealGetBeginTime( )
{
return m_RealBeginTime;
}
// 策略实战:当前时间
CSPTime CStrategy::RealGetCurrentTime( )
{
return m_RealCurrentTime;
}
// 策略实战:当前资金
double CStrategy::RealGetCurrentCash( )
{
return m_RealCurrentCash;
}
// 策略实战:执行一个操作
BOOL CStrategy::RealOperate( OPRECORD record, BOOL bTimeStrict )
{
if( bTimeStrict && m_RealOpRecord.GetSize() > 0 && record.time < m_RealOpRecord.ElementAt(m_RealOpRecord.GetSize()-1).time )
return FALSE;
CStockInfo info;
if( strlen(record.szCode)>0
&& ( !AfxGetStockContainer().GetStockInfo( record.szCode, &info )
|| !info.IsValidStock() ) )
return FALSE;
double dAmount = record.dwShare * record.dSharePrice;
double dRateCost = record.dRateCost;
if( STRATEGY_OPTYPE_BUY == record.lOpType ) // 买入
{
if( m_RealCurrentCash < dAmount+dRateCost )
return FALSE;
if( !m_RealStockOwn.AddStock( info, record.dwShare, record.dSharePrice ) )
return FALSE;
m_RealCurrentCash -= (dAmount+dRateCost);
}
else if( STRATEGY_OPTYPE_SELL == record.lOpType ) // 卖出
{
if( !m_RealStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
m_RealCurrentCash += (dAmount-dRateCost);
}
else if( STRATEGY_OPTYPE_ADDSTOCK == record.lOpType ) // 添加股票
{
if( !m_RealStockOwn.AddStock( info, record.dwShare, record.dSharePrice ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_REMOVESTOCK == record.lOpType ) // 移除股票
{
if( !m_RealStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_ADDCASH == record.lOpType ) // 加入资金
{
m_RealCurrentCash += record.dSharePrice;
}
else if( STRATEGY_OPTYPE_REMOVECASH == record.lOpType ) // 移除资金
{
if( m_RealCurrentCash < record.dSharePrice )
return FALSE;
m_RealCurrentCash -= record.dSharePrice;
}
else
return FALSE;
// Record
m_RealOpRecord.Add( record );
return TRUE;
}
// 策略实战:操作记录
COpRecordContainer & CStrategy::RealGetOpRecord( )
{
return m_RealOpRecord;
}
// 策略实战:下一步操作计划
COpRecordContainer & CStrategy::RealGetNextOp( )
{
return m_RealNextOp;
}
// 策略实战:当前拥有股票
CStockOwnContainer & CStrategy::RealGetStockOwn( )
{
return m_RealStockOwn;
}
// 策略实战:总资产序列
CAssetSerialContainer & CStrategy::RealGetAssetSerial( )
{
return m_RealAssetSerial;
}
// 策略实战:得到指定日期的总资产
double CStrategy::RealGetAsset( CSPTime tmCur )
{
double dAsset = 0;
if( m_techstocks.GetSumAsset( tmCur, m_RealStockOwn, &dAsset ) )
{
dAsset += m_RealCurrentCash;
ASSETSERIAL serial;
memset( &serial, 0, sizeof(serial) );
serial.time = tmCur.GetTime();
serial.dAsset = dAsset;
serial.dCash = m_RealCurrentCash;
m_RealAssetSerial.SortInsert( serial );
return dAsset;
}
else
{
for( int i=m_RealAssetSerial.GetSize()-1; i>=0; i-- )
{
ASSETSERIAL & serial = m_RealAssetSerial.ElementAt(i);
if( serial.time <= tmCur.GetTime() )
return serial.dAsset;
}
}
return m_opparam.m_nStartAmount;
}
// 策略实战:当前收益
double CStrategy::RealGetCurrentYield( )
{
if( m_opparam.m_nStartAmount > 0 )
return STRATEGY_BASEF_YIELD * RealGetAsset(RealGetCurrentTime()) / m_opparam.m_nStartAmount;
return STRATEGY_BASEF_YIELD;
}
// 策略实战:当前指数上涨百分比
double CStrategy::RealGetCurrentYieldIndexPercent( )
{
CSPTime sptmBegin( RealGetBeginTime().GetTime() );
CSPTime sptmNow( RealGetCurrentTime().GetTime() );
DWORD dateBegin = sptmBegin.ToStockTimeDay();
DWORD dateNow = sptmNow.ToStockTimeDay();
CKData & kdata = AfxGetStockMain().GetKData(m_opparam.m_nKType);
int nIndexBegin = kdata.GetAboutIndexByDate( dateBegin );
int nIndexNow = kdata.GetAboutIndexByDate( dateNow );
if( -1 == nIndexBegin || -1 == nIndexNow )
return 0;
if( kdata.ElementAt(nIndexBegin).m_fClose < 1e-4 )
return 0;
double dYield = ((double)kdata.ElementAt(nIndexNow).m_fClose) - kdata.ElementAt(nIndexBegin).m_fClose;
dYield = dYield / kdata.ElementAt(nIndexBegin).m_fClose;
return dYield;
}
// 策略实战:当前收益百分比
double CStrategy::RealGetCurrentYieldPercent( )
{
return ( RealGetCurrentYield() - STRATEGY_BASEF_YIELD ) / STRATEGY_BASEF_YIELD;
}
// 策略实战:执行操作计划
BOOL CStrategy::RealOperateNextop( CSPTime tmCur, COpRecordContainer & nextop, CTechStock & techstock )
{
for( int j=0; j<nextop.GetSize(); j++ ) // 依次执行每一个计划
{
OPRECORD & record = nextop.ElementAt(j);
if( STRATEGY_OPTYPE_BUY != record.lOpType && STRATEGY_OPTYPE_SELL != record.lOpType )
continue;
if( tmCur.GetTime() >= record.time
&& techstock.m_info.IsEqualTo( CStock::marketUnknown, record.szCode ) )
{
if( !record.bViewed ) // Not Viewed
{
nextop.RemoveAt(j);
j --;
continue;
}
if( techstock.IsStopTrading(tmCur) ) // 停牌,转入下一个交易日的计划中
{
CSPTime tmNext;
if( m_opparam.GetNextTradeTime(tmCur, tmNext) )
record.time = tmNext.GetTime();
continue;
}
double dPriceOK = record.dSharePrice;
if( techstock.GetPriceOK( record.lOpType, tmCur, record.dwShare, record.dSharePrice, &dPriceOK ) ) // 成交价格
{
record.time = tmCur.GetTime();
record.dSharePrice = dPriceOK;
record.dRateCost = record.dwShare * record.dSharePrice * m_rate.GetRate(techstock.m_info);
RealOperate( record );
}
else if( STRATEGY_OPTYPE_SELL == record.lOpType ) // 如果是卖出不成功,转入下一个交易日,直至卖出成功
{
CSPTime tmNext;
if( m_opparam.GetNextTradeTime(tmCur, tmNext) )
record.time = tmNext.GetTime();
if( techstock.GetClosePrice(tmCur,&dPriceOK) )
record.dSharePrice = dPriceOK * m_opparam.m_dSellMulti;
continue;
}
nextop.RemoveAt(j);
j --;
}
}
return TRUE;
}
// 策略实战:执行
BOOL CStrategy::RealRun( SIMULATION_CALLBACK fnCallback, void * cookie )
{
// TIMEZONES
// 准备数据
if( !PrepareData( fnCallback, cookie ) )
return FALSE;
ClearLastIntensity( );
DWORD dwShare = 0; // Temp Data
double dSharePrice = 0; // Temp Data
CSPTime tmOp; // Temp Data
do {
CSPTime tmCur = RealGetCurrentTime(); // 当前日期
// Process
for( int i=0; i<m_techstocks.GetSize(); i++ ) // 每只股票依次判断
{
CTechStock & techstock = m_techstocks.ElementAt(i);
// Operate
RealOperateNextop( tmCur, m_RealNextOp, techstock ); // 执行今日操作计划
// Judge Whether to operate, if yes, save to nextop
STOCKOWN own;
memset( &own, 0, sizeof(own) );
if( m_RealStockOwn.HasThisStock( techstock.m_info, &own ) ) // 如果有这支股票,判断是否卖出
{
if( m_techstocks.GetShouldSellShare( techstock, tmCur, own, m_opparam, &tmOp, &dwShare, &dSharePrice ) )
{ // 如果卖出,加入操作计划中
m_RealNextOp.AddRecordUniqueStock( STRATEGY_OPTYPE_SELL, tmOp, techstock.m_info.GetStockCode(), dwShare, dSharePrice, dwShare*dSharePrice*m_rate.GetRate(techstock.m_info) );
}
}
else // 判断是否买入
{
if( m_techstocks.GetShouldBuyShare( techstock, tmCur, m_RealCurrentCash, m_rate , m_opparam, m_RealStockOwn.GetSize(), &tmOp, &dwShare, &dSharePrice )
&& ( m_RealStockOwn.GetSize() + m_RealNextOp.GetBuyRecordCount() < m_opparam.m_nStoreDiv || m_RealNextOp.HasBuyStock(techstock.m_info.GetStockCode()) ) )
{ // 如果买入,加入操作计划中
m_RealNextOp.AddRecordUniqueStock( STRATEGY_OPTYPE_BUY, tmOp, techstock.m_info.GetStockCode(), dwShare, dSharePrice, dwShare*dSharePrice*m_rate.GetRate(techstock.m_info) );
}
}
// 进度显示
DWORD dwProgress = (DWORD)((i+1)*STRATEGY_MAX_PROGRESS/m_techstocks.GetSize());
if( fnCallback && !fnCallback( SIMULATION_PROGRESS, dwProgress, NULL, cookie ) )
return FALSE;
}
RealGetAsset( RealGetCurrentTime() );
} while( RealGotoNextTime() ); // 下一个交易日
if( fnCallback )
fnCallback( SIMULATION_PROGRESS, STRATEGY_MAX_PROGRESS, NULL, cookie );
return TRUE;
}
// 策略实战:加入操作记录,如果成功,同时要删除加入日后的所有操作
BOOL CStrategy::RealAddOpRecordStrict( OPRECORD record )
{
COpRecordContainer recordbk;
recordbk.Copy( m_RealOpRecord );
// 重新执行操作记录,到加入新操作日为止
BOOL bOK = TRUE;
m_RealCurrentCash = m_opparam.m_nStartAmount;
m_RealOpRecord.RemoveAll();
m_RealNextOp.RemoveAll();
m_RealStockOwn.RemoveAll();
for( int i=0; i<recordbk.GetSize(); i++ )
{
OPRECORD rec = recordbk.ElementAt(i);
if( bOK && rec.time < record.time )
bOK &= RealOperate( rec );
}
if( bOK && RealOperate( record ) )
{ // 加入成功,重新计算总资产序列
for( int i=m_RealAssetSerial.GetSize()-1; i>=0; i-- )
{
ASSETSERIAL serial = m_RealAssetSerial.ElementAt(i);
if( serial.time >= record.time )
m_RealAssetSerial.RemoveAt(i);
}
RealGetAsset( record.time );
return TRUE;
}
else
{
// 加入失败,全部重来,恢复原样
m_RealCurrentCash = m_opparam.m_nStartAmount;
m_RealOpRecord.RemoveAll();
m_RealNextOp.RemoveAll();
m_RealStockOwn.RemoveAll();
for( int i=0; i<recordbk.GetSize(); i++ )
{
OPRECORD rec = recordbk.ElementAt(i);
RealOperate( rec );
}
return FALSE;
}
}
// 策略实战:删除操作记录,如果成功,同时要删除日后的所有操作
BOOL CStrategy::RealDeleteOpRecordStrict( int nRecord )
{
if( nRecord < 0 || nRecord >= m_RealOpRecord.GetSize() )
{
SP_ASSERT( FALSE );
return FALSE;
}
OPRECORD record = m_RealOpRecord.ElementAt(nRecord);
COpRecordContainer recordbk;
recordbk.Copy( m_RealOpRecord );
// 重新执行操作记录,到删除日为止
BOOL bOK = TRUE;
m_RealCurrentCash = m_opparam.m_nStartAmount;
m_RealOpRecord.RemoveAll();
m_RealNextOp.RemoveAll();
m_RealStockOwn.RemoveAll();
for( int i=0; i<recordbk.GetSize(); i++ )
{
OPRECORD rec = recordbk.ElementAt(i);
if( bOK && rec.time < record.time )
bOK &= RealOperate( rec );
}
if( bOK )
{ // 成功删除,重新计算总资产序列
for( int i=m_RealAssetSerial.GetSize()-1; i>=0; i-- )
{
ASSETSERIAL serial = m_RealAssetSerial.ElementAt(i);
if( serial.time >= record.time )
m_RealAssetSerial.RemoveAt(i);
}
RealGetAsset( record.time );
return TRUE;
}
else
{
// 删除失败,恢复原样
m_RealCurrentCash = m_opparam.m_nStartAmount;
m_RealOpRecord.RemoveAll();
m_RealNextOp.RemoveAll();
m_RealStockOwn.RemoveAll();
for( int i=0; i<recordbk.GetSize(); i++ )
{
OPRECORD rec = recordbk.ElementAt(i);
RealOperate( rec );
}
return FALSE;
}
}
/*
BOOL CStrategy::RealUnOperate( OPRECORD record )
{
CStockInfo info;
if( strlen(record.szCode)>0
&& ( !AfxGetStockContainer().GetStockInfo( record.szCode, &info )
|| !info.IsValidStock() ) )
return FALSE;
double dAmount = record.dwShare * record.dSharePrice;
double dRateCost = record.dRateCost;
if( STRATEGY_OPTYPE_BUY == record.lOpType )
{
if( !m_RealStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
m_RealCurrentCash += (dAmount+dRateCost);
}
else if( STRATEGY_OPTYPE_SELL == record.lOpType )
{
if( m_RealCurrentCash < dAmount-dRateCost )
return FALSE;
if( !m_RealStockOwn.AddStock( info, record.dwShare ) )
return FALSE;
m_RealCurrentCash -= (dAmount-dRateCost);
}
else if( STRATEGY_OPTYPE_ADDSTOCK == record.lOpType )
{
if( !m_RealStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_REMOVESTOCK == record.lOpType )
{
if( !m_RealStockOwn.AddStock( info, record.dwShare ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_ADDCASH == record.lOpType )
{
if( m_RealCurrentCash < record.dSharePrice )
return FALSE;
m_RealCurrentCash -= record.dSharePrice;
}
else if( STRATEGY_OPTYPE_REMOVECASH == record.lOpType )
{
m_RealCurrentCash += record.dSharePrice;
}
else
return FALSE;
return TRUE;
}
BOOL CStrategy::RealAddOpRecordStrict( OPRECORD record )
{
COpRecordContainer recordbk;
recordbk.Copy( m_RealOpRecord );
BOOL bOK = TRUE;
for( int i=m_RealOpRecord.GetSize()-1; i>=0; i-- )
{
OPRECORD rec = m_RealOpRecord.ElementAt(i);
if( bOK && rec.time > record.time )
{
bOK &= RealUnOperate( rec );
if( bOK )
m_RealOpRecord.RemoveAt(i);
}
}
if( bOK && RealOperate( record ) )
{
for( i=m_RealAssetSerial.GetSize()-1; i>=0; i-- )
{
ASSETSERI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -