?? strategy.cpp
字號:
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( 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
// 準備數(shù)據(jù),讀取K線數(shù)據(jù),長周期K線數(shù)據(jù),生成技術(shù)指標對象
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 ) // 指數(shù)K線數(shù)據(jù)
{
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++ ) // 讀取每一只備選股票的數(shù)據(jù)
{
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
// 策略模擬:重新設(shè)定
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;
}
// 策略模擬:操作執(zhí)行,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;
}
// 策略模擬:總資產(chǎn)序列
CAssetSerialContainer & CStrategy::SimuGetAssetSerial( )
{
return m_SimuAssetSerial;
}
// 策略模擬:當前進度
DWORD CStrategy::SimuGetCurrentProgress( DWORD dwProgressMax )
{
return m_opparam.GetProgress( m_SimuCurrentTime, dwProgressMax );
}
// 策略模擬:給定時間的總資產(chǎn)
double CStrategy::SimuGetAsset( CSPTime tmCur )
{
double dAsset = 0;
if( m_techstocks.GetSumAsset( tmCur, m_SimuStockOwn, &dAsset ) ) // 計算總資產(chǎn)
{
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; // 初始總資產(chǎn)
}
// 策略模擬:當前收益
double CStrategy::SimuGetCurrentYield( )
{
if( m_opparam.m_nStartAmount > 0 )
return STRATEGY_BASEF_YIELD * SimuGetAsset(m_SimuCurrentTime) / m_opparam.m_nStartAmount;
return STRATEGY_BASEF_YIELD;
}
// 策略模擬:當前指數(shù)上漲多少
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;
}
// 策略模擬:當前收益百分數(shù)
double CStrategy::SimuGetCurrentYieldPercent( )
{
return ( SimuGetCurrentYield() - STRATEGY_BASEF_YIELD ) / STRATEGY_BASEF_YIELD;
}
// 策略模擬:執(zhí)行下一步操作計劃
BOOL CStrategy::SimuOperateNextop( CSPTime tmCur, COpRecordContainer & nextop, CTechStock & techstock )
{
for( int j=0; j<nextop.GetSize(); j++ ) // 每個計劃依次執(zhí)行
{
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(); // 下次再執(zhí)行
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
// 準備數(shù)據(jù)
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 ); // 執(zhí)行今天的操作計劃
// Judge Whether to operate, if yes, save to nextop
STOCKOWN own;
memset( &own, 0, sizeof(own) );
if( m_SimuStockOwn.HasThisStock( techstock.m_info, &own ) ) // 如果已經(jīng)有這支股票,判斷是否賣出
{
if( m_techstocks.GetShouldSellShare( techstock, tmCur, own, m_opparam, &tmOp, &dwShare, &dSharePrice ) )
{ // 如果要賣出,加入下一步操作計劃,下一個交易日執(zhí)行
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()) ) )
{ // 如果要買入,加入下一步操作計劃,下一個交易日執(zhí)行
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
// 策略實戰(zhàn):重新設(shè)定
void CStrategy::RealReset( )
{
CSPTime tmLatest = CSPTime::GetCurrentTime();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -