📄 strategy.cpp.svn-base
字号:
if( AfxGetStockContainer().GetStockInfo( m_stocks.ElementAt(i), &info ) )
//#ifdef CLKLAN_ENGLISH_US
// strStock += info.GetStockCode();
//#else
strStock += info.GetStockName();
//#endif
else
strStock += m_stocks.ElementAt(i);
}
if( strStock.GetLength() == 0 )
strStock = strategy_noselectedstock;
else if( m_stocks.GetSize() > nStockShowCount )
strStock += "...";
strStock += "; ";
CSPString strTech;
for( int i=0; i<m_anTechsBuy.GetSize() && i<nTechShowCount; i++ )
{
if( strTech.GetLength() > 0 )
strTech += ",";
strTech += AfxGetSTTShortName(m_anTechsBuy[i]);
}
if( strTech.GetLength() == 0 )
strTech = strategy_noselectedtech;
else if( m_anTechsBuy.GetSize() > nTechShowCount )
strTech += "...";
return strStock + strTech;
}
// 交易费率、操作条件等
CRateParam & CStrategy::GetRateParam( ) { return m_rate; }
COpParam & CStrategy::GetOpParam( ) { return m_opparam; }
CTechParameters & CStrategy::GetTechParametersBuy( ) { return m_paramBuy; }
CTechParameters & CStrategy::GetTechParametersSell( ) { return m_paramSell; }
CTechParameters & CStrategy::GetTechParametersLongTrend( ) { return m_paramLongTrend; }
CTechParameters & CStrategy::GetTechParametersIndexTrend( ) { return m_paramIndexTrend; }
CSPDWordArray & CStrategy::GetSelectedTechsBuy( ) { return m_anTechsBuy; }
CSPDWordArray & CStrategy::GetSelectedTechsSell( ) { return m_anTechsSell; }
CSPDWordArray & CStrategy::GetSelectedTechsLongTrend( ) { return m_anTechsLongTrend; }
CSPDWordArray & CStrategy::GetSelectedTechsIndexTrend( ) { return m_anTechsIndexTrend; }
/////////////////////////////////////////////////////////////////////////
// Cache
// 准备数据,读取K线数据,长周期K线数据,生成技术指标对象
BOOL CStrategy::PrepareData( SIMULATION_CALLBACK fnCallback, void * cookie )
{
if( m_techstocks.GetSize() == m_stocks.GetSize() )
return TRUE;
ClearCache( );
// m_techstocks.m_kdataIndex m_techstocks.m_infoIndex
if( m_opparam.m_bIndexTrend ) // 指数K线数据
{
CStockInfo infoIndex;
if( AfxGetStockContainer().GetStockInfo( STKLIB_CODE_MAIN, &infoIndex ) )
{
m_techstocks.m_infoIndex = infoIndex;
CStock stockIndex;
stockIndex.SetStockInfo( &infoIndex );
stockIndex.SetDatabase( &AfxGetDB() );
stockIndex.PrepareData( CStock::dataK, m_opparam.m_nKTypeIndex );
CKData & kdataIndex = stockIndex.GetKData(m_opparam.m_nKTypeIndex);
kdataIndex.SetMaindataType( m_opparam.m_nMaindataType );
m_techstocks.m_kdataIndex = kdataIndex;
// m_techstocks.m_techsIndex
for( int j=0; j<m_anTechsIndexTrend.GetSize(); j++ )
{
CTechnique * pTech = CTechnique::CreateTechnique( m_anTechsIndexTrend[j], &(m_techstocks.m_kdataIndex) );
m_paramIndexTrend.FindParameters( m_anTechsIndexTrend[j], pTech );
m_techstocks.m_techsIndex.Add( pTech );
}
}
}
m_techstocks.SetSize( m_stocks.GetSize() );
int nStockCount = 0;
for( int i=0; i<m_stocks.GetSize(); i++ ) // 读取每一只备选股票的数据
{
CStockInfo info;
if( AfxGetStockContainer().GetStockInfo( m_stocks.ElementAt(i), &info ) )
{
// CTechStock::m_info;
CTechStock temp;
temp.m_info = info;
m_techstocks.SetAt( nStockCount, temp );
CTechStock & techstock = m_techstocks.ElementAt(nStockCount);
nStockCount ++;
// CTechStock::m_kdata
CStock stock;
stock.SetStockInfo( &info );
AfxPrepareStockData( &AfxGetDB(), stock, m_opparam.m_nKType, CKData::formatXDRdown, m_opparam.m_nMaindataType, FALSE, FALSE );
techstock.m_kdata = stock.GetKData(m_opparam.m_nKType);
// CTechStock::m_techs
techstock.SetAutoDelete( TRUE );
for( int j=0; j<m_anTechsBuy.GetSize(); j++ )
{
CTechnique * pTech = CTechnique::CreateTechnique( m_anTechsBuy[j], &(techstock.m_kdata) );
m_paramBuy.FindParameters( m_anTechsBuy[j], pTech );
techstock.m_techs.Add( pTech );
}
// CTechStock::m_kdataLong
if( m_opparam.m_bLongTrend )
{
AfxPrepareStockData( &AfxGetDB(), stock, m_opparam.m_nKTypeLong, CKData::formatXDRdown, m_opparam.m_nMaindataType, FALSE, FALSE );
techstock.m_kdataLong = stock.GetKData( m_opparam.m_nKTypeLong );
// CTechStock::m_techsLong
for( int j=0; j<m_anTechsLongTrend.GetSize(); j++ )
{
CTechnique * pTech = CTechnique::CreateTechnique( m_anTechsLongTrend[j], &(techstock.m_kdataLong) );
m_paramLongTrend.FindParameters( m_anTechsLongTrend[j], pTech );
techstock.m_techsLong.Add( pTech );
}
}
}
DWORD dwProgress = (DWORD)((i+1)*STRATEGY_MAXF_PROGRESS / m_stocks.GetSize());
if( fnCallback && !fnCallback( SIMULATION_PROGRESS, dwProgress, NULL, cookie ) )
{
ClearCache( );
nStockCount = 0;
break;
}
}
m_techstocks.SetSize( nStockCount );
if( fnCallback )
fnCallback( SIMULATION_PROGRESS, STRATEGY_MAX_PROGRESS, NULL, cookie );
return ( m_techstocks.GetSize() == m_stocks.GetSize() );
}
// 清除每个指标保存的上次趋势值
void CStrategy::ClearLastIntensity( )
{
for( int i=0; i<m_techstocks.GetSize(); i++ )
{
CTechStock & techstock = m_techstocks.ElementAt(i);
for( int nTech=0; nTech<techstock.m_techs.GetSize(); nTech++ )
{
CTechnique * pTech = (CTechnique *)techstock.m_techs.ElementAt(nTech);
if( pTech )
pTech->ClearLastIntensity();
}
}
}
void CStrategy::ClearCache( )
{
m_techstocks.Clear();
}
CTechStockContainer & CStrategy::GetTechStockContainer( )
{
return m_techstocks;
}
////////////////////////////////////////////////////////////////////////
// Simulation
// 策略模拟:重新设定
void CStrategy::SimuReset( )
{
SimuSetStatusInit( );
m_SimuCurrentTime = m_opparam.GetBeginTime( );
m_SimuCurrentCash = m_opparam.m_nStartAmount;
m_SimuOpRecord.RemoveAll();
m_SimuNextOp.RemoveAll();
m_SimuStockOwn.RemoveAll();
m_SimuAssetSerial.RemoveAll();
SP_ASSERT( m_opparam.IsValid() );
}
// 策略模拟:进入下一个交易日
BOOL CStrategy::SimuGotoNextTime( )
{
CSPTime tmNext;
if( m_opparam.GetNextTradeTime( m_SimuCurrentTime, tmNext )
&& m_opparam.IsInTimeZones( tmNext ) )
{
m_SimuCurrentTime = tmNext;
return TRUE;
}
return FALSE;
}
// 策略模拟:模拟的当前时间
CSPTime CStrategy::SimuGetCurrentTime( )
{
return m_SimuCurrentTime;
}
// 策略模拟:模拟的当前资金
double CStrategy::SimuGetCurrentCash( )
{
return m_SimuCurrentCash;
}
// 策略模拟:操作执行,bTimeStrict表示是否严格遵守计划时间
BOOL CStrategy::SimuOperate( OPRECORD record, BOOL bTimeStrict )
{
if( ! m_opparam.IsInTimeZones( record.time ) )
return FALSE;
if( bTimeStrict && m_SimuOpRecord.GetSize() > 0 && record.time < m_SimuOpRecord.ElementAt(m_SimuOpRecord.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_SimuCurrentCash < dAmount+dRateCost )
return FALSE;
if( !m_SimuStockOwn.AddStock( info, record.dwShare, record.dSharePrice ) )
return FALSE;
m_SimuCurrentCash -= (dAmount+dRateCost);
}
else if( STRATEGY_OPTYPE_SELL == record.lOpType ) // 卖出
{
if( !m_SimuStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
m_SimuCurrentCash += (dAmount-dRateCost);
}
else if( STRATEGY_OPTYPE_ADDSTOCK == record.lOpType )// 添加股票
{
if( !m_SimuStockOwn.AddStock( info, record.dwShare, record.dSharePrice ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_REMOVESTOCK == record.lOpType )// 移除股票
{
if( !m_SimuStockOwn.RemoveStock( info, record.dwShare ) )
return FALSE;
}
else if( STRATEGY_OPTYPE_ADDCASH == record.lOpType ) // 添加资金
{
m_SimuCurrentCash += record.dSharePrice;
}
else if( STRATEGY_OPTYPE_REMOVECASH == record.lOpType ) // 移除资金
{
if( m_SimuCurrentCash < record.dSharePrice )
return FALSE;
m_SimuCurrentCash -= record.dSharePrice;
}
else
return FALSE;
// Record
m_SimuOpRecord.Add( record );
return TRUE;
}
// 策略模拟:操作记录
COpRecordContainer & CStrategy::SimuGetOpRecord( )
{
return m_SimuOpRecord;
}
// 策略模拟:下一步操作
COpRecordContainer & CStrategy::SimuGetNextOp( )
{
return m_SimuNextOp;
}
// 策略模拟:当前拥有股票
CStockOwnContainer & CStrategy::SimuGetStockOwn( )
{
return m_SimuStockOwn;
}
// 策略模拟:总资产序列
CAssetSerialContainer & CStrategy::SimuGetAssetSerial( )
{
return m_SimuAssetSerial;
}
// 策略模拟:当前进度
DWORD CStrategy::SimuGetCurrentProgress( DWORD dwProgressMax )
{
return m_opparam.GetProgress( m_SimuCurrentTime, dwProgressMax );
}
// 策略模拟:给定时间的总资产
double CStrategy::SimuGetAsset( CSPTime tmCur )
{
double dAsset = 0;
if( m_techstocks.GetSumAsset( tmCur, m_SimuStockOwn, &dAsset ) ) // 计算总资产
{
dAsset += m_SimuCurrentCash;
ASSETSERIAL serial;
memset( &serial, 0, sizeof(serial) );
serial.time = tmCur.GetTime();
serial.dAsset = dAsset;
serial.dCash = m_SimuCurrentCash;
m_SimuAssetSerial.SortInsert( serial );
return dAsset;
}
else
{
for( int i=m_SimuAssetSerial.GetSize()-1; i>=0; i-- )
{
ASSETSERIAL & serial = m_SimuAssetSerial.ElementAt(i);
if( serial.time <= tmCur.GetTime() )
return serial.dAsset;
}
}
return m_opparam.m_nStartAmount; // 初始总资产
}
// 策略模拟:当前收益
double CStrategy::SimuGetCurrentYield( )
{
if( m_opparam.m_nStartAmount > 0 )
return STRATEGY_BASEF_YIELD * SimuGetAsset(m_SimuCurrentTime) / m_opparam.m_nStartAmount;
return STRATEGY_BASEF_YIELD;
}
// 策略模拟:当前指数上涨多少
double CStrategy::SimuGetCurrentYieldIndexPercent( )
{
CSPTime sptmBegin( m_opparam.GetBeginTime().GetTime() );
CSPTime sptmNow( m_SimuCurrentTime.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::SimuGetCurrentYieldPercent( )
{
return ( SimuGetCurrentYield() - STRATEGY_BASEF_YIELD ) / STRATEGY_BASEF_YIELD;
}
// 策略模拟:执行下一步操作计划
BOOL CStrategy::SimuOperateNextop( 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( 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);
SimuOperate( 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::SimuRun( 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 = SimuGetCurrentTime(); // 模拟当前时间
// Process
for( int i=0; i<m_techstocks.GetSize(); i++ ) // 每只股票依次判断
{
CTechStock & techstock = m_techstocks.ElementAt(i);
// Operate
SimuOperateNextop( tmCur, m_SimuNextOp, techstock ); // 执行今天的操作计划
// Judge Whether to operate, if yes, save to nextop
STOCKOWN own;
memset( &own, 0, sizeof(own) );
if( m_SimuStockOwn.HasThisStock( techstock.m_info, &own ) ) // 如果已经有这支股票,判断是否卖出
{
if( m_techstocks.GetShouldSellShare( techstock, tmCur, own, m_opparam, &tmOp, &dwShare, &dSharePrice ) )
{ // 如果要卖出,加入下一步操作计划,下一个交易日执行
m_SimuNextOp.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_SimuCurrentCash, m_rate , m_opparam, m_SimuStockOwn.GetSize(), &tmOp, &dwShare, &dSharePrice )
&& ( m_SimuStockOwn.GetSize() + m_SimuNextOp.GetBuyRecordCount() < m_opparam.m_nStoreDiv || m_SimuNextOp.HasBuyStock(techstock.m_info.GetStockCode()) ) )
{ // 如果要买入,加入下一步操作计划,下一个交易日执行
m_SimuNextOp.AddRecordUniqueStock( STRATEGY_OPTYPE_BUY, tmOp, techstock.m_info.GetStockCode(), dwShare, dSharePrice, dwShare*dSharePrice*m_rate.GetRate(techstock.m_info) );
}
}
}
// 进度显示
DWORD dwProgress = SimuGetCurrentProgress( STRATEGY_MAX_PROGRESS );
double dYield = SimuGetCurrentYield( );
if( fnCallback && !fnCallback( SIMULATION_PROGRESS, dwProgress, NULL, cookie ) )
return FALSE;
if( fnCallback && !fnCallback( SIMULATION_YIELD, (DWORD)dYield, NULL, cookie ) )
return FALSE;
} while( SimuGotoNextTime() ); // 模拟的下一个交易日
if( fnCallback )
fnCallback( SIMULATION_PROGRESS, STRATEGY_MAX_PROGRESS, NULL, cookie );
return TRUE;
}
////////////////////////////////////////////////////////////////////////
// Real
// 策略实战:重新设定
void CStrategy::RealReset( )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -