Container.cpp
上传用户:zhanglf88
上传日期:2013-11-19
资源大小:6036k
文件大小:42k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. /*
  2. Cross Platform Core Code.
  3. Copyright(R) 2001-2002 Balang Software.
  4. All rights reserved.
  5. Using:
  6. class CStockInfoArray;
  7. class CStockContainer;
  8. class CDomain;
  9. class CDomainContainer;
  10. */
  11. #include "stdafx.h"
  12. #include "../Include/Container.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char THIS_FILE[]=__FILE__;
  16. #define new DEBUG_NEW
  17. #endif
  18. //////////////////////////////////////////////////////////////////////
  19. // class CStockContainer
  20. CStockContainer * CStockContainer::m_pSortContainer = NULL;
  21. //////////////////////////////////////////////////////////////////////
  22. // Construction/Destruction
  23. //////////////////////////////////////////////////////////////////////
  24. CStockContainer::CStockContainer()
  25. {
  26. m_nType = typeNone;
  27. m_dwDate = -1;
  28. m_nCurrentStock = -1;
  29. m_nSortVariantID = SLH_INVALID;
  30. m_bSortAscend = FALSE;
  31. }
  32. CStockContainer::~CStockContainer()
  33. {
  34. Clear( );
  35. }
  36. BOOL CStockContainer::Lock()
  37. {
  38. return m_mutex.Lock();
  39. }
  40. BOOL CStockContainer::UnLock()
  41. {
  42. return m_mutex.UnLock();
  43. }
  44. int CStockContainer::Add( CStockInfo &newElement )
  45. {
  46. CSPMutex::Scoped l(m_mutex);
  47. int nIndex = CStockInfoArray::Add(newElement);
  48. m_map.SetAt( newElement.GetStockCode(), (void *)nIndex );
  49. return nIndex;
  50. }
  51. BOOL CStockContainer::GetCurrentType( int *pType, CSPString * pDomain, DWORD *pdwDate )
  52. {
  53. CSPMutex::Scoped l(m_mutex);
  54. if( pType )
  55. *pType = m_nType;
  56. if( pDomain )
  57. *pDomain = m_strDomain;
  58. if( pdwDate )
  59. *pdwDate = m_dwDate;
  60. return TRUE;
  61. }
  62. BOOL CStockContainer::GetPioneerTechDate( DWORD * pdwDate )
  63. {
  64. CStockInfo info;
  65. if( GetStockInfo( STKLIB_CODE_MAIN, &info )
  66. && info.m_kdata.GetSize() > 0 )
  67. {
  68. *pdwDate = info.m_kdata.ElementAt(0).m_date;
  69. return TRUE;
  70. }
  71. return FALSE;
  72. }
  73. BOOL CStockContainer::GetLatestTechDate( DWORD * pdwDate )
  74. {
  75. CStockInfo info;
  76. if( GetStockInfo( STKLIB_CODE_MAIN, &info )
  77. && info.m_kdata.GetSize() > 0 )
  78. {
  79. *pdwDate = info.m_kdata.ElementAt(info.m_kdata.GetSize()-1).m_date;
  80. return TRUE;
  81. }
  82. return FALSE;
  83. }
  84. BOOL CStockContainer::GetTechDateArray( CSPDWordArray & dwArray )
  85. {
  86. CStockInfo info;
  87. if( GetStockInfo( STKLIB_CODE_MAIN, &info ) )
  88. {
  89. dwArray.SetSize( 0, info.m_kdata.GetSize()+10 );
  90. for( int i=0; i<info.m_kdata.GetSize(); i++ )
  91. dwArray.Add( info.m_kdata.ElementAt(i).m_date );
  92. return TRUE;
  93. }
  94. return FALSE;
  95. }
  96. BOOL CStockContainer::RetrieveFromStatic( int nType, LPCTSTR lpszDomain, CStrategy * pStrategy, DWORD dwDate )
  97. {
  98. CSPMutex::Scoped l(m_mutex);
  99. Clear( );
  100. if( nType == typeNone )
  101. {
  102. m_nType = typeNone;
  103. return TRUE;
  104. }
  105. if( nType < typeMin || nType > typeMax )
  106. return FALSE;
  107. m_nType = nType;
  108. m_dwDate = dwDate;
  109. CSPStringArray astrSpecify;
  110. switch( nType )
  111. {
  112. case typeAll:
  113. CopyData( AfxGetStockContainer() );
  114. break;
  115. case typeIndex:
  116. case typeA:
  117. case typeBond:
  118. case typeFund:
  119. case typeClassShaa:
  120. case typeClassShab:
  121. case typeClassSzna:
  122. case typeClassSznb:
  123. case typeClassShabond:
  124. case typeClassSznbond:
  125. case typeRight:
  126. {
  127. int nCount = 0;
  128. SetSize( 0, AfxGetStockContainer().GetSize() );
  129. for( int i=0; i<AfxGetStockContainer().GetSize(); i++ )
  130. {
  131. CStockInfo & info = AfxGetStockContainer().ElementAt(i);
  132. LONG stocktype = info.GetType();
  133. if( ( typeIndex == nType && CStock::typeshIndex == stocktype )
  134. || ( typeIndex == nType && CStock::typeszIndex == stocktype )
  135. || ( typeA == nType && (CStock::typeshA == stocktype || CStock::typeszA == stocktype) && !info.IsFund() )
  136. || ( typeBond == nType && (CStock::typeshBond == stocktype || CStock::typeszBond == stocktype) )
  137. || ( typeFund == nType && info.IsFund() )
  138. || ( typeClassShaa == nType && CStock::typeshA == stocktype )
  139. || ( typeClassShab == nType && CStock::typeshB == stocktype )
  140. || ( typeClassSzna == nType && CStock::typeszA == stocktype )
  141. || ( typeClassSznb == nType && CStock::typeszB == stocktype )
  142. || ( typeClassShabond == nType && CStock::typeshBond == stocktype )
  143. || ( typeClassSznbond == nType && CStock::typeszBond == stocktype )
  144. || ( typeRight == nType && (CStock::typeshRight == stocktype || CStock::typeszRight == stocktype) ) )
  145. {
  146. Add( info );
  147. nCount ++;
  148. }
  149. }
  150. SetSize( nCount );
  151. }
  152. break;
  153. case typeStrategy:
  154. {
  155. if( pStrategy )
  156. RetrieveSpecify( pStrategy->GetStocks() );
  157. }
  158. break;
  159. case typeGroup:
  160. {
  161. if( lpszDomain && strlen(lpszDomain) > 0 )
  162. {
  163. AfxGetGroupContainer().GetDomainStocks( lpszDomain, astrSpecify );
  164. RetrieveSpecify( astrSpecify );
  165. m_strDomain = lpszDomain;
  166. }
  167. else
  168. return AfxGetGroupContainer().GetAllDomainInfo( this, m_dwDate );
  169. }
  170. break;
  171. case typeDomain:
  172. {
  173. if( lpszDomain && strlen(lpszDomain) > 0 )
  174. {
  175. AfxGetDomainContainer().GetDomainStocks( lpszDomain, astrSpecify );
  176. RetrieveSpecify( astrSpecify );
  177. m_strDomain = lpszDomain;
  178. }
  179. else
  180. return AfxGetDomainContainer().GetAllDomainInfo( this, m_dwDate );
  181. }
  182. break;
  183. default:
  184. SP_ASSERT( FALSE );
  185. SetMap( );
  186. SetAverage( );
  187. return FALSE;
  188. }
  189. SetMap( );
  190. DWORD dwMainDate = -1;
  191. AfxGetStockContainer().GetCurrentType( NULL, NULL, &dwMainDate );
  192. if( m_dwDate != dwMainDate )
  193. OnDataChanged();
  194. else
  195. SetAverage( );
  196. return TRUE;
  197. }
  198. BOOL CStockContainer::ReRetrieveFromStatic( CStrategy * pStrategy, BOOL bUpToDate )
  199. {
  200. CSPMutex::Scoped l(m_mutex);
  201. int type;
  202. CSPString strDomain;
  203. DWORD dwDate;
  204. GetCurrentType( &type, &strDomain, &dwDate );
  205. if( bUpToDate )
  206. dwDate = -1;
  207. return RetrieveFromStatic( type, strDomain, pStrategy, dwDate );
  208. }
  209. BOOL CStockContainer::RetrieveSpecify( CSPStringArray & astr )
  210. {
  211. CSPMutex::Scoped l(m_mutex);
  212. SetSize( 0, astr.GetSize() );
  213. int nCount = 0;
  214. for( int i=0; i<astr.GetSize(); i++ )
  215. {
  216. CSPString string = astr.ElementAt(i);
  217. CStockInfo info;
  218. if( AfxGetStockContainer().GetStockInfo( string, &info ) )
  219. {
  220. Add( info );
  221. nCount ++;
  222. }
  223. }
  224. SetSize( nCount );
  225. return TRUE;
  226. }
  227. BOOL CStockContainer::GetStockInfo( const char * szCode, CStockInfo * pInfo, int * pid )
  228. {
  229. CSPMutex::Scoped l(m_mutex);
  230. if( NULL == szCode || strlen(szCode) <= 0 )
  231. return FALSE;
  232. void * pArrayID = NULL;
  233. if( m_map.Lookup( szCode, pArrayID ) )
  234. {
  235. if( ((int)pArrayID) >= 0 && ((int)pArrayID) < GetSize() )
  236. {
  237. CStockInfo & info = ElementAt((int)pArrayID);
  238. if( pInfo )
  239. *pInfo = info;
  240. if( pid )
  241. *pid = (int)pArrayID;
  242. return TRUE;
  243. }
  244. }
  245. return FALSE;
  246. }
  247. BOOL CStockContainer::SetCurrentStock( const char * szCode )
  248. {
  249. CSPMutex::Scoped l(m_mutex);
  250. int nStockIndex = -1;
  251. CStockInfo info;
  252. if( GetStockInfo( szCode, &info, &nStockIndex ) )
  253. return SetCurrentStock( nStockIndex );
  254. else
  255. {
  256. m_nCurrentStock = -1;
  257. m_strCurrentStockCode = szCode;
  258. return FALSE;
  259. }
  260. }
  261. BOOL CStockContainer::SetCurrentStock( int nStockIndex )
  262. {
  263. CSPMutex::Scoped l(m_mutex);
  264. if( nStockIndex >= 0 && nStockIndex < GetSize() )
  265. {
  266. m_nCurrentStock = nStockIndex;
  267. return TRUE;
  268. }
  269. return FALSE;
  270. }
  271. BOOL CStockContainer::GetCurrentStock( CStockInfo * pInfo )
  272. {
  273. CSPMutex::Scoped l(m_mutex);
  274. SP_ASSERT( pInfo );
  275. if( m_nCurrentStock >= 0 && m_nCurrentStock < GetSize() )
  276. {
  277. CStockInfo & info = ElementAt(m_nCurrentStock);
  278. if( pInfo )
  279. * pInfo = info;
  280. return TRUE;
  281. }
  282. else if( m_strCurrentStockCode.GetLength() > 0 )
  283. {
  284. CStockInfo info;
  285. info.SetStockCode( CStock::marketUnknown, m_strCurrentStockCode );
  286. if( pInfo )
  287. *pInfo = info;
  288. return TRUE;
  289. }
  290. return FALSE;
  291. }
  292. BOOL CStockContainer::GetPrevStock( CStockInfo * pInfo )
  293. {
  294. CSPMutex::Scoped l(m_mutex);
  295. SP_ASSERT( pInfo );
  296. if( GetSize() == 0 )
  297. return FALSE;
  298. if( m_nCurrentStock < 0 || m_nCurrentStock >= GetSize() )
  299. m_nCurrentStock = -1;
  300. if( m_auidSort.GetSize() == GetSize() )
  301. {
  302. if( m_nCurrentStock == -1 )
  303. m_nCurrentStock = m_auidSort[m_auidSort.GetSize()-1];
  304. else
  305. {
  306. for( int i=0; i<m_auidSort.GetSize(); i++ )
  307. {
  308. if( m_nCurrentStock == (int)m_auidSort[i] )
  309. break;
  310. }
  311. if( i >= m_auidSort.GetSize() || i == 0 )
  312. {
  313. m_nCurrentStock = -1;
  314. return FALSE;
  315. }
  316. i --;
  317. m_nCurrentStock = m_auidSort[i];
  318. }
  319. }
  320. else
  321. {
  322. if( m_nCurrentStock < 0 )
  323. m_nCurrentStock = GetSize()-1;
  324. else
  325. m_nCurrentStock --;
  326. if( m_nCurrentStock < 0 )
  327. {
  328. m_nCurrentStock = -1;
  329. return FALSE;
  330. }
  331. }
  332. if( m_nCurrentStock >= 0 && m_nCurrentStock < GetSize() )
  333. {
  334. CStockInfo & info = ElementAt(m_nCurrentStock);
  335. if( pInfo )
  336. * pInfo = info;
  337. return TRUE;
  338. }
  339. else
  340. m_nCurrentStock = -1;
  341. return FALSE;
  342. }
  343. BOOL CStockContainer::GetNextStock( CStockInfo * pInfo )
  344. {
  345. CSPMutex::Scoped l(m_mutex);
  346. SP_ASSERT( pInfo );
  347. if( GetSize() == 0 )
  348. return FALSE;
  349. if( m_nCurrentStock < 0 || m_nCurrentStock >= GetSize() )
  350. m_nCurrentStock = -1;
  351. if( m_auidSort.GetSize() == GetSize() )
  352. {
  353. if( m_nCurrentStock == -1 )
  354. m_nCurrentStock = m_auidSort[0];
  355. else
  356. {
  357. for( int i=0; i<m_auidSort.GetSize(); i++ )
  358. {
  359. if( m_nCurrentStock == (int)m_auidSort[i] )
  360. break;
  361. }
  362. i ++;
  363. if( i >= m_auidSort.GetSize() )
  364. {
  365. m_nCurrentStock = -1;
  366. return FALSE;
  367. }
  368. m_nCurrentStock = m_auidSort[i];
  369. }
  370. }
  371. else
  372. {
  373. if( m_nCurrentStock < 0 )
  374. m_nCurrentStock = 0;
  375. else
  376. m_nCurrentStock ++;
  377. if( m_nCurrentStock >= GetSize() )
  378. {
  379. m_nCurrentStock = -1;
  380. return FALSE;
  381. }
  382. }
  383. if( m_nCurrentStock >= 0 && m_nCurrentStock < GetSize() )
  384. {
  385. CStockInfo & info = ElementAt(m_nCurrentStock);
  386. if( pInfo )
  387. * pInfo = info;
  388. return TRUE;
  389. }
  390. else
  391. m_nCurrentStock = -1;
  392. return FALSE;
  393. }
  394. CStockInfo & CStockContainer::GetStockInfoByID( int nID )
  395. {
  396. CSPMutex::Scoped l(m_mutex);
  397. if( ID_STOCKCNTN_AVERAGE == nID )
  398. return m_infoAverage;
  399. if( ID_STOCKCNTN_WEIGHTAVERAGE == nID )
  400. return m_infoWeightAverage;
  401. if( nID >= 0 && nID < GetSize() )
  402. return ElementAt( nID );
  403. SP_ASSERT( FALSE );
  404. return m_infoNull;
  405. }
  406. CStockInfo & CStockContainer::GetStockInfoByIDSort( int nID )
  407. {
  408. CSPMutex::Scoped l(m_mutex);
  409. if( ID_STOCKCNTN_AVERAGE == nID )
  410. return m_infoAverage;
  411. if( ID_STOCKCNTN_WEIGHTAVERAGE == nID )
  412. return m_infoWeightAverage;
  413. if( m_auidSort.GetSize() == GetSize() 
  414. && nID >= 0 && nID < GetSize() )
  415. {
  416. if( m_auidSort[nID] >= 0 && (int)m_auidSort[nID] < GetSize() )
  417. return ElementAt(m_auidSort[nID]);
  418. }
  419. else if( nID >= 0 && nID < GetSize() )
  420. return ElementAt( nID );
  421. SP_ASSERT( FALSE );
  422. return m_infoNull;
  423. }
  424. CStockInfo & CStockContainer::GetAverage( )
  425. {
  426. return m_infoAverage;
  427. }
  428. CStockInfo & CStockContainer::GetWeightAverage( )
  429. {
  430. return m_infoWeightAverage;
  431. }
  432. BOOL CStockContainer::Load( CStDatabase * pDB, PROGRESS_CALLBACK fnCallback, void *cookie, int nProgStart, int nProgEnd )
  433. {
  434. CSPMutex::Scoped l(m_mutex);
  435. SP_ASSERT( nProgStart <= nProgEnd );
  436. SP_ASSERT( pDB );
  437. if( nProgStart > nProgEnd || NULL == pDB )
  438. return FALSE;
  439. Clear( );
  440. int nLen = pDB->LoadCodetable( *this );
  441. SetMap( );
  442. pDB->LoadBasetable( *this );
  443. // pDB->LoadKDataCache( *this, fnCallback, cookie, nProgStart, nProgEnd );
  444. m_nType = typeAll;
  445. m_dwDate = -1;
  446. OnDataChanged( );
  447. return TRUE;
  448. }
  449. void CStockContainer::OnDataChanged( )
  450. {
  451. CSPMutex::Scoped l(m_mutex);
  452. DWORD dateLatest = m_dwDate;
  453. if( -1 == dateLatest )
  454. AfxGetStockContainer().GetLatestTechDate( &dateLatest );
  455. for( int i=0; i<GetSize(); i++ )
  456. {
  457. CStockInfo & info = ElementAt(i);
  458. info.StatBaseIndex( dateLatest );
  459. info.StatTechIndex( dateLatest );
  460. }
  461. SetAverage( );
  462. }
  463. BOOL CStockContainer::ReloadBase( CStDatabase * pDB )
  464. {
  465. CSPMutex::Scoped l(m_mutex);
  466. SP_ASSERT( pDB );
  467. if( GetSize() <= 0 || NULL == pDB )
  468. return Load( NULL, NULL );
  469. pDB->LoadBasetable( *this );
  470. OnDataChanged();
  471. return TRUE;
  472. }
  473. BOOL CStockContainer::SetMap( )
  474. {
  475. CSPMutex::Scoped l(m_mutex);
  476. m_map.RemoveAll( );
  477. if( GetSize() == 0 )
  478. return TRUE;
  479. m_map.InitHashTable( GetSize() * 2 + 10 );
  480. for( int i=0; i<GetSize(); i++ )
  481. {
  482. CStockInfo &info = ElementAt(i);
  483. m_map.SetAt( info.GetStockCode(), (void *)i );
  484. }
  485. return TRUE;
  486. }
  487. BOOL CStockContainer::SetAverage( PROGRESS_CALLBACK fnCallback, void *cookie, int nProgStart, int nProgEnd )
  488. {
  489. CSPMutex::Scoped l(m_mutex);
  490. SP_ASSERT( nProgStart <= nProgEnd );
  491. if( nProgStart > nProgEnd )
  492. return FALSE;
  493. CStockInfo & ave = m_infoAverage;
  494. CStockInfo & wave = m_infoWeightAverage;
  495. ave.Clear( );
  496. wave.Clear( );
  497. ave.SetStockCode( CStock::marketUnknown, slh_avrcode );
  498. ave.SetStockName( slh_avrname );
  499. wave.SetStockCode( CStock::marketUnknown, slh_wavrcode );
  500. wave.SetStockName( slh_wavrname );
  501. ave.m_reporttype = CStock::reportUnknown;
  502. wave.m_reporttype = CStock::reportUnknown;
  503. float fTemp = 0;
  504. float dc[100], wdc[100];
  505. int i = 0;
  506. for( i=0; i<sizeof(dc)/sizeof(dc[0]); i++ ) dc[i] = 0.;
  507. for( i=0; i<sizeof(wdc)/sizeof(wdc[0]); i++ ) wdc[i] = (float)0.0001;
  508. int nProgressSegment = GetSize() / 25;
  509. float dProgressRatio = ( 0 == GetSize() ? 1 : ((float)(nProgEnd - nProgStart))/GetSize() );
  510. for( int nCount=0; nCount<GetSize(); nCount++ )
  511. {
  512. if( fnCallback && !(nCount % nProgressSegment) )
  513. fnCallback( PROG_PROGRESS, (int)(nProgStart+nCount*dProgressRatio), NULL, cookie );
  514. CStockInfo & info = ElementAt(nCount);
  515. float factor = 1; // (float)CStock::GetReportFactor( info.m_reporttype );
  516. if( CStock::typeshIndex == info.GetType() || CStock::typeszIndex == info.GetType()
  517. || CStock::typeshBond == info.GetType() || CStock::typeszBond == info.GetType() )
  518. continue;
  519. ave.m_datebase = info.m_datebase;
  520. ave.m_datetech = info.m_datetech;
  521. wave.m_datebase = info.m_datebase;
  522. wave.m_datetech = info.m_datetech;
  523. float w = info.m_fShare_count_total;
  524. /* 平均值 *********************************************************************/
  525. // ★技术数据
  526. int m = 0, n = 0;
  527. if( info.m_fLast > 1e-4 )
  528. {
  529. ave.m_fLast = ( ave.m_fLast * dc[m] + info.m_fLast )/(dc[m]+1); dc[m] += 1;
  530. wave.m_fLast = ( wave.m_fLast * wdc[n] + info.m_fLast * w )/(wdc[n]+w); wdc[n] += w;
  531. }
  532. m++; n++;
  533. if( info.m_fOpen > 1e-4 )
  534. {
  535. ave.m_fOpen = ( ave.m_fOpen * dc[m] + info.m_fOpen )/(dc[m]+1); dc[m] += 1;
  536. wave.m_fOpen = ( wave.m_fOpen * wdc[n] + info.m_fOpen * w )/(wdc[n]+w); wdc[n] += w;
  537. }
  538. m++; n++;
  539. if( info.m_fClose > 1e-4 )
  540. {
  541. ave.m_fClose = ( ave.m_fClose * dc[m] + info.m_fClose )/(dc[m]+1); dc[m] += 1;
  542. wave.m_fClose = ( wave.m_fClose * wdc[n] + info.m_fClose * w )/(wdc[n]+w); wdc[n] += w;
  543. }
  544. m++; n++;
  545. if( info.m_fHigh > 1e-4 )
  546. {
  547. ave.m_fHigh = ( ave.m_fHigh * dc[m] + info.m_fHigh )/(dc[m]+1); dc[m] += 1;
  548. wave.m_fHigh = ( wave.m_fHigh * wdc[n] + info.m_fHigh * w )/(wdc[n]+w); wdc[n] += w;
  549. }
  550. m++; n++;
  551. if( info.m_fLow > 1e-4 )
  552. {
  553. ave.m_fLow = ( ave.m_fLow * dc[m] + info.m_fLow )/(dc[m]+1); dc[m] += 1;
  554. wave.m_fLow = ( wave.m_fLow * wdc[n] + info.m_fLow * w )/(wdc[n]+w); wdc[n] += w;
  555. }
  556. m++; n++;
  557. if( info.m_fVolume > 1e-4 )
  558. {
  559. ave.m_fVolume = ( ave.m_fVolume * dc[m] + info.m_fVolume )/(dc[m]+1); dc[m] += 1;
  560. }
  561. m++; n++;
  562. if( info.m_fAmount > 1e-4 )
  563. {
  564. ave.m_fAmount = ( ave.m_fAmount * dc[m] + info.m_fAmount )/(dc[m]+1); dc[m] += 1;
  565. }
  566. for( i=0; i<sizeof(ave.m_fBuyPrice)/sizeof(ave.m_fBuyPrice[0]); i++ )
  567. {
  568. m++; n++;
  569. if( info.m_fBuyPrice[i] > 1e-4 )
  570. {
  571. ave.m_fBuyPrice[i] = ( ave.m_fBuyPrice[i] * dc[m] + info.m_fBuyPrice[i] )/(dc[m]+1); dc[m] += 1;
  572. wave.m_fBuyPrice[i] = ( wave.m_fBuyPrice[i] * wdc[n] + info.m_fBuyPrice[i] )/(wdc[n]+1); wdc[n] += w;
  573. }
  574. }
  575. for( i=0; i<sizeof(ave.m_fBuyVolume)/sizeof(ave.m_fBuyVolume[0]); i++ )
  576. {
  577. m++; n++;
  578. if( info.m_fBuyVolume[i] > 1e-4 )
  579. {
  580. ave.m_fBuyVolume[i] = ( ave.m_fBuyVolume[i] * dc[m] + info.m_fBuyVolume[i] )/(dc[m]+1); dc[m] += 1;
  581. wave.m_fBuyVolume[i] = ( wave.m_fBuyVolume[i] * wdc[n] + info.m_fBuyVolume[i] )/(wdc[n]+1); wdc[n] += w;
  582. }
  583. }
  584. for( i=0; i<sizeof(ave.m_fSellPrice)/sizeof(ave.m_fSellPrice[0]); i++ )
  585. {
  586. m++; n++;
  587. if( info.m_fSellPrice[i] > 1e-4 )
  588. {
  589. ave.m_fSellPrice[i] = ( ave.m_fSellPrice[i] * dc[m] + info.m_fSellPrice[i] )/(dc[m]+1); dc[m] += 1;
  590. wave.m_fSellPrice[i] = ( wave.m_fSellPrice[i] * wdc[n] + info.m_fSellPrice[i] )/(wdc[n]+1); wdc[n] += w;
  591. }
  592. }
  593. for( i=0; i<sizeof(ave.m_fSellVolume)/sizeof(ave.m_fSellVolume[0]); i++ )
  594. {
  595. m++; n++;
  596. if( info.m_fSellVolume[i] > 1e-4 )
  597. {
  598. ave.m_fSellVolume[i] = ( ave.m_fSellVolume[i] * dc[m] + info.m_fSellVolume[i] )/(dc[m]+1); dc[m] += 1;
  599. wave.m_fSellVolume[i] = ( wave.m_fSellVolume[i] * wdc[n] + info.m_fSellVolume[i] )/(wdc[n]+1); wdc[n] += w;
  600. }
  601. }
  602. // ★偿债能力
  603. m++; n++;
  604. if( fabs(info.m_fRatio_liquidity) > 1e-4 )
  605. {
  606. ave.m_fRatio_liquidity = ( ave.m_fRatio_liquidity * dc[m] + info.m_fRatio_liquidity )/(dc[m]+1); dc[m] += 1;
  607. wave.m_fRatio_liquidity = ( wave.m_fRatio_liquidity * wdc[n] + info.m_fRatio_liquidity * w )/(wdc[n]+w); wdc[n] += w;
  608. }
  609. m++; n++;
  610. if( fabs(info.m_fRatio_quick) > 1e-4 )
  611. {
  612. ave.m_fRatio_quick = ( ave.m_fRatio_quick * dc[m] + info.m_fRatio_quick )/(dc[m]+1); dc[m] += 1;
  613. wave.m_fRatio_quick = ( wave.m_fRatio_quick * wdc[n] + info.m_fRatio_quick * w )/(wdc[n]+w); wdc[n] += w;
  614. }
  615. m++; n++;
  616. if( fabs(info.m_fVelocity_receivables) > 1e-4 )
  617. {
  618. ave.m_fVelocity_receivables = ( ave.m_fVelocity_receivables * dc[m] + info.m_fVelocity_receivables )/(dc[m]+1); dc[m] += 1;
  619. wave.m_fVelocity_receivables= ( wave.m_fVelocity_receivables * wdc[n] + info.m_fVelocity_receivables * w )/(wdc[n]+w); wdc[n] += w;
  620. }
  621. // ★经营能力
  622. m++; n++;
  623. if( fabs(info.m_fVelocity_merchandise) > 1e-4 )
  624. {
  625. ave.m_fVelocity_merchandise = ( ave.m_fVelocity_merchandise * dc[m] + info.m_fVelocity_merchandise )/(dc[m]+1); dc[m] += 1;
  626. wave.m_fVelocity_merchandise= ( wave.m_fVelocity_merchandise * wdc[n] + info.m_fVelocity_merchandise * w )/(wdc[n]+w); wdc[n] += w;
  627. }
  628. m++; n++;
  629. if( fabs(info.m_fMain_income) > 1e-4 )
  630. {
  631. ave.m_fMain_income = ( ave.m_fMain_income * dc[m] + factor*info.m_fMain_income )/(dc[m]+1); dc[m] += 1;
  632. }
  633. m++; n++;
  634. if( fabs(info.m_fCash_ps) > 1e-4 )
  635. {
  636. ave.m_fCash_ps = ( ave.m_fCash_ps * dc[m] + factor*info.m_fCash_ps )/(dc[m]+1); dc[m] += 1;
  637. wave.m_fCash_ps = ( wave.m_fCash_ps * wdc[n] + factor * info.m_fCash_ps * w )/(wdc[n]+w); wdc[n] += w;
  638. }
  639. // ★盈利能力
  640. m++; n++;
  641. if( fabs(info.m_fProfit_margin) > 1e-4 )
  642. {
  643. ave.m_fProfit_margin = ( ave.m_fProfit_margin * dc[m] + info.m_fProfit_margin )/(dc[m]+1); dc[m] += 1;
  644. wave.m_fProfit_margin = ( wave.m_fProfit_margin * wdc[n] + info.m_fProfit_margin * w )/(wdc[n]+w); wdc[n] += w;
  645. }
  646. m++; n++;
  647. if( fabs(info.m_fNetasset_yield) > 1e-4 )
  648. {
  649. ave.m_fNetasset_yield = ( ave.m_fNetasset_yield * dc[m] + factor*info.m_fNetasset_yield )/(dc[m]+1); dc[m] += 1;
  650. wave.m_fNetasset_yield = ( wave.m_fNetasset_yield * wdc[n] + factor * info.m_fNetasset_yield * w )/(wdc[n]+w); wdc[n] += w;
  651. }
  652. // ★资本结构
  653. m++; n++;
  654. if( info.m_fShare_count_total > 1e-4 )
  655. {
  656. ave.m_fShare_count_total = ( ave.m_fShare_count_total * dc[m] + info.m_fShare_count_total )/(dc[m]+1); dc[m] += 1;
  657. }
  658. m++; n++;
  659. if( info.m_fShare_count_a > 1e-4 )
  660. {
  661. ave.m_fShare_count_a = ( ave.m_fShare_count_a * dc[m] + info.m_fShare_count_a )/(dc[m]+1); dc[m] += 1;
  662. }
  663. m++; n++;
  664. if( info.m_fShare_count_b > 1e-4 )
  665. {
  666. ave.m_fShare_count_b = ( ave.m_fShare_count_b * dc[m] + info.m_fShare_count_b )/(dc[m]+1); dc[m] += 1;
  667. }
  668. m++; n++;
  669. if( info.m_fShare_count_h > 1e-4 )
  670. {
  671. ave.m_fShare_count_h = ( ave.m_fShare_count_h * dc[m] + info.m_fShare_count_h )/(dc[m]+1); dc[m] += 1;
  672. }
  673. m++; n++;
  674. if( info.m_fShare_count_national > 1e-4 )
  675. {
  676. ave.m_fShare_count_national = ( ave.m_fShare_count_national * dc[m] + info.m_fShare_count_national )/(dc[m]+1); dc[m] += 1;
  677. }
  678. m++; n++;
  679. if( info.m_fShare_count_corp > 1e-4 )
  680. {
  681. ave.m_fShare_count_corp = ( ave.m_fShare_count_corp * dc[m] + info.m_fShare_count_corp )/(dc[m]+1); dc[m] += 1;
  682. }
  683. m++; n++;
  684. if( fabs(info.m_fProfit_psud) > 1e-4 )
  685. {
  686. ave.m_fProfit_psud = ( ave.m_fProfit_psud * dc[m] + info.m_fProfit_psud )/(dc[m]+1); dc[m] += 1;
  687. wave.m_fProfit_psud = ( wave.m_fProfit_psud * wdc[n] + info.m_fProfit_psud * w )/(wdc[n]+w); wdc[n] += w;
  688. }
  689. m++; n++;
  690. if( fabs(info.m_fAsset) > 1e-4 )
  691. {
  692. ave.m_fAsset = ( ave.m_fAsset * dc[m] + info.m_fAsset )/(dc[m]+1); dc[m] += 1;
  693. }
  694. m++; n++;
  695. if( fabs(info.m_fRatio_holderright) > 1e-4 )
  696. {
  697. ave.m_fRatio_holderright = ( ave.m_fRatio_holderright * dc[m] + info.m_fRatio_holderright )/(dc[m]+1); dc[m] += 1;
  698. wave.m_fRatio_holderright = ( wave.m_fRatio_holderright * wdc[n] + info.m_fRatio_holderright * w )/(wdc[n]+w); wdc[n] += w;
  699. }
  700. m++; n++;
  701. if( fabs(info.m_fRatio_longdebt) > 1e-4 )
  702. {
  703. ave.m_fRatio_longdebt = ( ave.m_fRatio_longdebt * dc[m] + info.m_fRatio_longdebt )/(dc[m]+1); dc[m] += 1;
  704. wave.m_fRatio_longdebt = ( wave.m_fRatio_longdebt * wdc[n] + info.m_fRatio_longdebt * w )/(wdc[n]+w); wdc[n] += w;
  705. }
  706. m++; n++;
  707. if( fabs(info.m_fRatio_debt) > 1e-4 )
  708. {
  709. ave.m_fRatio_debt = ( ave.m_fRatio_debt * dc[m] + info.m_fRatio_debt )/(dc[m]+1); dc[m] += 1;
  710. wave.m_fRatio_debt = ( wave.m_fRatio_debt * wdc[n] + info.m_fRatio_debt * w )/(wdc[n]+w); wdc[n] += w;
  711. }
  712. // ★投资收益能力
  713. m++; n++;
  714. if( fabs(info.m_fNetasset_ps) > 1e-4 )
  715. {
  716. ave.m_fNetasset_ps = ( ave.m_fNetasset_ps * dc[m] + info.m_fNetasset_ps )/(dc[m]+1); dc[m] += 1;
  717. wave.m_fNetasset_ps = ( wave.m_fNetasset_ps * wdc[n] + info.m_fNetasset_ps * w )/(wdc[n]+w); wdc[n] += w;
  718. }
  719. m++; n++;
  720. if( fabs(info.m_fNetasset_ps_regulate) > 1e-4 )
  721. {
  722. ave.m_fNetasset_ps_regulate = ( ave.m_fNetasset_ps_regulate * dc[m] + info.m_fNetasset_ps_regulate )/(dc[m]+1); dc[m] += 1;
  723. wave.m_fNetasset_ps_regulate= ( wave.m_fNetasset_ps_regulate * wdc[n] + info.m_fNetasset_ps_regulate * w )/(wdc[n]+w); wdc[n] += w;
  724. }
  725. m++; n++;
  726. if( fabs(info.m_fEps) > 1e-4 )
  727. {
  728. ave.m_fEps = ( ave.m_fEps * dc[m] + factor*info.m_fEps )/(dc[m]+1); dc[m] += 1;
  729. wave.m_fEps = ( wave.m_fEps * wdc[n] + factor * info.m_fEps * w )/(wdc[n]+w); wdc[n] += w;
  730. }
  731. m++; n++;
  732. if( fabs(info.m_fEps_deduct) > 1e-4 )
  733. {
  734. ave.m_fEps_deduct = ( ave.m_fEps_deduct * dc[m] + factor*info.m_fEps_deduct )/(dc[m]+1); dc[m] += 1;
  735. wave.m_fEps_deduct = ( wave.m_fEps_deduct * wdc[n] + factor * info.m_fEps_deduct * w )/(wdc[n]+w); wdc[n] += w;
  736. }
  737. m++; n++;
  738. if( fabs(info.m_fNet_profit) > 1e-4 )
  739. {
  740. ave.m_fNet_profit = ( ave.m_fNet_profit * dc[m] + factor*info.m_fNet_profit )/(dc[m]+1); dc[m] += 1;
  741. }
  742. m++; n++;
  743. if( fabs(info.m_fMain_profit) > 1e-4 )
  744. {
  745. ave.m_fMain_profit = ( ave.m_fMain_profit * dc[m] + factor*info.m_fMain_profit )/(dc[m]+1); dc[m] += 1;
  746. }
  747. m++; n++;
  748. if( fabs(info.m_fTotal_profit) > 1e-4 )
  749. {
  750. ave.m_fTotal_profit = ( ave.m_fTotal_profit * dc[m] + factor*info.m_fTotal_profit )/(dc[m]+1);dc[m] += 1;
  751. }
  752. // ★增长率
  753. m++; n++;
  754. ave.m_fProfit_inc = ( ave.m_fProfit_inc * dc[m] + info.m_fProfit_inc )/(dc[m]+1); dc[m] += 1;
  755. wave.m_fProfit_inc = ( wave.m_fProfit_inc * wdc[n] + info.m_fProfit_inc * w )/(wdc[n]+w); wdc[n] += w;
  756. m++; n++;
  757. ave.m_fIncome_inc = ( ave.m_fIncome_inc * dc[m] + info.m_fIncome_inc )/(dc[m]+1); dc[m] += 1;
  758. wave.m_fIncome_inc = ( wave.m_fIncome_inc * wdc[n] + info.m_fIncome_inc * w )/(wdc[n]+w); wdc[n] += w;
  759. m++; n++;
  760. ave.m_fAsset_inc = ( ave.m_fAsset_inc * dc[m] + info.m_fAsset_inc )/(dc[m]+1); dc[m] += 1;
  761. wave.m_fAsset_inc = ( wave.m_fAsset_inc * wdc[n] + info.m_fAsset_inc * w )/(wdc[n]+w); wdc[n] += w;
  762. // ★技术数据统计值
  763. m++; n++;
  764. if( fabs(STKLIB_DATA_INVALID - info.m_fYield_average) > 1e-4 )
  765. {
  766. ave.m_fYield_average = ( ave.m_fYield_average * dc[m] + info.m_fYield_average )/(dc[m]+1); dc[m] += 1;
  767. wave.m_fYield_average = ( wave.m_fYield_average * wdc[n] + info.m_fYield_average * w )/(wdc[n]+w); wdc[n] += w;
  768. m++; n++;
  769. if( fabs(STKLIB_DATA_INVALID - info.m_fYield_stddev) > 1e-4 )
  770. {
  771. ave.m_fYield_stddev = ( ave.m_fYield_stddev * dc[m] + info.m_fYield_stddev )/(dc[m]+1); dc[m] += 1;
  772. wave.m_fYield_stddev= ( wave.m_fYield_stddev * wdc[n] + info.m_fYield_stddev * w )/(wdc[n]+w); wdc[n] += w;
  773. }
  774. }
  775. m++; n++;
  776. if( fabs(STKLIB_DATA_INVALID - info.m_fBeite) > 1e-4 )
  777. {
  778. ave.m_fBeite = ( ave.m_fBeite * dc[m] + info.m_fBeite )/(dc[m]+1); dc[m] += 1;
  779. wave.m_fBeite = ( wave.m_fBeite * wdc[n] + info.m_fBeite * w )/(wdc[n]+w); wdc[n] += w;
  780. }
  781. // K线数据
  782. m++; n++;
  783. if( 0 == nCount )
  784. {
  785. m_infoAverage.m_kdata = info.m_kdata;
  786. m_infoWeightAverage.m_kdata = info.m_kdata;
  787. }
  788. for( int k=info.m_kdata.GetSize()-1; k>=0; k-- )
  789. {
  790. KDATA & kdInfo = info.m_kdata.ElementAt(k);
  791. // 平均值
  792. int nIndex = k;
  793. if( nIndex >= m_infoAverage.m_kdata.GetSize() || m_infoAverage.m_kdata.ElementAt(nIndex).m_date != kdInfo.m_date )
  794. nIndex = m_infoAverage.m_kdata.GetIndexByDate(kdInfo.m_date);
  795. if( -1 == nIndex )
  796. {
  797. KDATA kdNew;
  798. memset( &kdNew, 0, sizeof(kdNew) );
  799. kdNew.m_date = kdInfo.m_date;
  800. nIndex = m_infoAverage.m_kdata.InsertKDataSort(kdNew);
  801. }
  802. if( -1 == nIndex )
  803. continue;
  804. KDATA & kdAve = m_infoAverage.m_kdata.ElementAt(nIndex);
  805. kdAve.m_fOpen = (kdAve.m_fOpen * dc[m] + kdInfo.m_fOpen)/(dc[m]+1);
  806. kdAve.m_fHigh = (kdAve.m_fHigh * dc[m] + kdInfo.m_fHigh)/(dc[m]+1);
  807. kdAve.m_fLow = (kdAve.m_fLow * dc[m] + kdInfo.m_fLow)/(dc[m]+1);
  808. kdAve.m_fClose = (kdAve.m_fClose * dc[m] + kdInfo.m_fClose)/(dc[m]+1);
  809. kdAve.m_fVolume = (kdAve.m_fVolume * dc[m] + kdInfo.m_fVolume)/(dc[m]+1);
  810. kdAve.m_fAmount = (kdAve.m_fAmount * dc[m] + kdInfo.m_fAmount)/(dc[m]+1);
  811. // 加权平均值
  812. nIndex = k;
  813. if( nIndex >= m_infoWeightAverage.m_kdata.GetSize() || m_infoWeightAverage.m_kdata.ElementAt(nIndex).m_date != kdInfo.m_date )
  814. nIndex = m_infoWeightAverage.m_kdata.GetIndexByDate(kdInfo.m_date);
  815. if( -1 == nIndex )
  816. {
  817. KDATA kdNew;
  818. memset( &kdNew, 0, sizeof(kdNew) );
  819. kdNew.m_date = kdInfo.m_date;
  820. nIndex = m_infoWeightAverage.m_kdata.InsertKDataSort(kdNew);
  821. }
  822. if( -1 == nIndex )
  823. continue;
  824. KDATA & kdWAve = m_infoWeightAverage.m_kdata.ElementAt(nIndex);
  825. kdWAve.m_fOpen = (kdWAve.m_fOpen * wdc[n] + kdInfo.m_fOpen * w)/(wdc[n]+w);
  826. kdWAve.m_fHigh = (kdWAve.m_fHigh * wdc[n] + kdInfo.m_fHigh * w)/(wdc[n]+w);
  827. kdWAve.m_fLow = (kdWAve.m_fLow * wdc[n] + kdInfo.m_fLow * w)/(wdc[n]+w);
  828. kdWAve.m_fClose = (kdWAve.m_fClose * wdc[n] + kdInfo.m_fClose * w)/(wdc[n]+w);
  829. kdWAve.m_fVolume = (kdWAve.m_fVolume * wdc[n] + kdInfo.m_fVolume * w)/(wdc[n]+w);
  830. kdWAve.m_fAmount = (kdWAve.m_fAmount * wdc[n] + kdInfo.m_fAmount * w)/(wdc[n]+w);
  831. }
  832. dc[m] += 1;
  833. wdc[n] += w;
  834. SP_ASSERT( m <= sizeof(dc)/sizeof(dc[0]) );
  835. SP_ASSERT( n <= sizeof(wdc)/sizeof(wdc[0]) );
  836. }
  837. if( fnCallback )
  838. fnCallback( PROG_PROGRESS, nProgEnd, NULL, cookie );
  839. return TRUE;
  840. }
  841. BOOL CStockContainer::Clear( )
  842. {
  843. CSPMutex::Scoped l(m_mutex);
  844. ClearVariantSaveValue( );
  845. // WARNING: Cannot clear this m_nCurrentStock = -1;
  846. // WARNING: Cannot clear this m_strCurrentStockCode.Empty();
  847. m_nType = typeNone;
  848. m_strDomain.Empty();
  849. m_dwDate = -1;
  850. RemoveAll();
  851. m_map.RemoveAll( );
  852. m_infoAverage.Clear( );
  853. m_infoWeightAverage.Clear( );
  854. m_auidSort.RemoveAll();
  855. return TRUE;
  856. }
  857. void CStockContainer::CopyData( CStockContainer & src )
  858. {
  859. CSPMutex::Scoped l(m_mutex);
  860. SetSize( src.GetSize() );
  861. for( int i=0; i<src.GetSize(); i++ )
  862. {
  863. CStockInfo & info = src.ElementAt(i);
  864. SetAt( i, info );
  865. }
  866. }
  867. int CStockContainer::SortFunction(const void *s1,const void *s2)
  868. {
  869. CStockInfo *pStock1 = (CStockInfo *)s1;
  870. CStockInfo *pStock2 = (CStockInfo *)s2;
  871. if( NULL == pStock2 )
  872. return 1;
  873. if( NULL == pStock1 )
  874. return -1;
  875. if( NULL == CStockContainer::m_pSortContainer )
  876. return 1;
  877. int nRet = AfxCompareVariantValue( CStockContainer::m_pSortContainer->m_nSortVariantID, *pStock1, *pStock2,
  878. CStockContainer::m_pSortContainer );
  879. if( CStockContainer::m_pSortContainer->m_bSortAscend )
  880. return nRet;
  881. if( nRet > 0 )
  882. return -1;
  883. else if( nRet < 0 )
  884. return 1;
  885. return 0;
  886. }
  887. int CStockContainer::StockInfoCompareFunc( const void *s1,const void *s2, CStockContainer * pContainer, int nSortVariantID )
  888. {
  889. CStockInfo *pStock1 = (CStockInfo *)s1;
  890. CStockInfo *pStock2 = (CStockInfo *)s2;
  891. if( NULL == pStock2 )
  892. return 1;
  893. if( NULL == pStock1 )
  894. return -1;
  895. return AfxCompareVariantValue( nSortVariantID, *pStock1, *pStock2, pContainer );
  896. }
  897. BOOL CStockContainer::Sort( int nSortVariantID, BOOL bAscend )
  898. {
  899. CSPMutex::Scoped l(m_mutex);
  900. m_auidSort.RemoveAll(); // if call this Sort(...), then not use m_auidSort
  901. CStockContainer::m_pSortContainer = this;
  902. m_nSortVariantID = nSortVariantID;
  903. m_bSortAscend = bAscend;
  904. if( NULL != GetData() )
  905. qsort( GetData(), GetSize(), sizeof(CStockInfo), SortFunction );
  906. return TRUE;
  907. }
  908. void CStockContainer::SetSortID( CSPDWordArray & auidsort )
  909. {
  910. CSPMutex::Scoped l(m_mutex);
  911. m_auidSort.RemoveAll();
  912. m_auidSort.Copy( auidsort );
  913. }
  914. BOOL CStockContainer::GetMultiSortIDArray( CSPDWordArray & adwSortID, LONG lStockType, UINT nSLH, BOOL bAsc, int nCount )
  915. {
  916. CSPMutex::Scoped l(m_mutex);
  917. SP_ASSERT( nCount > 0 && nSLH >= SLH_MIN && nSLH <= SLH_MAX );
  918. if( nCount <= 0 || nSLH < SLH_MIN || nSLH > SLH_MAX )
  919. return FALSE;
  920. adwSortID.RemoveAll();
  921. for( int n=0; n<nCount; n++ )
  922. {
  923. int nMinMaxIndex = -1;
  924. double dMinMaxValue = 0;
  925. BOOL bInited = FALSE;
  926. for( int i=0; i<GetSize(); i++ )
  927. {
  928. CStockInfo & info = ElementAt(i);
  929. // 股票类型
  930. if( info.GetType() != lStockType )
  931. continue;
  932. // 如果加过,则继续寻找下一个
  933. for( int k=0; k<adwSortID.GetSize(); k++ )
  934. {
  935. if( adwSortID[k] == (DWORD)i )
  936. break;
  937. }
  938. if( k != adwSortID.GetSize() )
  939. continue;
  940. // 判断大小
  941. double dValue = 0;
  942. if( AfxGetVariantValue( nSLH, info, &dValue, NULL ) )
  943. {
  944. if( !bInited )
  945. {
  946. nMinMaxIndex = i;
  947. dMinMaxValue = dValue;
  948. bInited = TRUE;
  949. }
  950. if( bAsc && dValue < dMinMaxValue )
  951. {
  952. nMinMaxIndex = i;
  953. dMinMaxValue = dValue;
  954. }
  955. if( !bAsc && dValue > dMinMaxValue )
  956. {
  957. nMinMaxIndex = (DWORD)i;
  958. dMinMaxValue = dValue;
  959. }
  960. }
  961. }
  962. if( -1 == nMinMaxIndex )
  963. break;
  964. adwSortID.Add( nMinMaxIndex );
  965. }
  966. return TRUE;
  967. }
  968. BOOL CStockContainer::GetVariantSaveValue( double *pValue, UINT nVariantID, CStockInfo &info, BOOL *pNoValue )
  969. {
  970. CSPMutex::Scoped l(m_mutex);
  971. void * pArrayID = NULL;
  972. if( !m_map.Lookup( info.GetStockCode(), pArrayID ) )
  973. return FALSE;
  974. int nIndex = (int)pArrayID;
  975. if( nIndex >= 0 && nIndex < m_aptrSaveValueArray.GetSize() )
  976. {
  977. CSPPtrArray * pArray = (CSPPtrArray *)m_aptrSaveValueArray.ElementAt( nIndex );
  978. if( pArray )
  979. {
  980. VARIANT_SAVEVALUE * pSave = NULL;
  981. for( int j=0; j<pArray->GetSize(); j++ )
  982. {
  983. pSave = (VARIANT_SAVEVALUE *) pArray->GetAt(j);
  984. if( pSave->nVariantID == nVariantID )
  985. {
  986. if( pValue ) *pValue = pSave->Value;
  987. if( pNoValue ) *pNoValue = pSave->bNoValue;
  988. return TRUE;
  989. }
  990. }
  991. }
  992. }
  993. return FALSE;
  994. }
  995. void CStockContainer::SetVariantSaveValue( double Value, UINT nVariantID, CStockInfo &info, BOOL bNoValue )
  996. {
  997. CSPMutex::Scoped l(m_mutex);
  998. void * pArrayID = NULL;
  999. if( !m_map.Lookup( info.GetStockCode(), pArrayID ) )
  1000. return;
  1001. // alloc for m_aptrSaveValueArray
  1002. if( m_aptrSaveValueArray.GetSize() == 0 )
  1003. {
  1004. m_aptrSaveValueArray.SetSize( GetSize() );
  1005. for( int i=0; i<m_aptrSaveValueArray.GetSize(); i++ )
  1006. m_aptrSaveValueArray.SetAt( i, NULL );
  1007. }
  1008. int nIndex = (int)pArrayID;
  1009. if( nIndex >= 0 && nIndex < m_aptrSaveValueArray.GetSize() )
  1010. {
  1011. CSPPtrArray * pArray = (CSPPtrArray *)m_aptrSaveValueArray.ElementAt( nIndex );
  1012. if( NULL == pArray )
  1013. {
  1014. pArray = new CSPPtrArray;
  1015. m_aptrSaveValueArray.SetAt( nIndex, pArray );
  1016. }
  1017. // 如果已经存在,覆盖之
  1018. for( int j=0; j<pArray->GetSize(); j++ )
  1019. {
  1020. VARIANT_SAVEVALUE * pSave = (VARIANT_SAVEVALUE *) pArray->GetAt(j);
  1021. if( pSave->nVariantID == nVariantID )
  1022. {
  1023. pSave->Value = Value;
  1024. pSave->bNoValue = bNoValue;
  1025. return;
  1026. }
  1027. }
  1028. // 加入新的
  1029. VARIANT_SAVEVALUE * pSaveValue = new VARIANT_SAVEVALUE;
  1030. pSaveValue->nVariantID = nVariantID;
  1031. pSaveValue->Value = Value;
  1032. pSaveValue->bNoValue = bNoValue;
  1033. pArray->Add( pSaveValue );
  1034. }
  1035. }
  1036. void CStockContainer::ClearVariantSaveValue( )
  1037. {
  1038. CSPMutex::Scoped l(m_mutex);
  1039. for( int i=0; i<m_aptrSaveValueArray.GetSize(); i++ )
  1040. {
  1041. CSPPtrArray * pArray = (CSPPtrArray *)m_aptrSaveValueArray.ElementAt( i );
  1042. if( pArray )
  1043. {
  1044. for( int j=0; j<pArray->GetSize(); j++ )
  1045. delete pArray->GetAt(j);
  1046. delete pArray;
  1047. }
  1048. }
  1049. m_aptrSaveValueArray.RemoveAll();
  1050. }
  1051. //////////////////////////////////////////////////////////////////////
  1052. // class CDomain
  1053. CDomain::CDomain( )
  1054. {
  1055. }
  1056. CDomain::CDomain( const CDomain &src )
  1057. {
  1058. *this = src;
  1059. }
  1060. CDomain::~CDomain( )
  1061. {
  1062. }
  1063. BOOL CDomain::AddStock( LPCTSTR lpszStockCode )
  1064. {
  1065. if( NULL == lpszStockCode || strlen(lpszStockCode) <= 0 )
  1066. return FALSE;
  1067. for( int k=0; k<GetSize(); k++ )
  1068. {
  1069. int nCmp = ElementAt(k).CompareNoCase(lpszStockCode);
  1070. if( 0 == nCmp )
  1071. return FALSE;
  1072. }
  1073. Add( lpszStockCode );
  1074. return TRUE;
  1075. }
  1076. BOOL CDomain::AddStockSort( LPCTSTR lpszStockCode )
  1077. {
  1078. if( NULL == lpszStockCode || strlen(lpszStockCode) <= 0 )
  1079. return FALSE;
  1080. for( int k=0; k<GetSize(); k++ )
  1081. {
  1082. int nCmp = ElementAt(k).CompareNoCase(lpszStockCode);
  1083. if( 0 == nCmp )
  1084. return FALSE;
  1085. if( nCmp > 0 )
  1086. {
  1087. InsertAt(k, lpszStockCode );
  1088. return TRUE;
  1089. }
  1090. }
  1091. Add( lpszStockCode );
  1092. return TRUE;
  1093. }
  1094. BOOL CDomain::RemoveStock( LPCTSTR lpszStockCode )
  1095. {
  1096. if( NULL == lpszStockCode || strlen(lpszStockCode) <= 0 )
  1097. return FALSE;
  1098. for( int k=0; k<GetSize(); k++ )
  1099. {
  1100. if( 0 == ElementAt(k).CompareNoCase(lpszStockCode) )
  1101. {
  1102. RemoveAt(k);
  1103. return TRUE;
  1104. }
  1105. }
  1106. return FALSE;
  1107. }
  1108. CDomain &CDomain::operator = ( const CDomain &src )
  1109. {
  1110. m_strName = src.m_strName;
  1111. Copy( src );
  1112. return *this;
  1113. }
  1114. struct fxj_block_t {
  1115. WORD wMarket;
  1116. char szCode[10];
  1117. };
  1118. int CDomain::AddFxjDomain( LPCTSTR lpszFile )
  1119. {
  1120. CSPFile file;
  1121. DWORD dwMagic;
  1122. if( !file.Open( lpszFile, CSPFile::modeRead )
  1123. || sizeof(dwMagic) != file.Read(&dwMagic,sizeof(dwMagic)) || dwMagic != 0xFF5100A5 )
  1124. return 0;
  1125. int nCount = 0;
  1126. struct fxj_block_t stock;
  1127. while( sizeof(stock) == file.Read(&stock,sizeof(stock)) )
  1128. {
  1129. if( 0 == stock.szCode[6] )
  1130. {
  1131. CSPString sCode = stock.szCode;
  1132. if( sCode.GetLength() == 4 )
  1133. sCode = "00" + sCode;
  1134. if( sCode.GetLength() == 6 )
  1135. AddStock( sCode );
  1136. }
  1137. }
  1138. return GetSize();
  1139. }
  1140. //////////////////////////////////////////////////////////////////////
  1141. // class CDomainContainer
  1142. CDomainContainer::CDomainContainer( )
  1143. {
  1144. }
  1145. CDomainContainer::CDomainContainer( CDomainContainer & src )
  1146. {
  1147. *this = src;
  1148. }
  1149. CDomainContainer::~CDomainContainer( )
  1150. {
  1151. RemoveAll( );
  1152. }
  1153. CDomainContainer & CDomainContainer::operator = ( CDomainContainer & src )
  1154. {
  1155. SetSize( src.GetSize() );
  1156. for( int i=0; i<src.GetSize(); i++ )
  1157. {
  1158. CDomain domain = src.ElementAt(i);
  1159. SetAt( i, domain );
  1160. }
  1161. return *this;
  1162. }
  1163. int CDomainContainer::AddDomain( LPCTSTR lpszDomainName )
  1164. {
  1165. if( NULL == lpszDomainName || strlen(lpszDomainName) <=0  )
  1166. return -1;
  1167. CDomain newdomain;
  1168. newdomain.m_strName = lpszDomainName;
  1169. return AddDomain( newdomain );
  1170. }
  1171. int CDomainContainer::AddDomain( CDomain & newdomain )
  1172. {
  1173. if( 0 == newdomain.m_strName.GetLength() )
  1174. return -1;
  1175. for( int i=0; i<GetSize(); i++ )
  1176. {
  1177. CDomain & domain = ElementAt(i);
  1178. if( 0 == newdomain.m_strName.CompareNoCase( domain.m_strName ) )
  1179. return -1;
  1180. }
  1181. return Add( newdomain );
  1182. }
  1183. int CDomainContainer::AddDomainReplace( CDomain & newdomain )
  1184. {
  1185. if( 0 == newdomain.m_strName.GetLength() )
  1186. return -1;
  1187. for( int i=0; i<GetSize(); i++ )
  1188. {
  1189. CDomain & domain = ElementAt(i);
  1190. if( 0 == newdomain.m_strName.CompareNoCase( domain.m_strName ) )
  1191. {
  1192. SetAt( i, newdomain );
  1193. return i;
  1194. }
  1195. }
  1196. return Add( newdomain );
  1197. }
  1198. int CDomainContainer::AddDomainReplace( CDomainContainer & newdomains )
  1199. {
  1200. int nCount = 0;
  1201. for( int i=0; i<newdomains.GetSize(); i++ )
  1202. {
  1203. if( AddDomainReplace( newdomains.ElementAt(i) ) >= 0 )
  1204. nCount ++;
  1205. }
  1206. return nCount;
  1207. }
  1208. BOOL CDomainContainer::RemoveDomain( LPCTSTR lpszDomainName )
  1209. {
  1210. if( NULL == lpszDomainName || strlen(lpszDomainName) <= 0 )
  1211. return FALSE;
  1212. for( int i=0; i<GetSize(); i++ )
  1213. {
  1214. CDomain & domain = ElementAt(i);
  1215. if( 0 == domain.m_strName.CompareNoCase( lpszDomainName ) )
  1216. {
  1217. RemoveAt( i );
  1218. return TRUE;
  1219. }
  1220. }
  1221. return FALSE;
  1222. }
  1223. BOOL CDomainContainer::AddDomainStock( LPCTSTR lpszDomainName, LPCTSTR lpszStockCode )
  1224. {
  1225. if( NULL == lpszDomainName || strlen(lpszDomainName) < 0
  1226. || NULL == lpszStockCode || strlen(lpszStockCode) < 0 )
  1227. return FALSE;
  1228. for( int i=0; i<GetSize(); i++ )
  1229. {
  1230. CDomain & domain = ElementAt(i);
  1231. if( 0 == domain.m_strName.CompareNoCase( lpszDomainName ) )
  1232. {
  1233. return domain.AddStock( lpszStockCode );
  1234. }
  1235. }
  1236. return FALSE;
  1237. }
  1238. BOOL CDomainContainer::AddDomainStock( LPCTSTR lpszDomainName, CSPStringArray & astr )
  1239. {
  1240. if( NULL == lpszDomainName || strlen(lpszDomainName) < 0 )
  1241. return FALSE;
  1242. for( int i=0; i<GetSize(); i++ )
  1243. {
  1244. CDomain & domain = ElementAt(i);
  1245. if( 0 == domain.m_strName.CompareNoCase( lpszDomainName ) )
  1246. {
  1247. for( int j=0; j<astr.GetSize(); j++ )
  1248. domain.AddStock( astr.ElementAt(j) );
  1249. return TRUE;
  1250. }
  1251. }
  1252. return FALSE;
  1253. }
  1254. BOOL CDomainContainer::RemoveDomainStock( LPCTSTR lpszDomainName, LPCTSTR lpszStockCode )
  1255. {
  1256. if( NULL == lpszDomainName || strlen(lpszDomainName) < 0
  1257. || NULL == lpszStockCode || strlen(lpszStockCode) < 0 )
  1258. return FALSE;
  1259. for( int i=0; i<GetSize(); i++ )
  1260. {
  1261. CDomain & domain = ElementAt(i);
  1262. if( 0 == domain.m_strName.CompareNoCase( lpszDomainName ) )
  1263. {
  1264. for( int k=0; k<domain.GetSize(); k++ )
  1265. {
  1266. if( 0 == domain.ElementAt(k).CompareNoCase(lpszStockCode) )
  1267. {
  1268. domain.RemoveAt(k);
  1269. return TRUE;
  1270. }
  1271. }
  1272. break;
  1273. }
  1274. }
  1275. return FALSE;
  1276. }
  1277. BOOL CDomainContainer::RemoveDomainStockAll( LPCTSTR lpszDomainName )
  1278. {
  1279. if( NULL == lpszDomainName || strlen(lpszDomainName) < 0 )
  1280. return FALSE;
  1281. for( int i=0; i<GetSize(); i++ )
  1282. {
  1283. CDomain & domain = ElementAt(i);
  1284. if( 0 == domain.m_strName.CompareNoCase( lpszDomainName ) )
  1285. {
  1286. domain.RemoveAll();
  1287. return TRUE;
  1288. }
  1289. }
  1290. return FALSE;
  1291. }
  1292. BOOL CDomainContainer::GetDomainStocks( LPCTSTR lpszDomain, CSPStringArray &astr )
  1293. {
  1294. if( NULL == lpszDomain || strlen(lpszDomain) < 0 )
  1295. return FALSE;
  1296. for( int i=0; i<GetSize(); i++ )
  1297. {
  1298. CDomain & domain = ElementAt(i);
  1299. if( 0 == domain.m_strName.CompareNoCase( lpszDomain ) )
  1300. {
  1301. astr.Copy( domain );
  1302. return TRUE;
  1303. }
  1304. }
  1305. return FALSE;
  1306. }
  1307. BOOL CDomainContainer::GetDomains( CSPStringArray & astr )
  1308. {
  1309. astr.SetSize( GetSize() );
  1310. for( int i=0; i<GetSize(); i++ )
  1311. {
  1312. CDomain & domain = ElementAt(i);
  1313. CSPString string = domain.m_strName;
  1314. astr.SetAt( i, string );
  1315. }
  1316. return TRUE;
  1317. }
  1318. BOOL CDomainContainer::GetAllDomainInfo( CStockContainer * pContainer, DWORD dwDate )
  1319. {
  1320. SP_ASSERT( pContainer );
  1321. if( NULL == pContainer )
  1322. return FALSE;
  1323. DWORD dwDateLatest = -1;
  1324. AfxGetStockContainer().GetLatestTechDate( &dwDateLatest );
  1325. for( int nDomain=0; nDomain<GetSize(); nDomain++ )
  1326. {
  1327. CDomain & domain = ElementAt(nDomain);
  1328. CStockContainer cntn;
  1329. if( cntn.RetrieveSpecify( domain ) )
  1330. {
  1331. if( -1 != dwDate && dwDateLatest != dwDate )
  1332. {
  1333. for( int i=0; i<cntn.GetSize(); i++ )
  1334. {
  1335. CStockInfo & info = cntn.ElementAt(i);
  1336. info.StatBaseIndex( dwDate );
  1337. info.StatTechIndex( dwDate );
  1338. }
  1339. }
  1340. // cntn.SetMap( );
  1341. cntn.SetAverage( );
  1342. CStockInfo info = cntn.GetAverage( );
  1343. info.SetStockName( domain.m_strName );
  1344. info.SetStockShortName( domain.m_strName );
  1345. pContainer->Add( info );
  1346. }
  1347. }
  1348. pContainer->SetMap();
  1349. pContainer->SetAverage();
  1350. return TRUE;
  1351. }
  1352. #define SF_MAX_DOMAINFILE_LENGTH 0x10000000
  1353. BOOL CDomainContainer::Load( LPCTSTR lpszFileName )
  1354. {
  1355. if( NULL == lpszFileName || strlen(lpszFileName) <= 0 )
  1356. return FALSE;
  1357. BOOL bOK = FALSE;
  1358. CSPFile file;
  1359. if( file.Open( lpszFileName, CSPFile::modeRead ) )
  1360. {
  1361. DWORD dwLen = file.GetLength();
  1362. if( 0 == dwLen || dwLen > SF_MAX_DOMAINFILE_LENGTH )
  1363. {
  1364. file.Close();
  1365. return FALSE;
  1366. }
  1367. SetSize( 0, min(dwLen / 300, 20) );
  1368. CDomain domain;
  1369. CSPString rString;
  1370. while( file.ReadString( rString ) )
  1371. {
  1372. int nIndex = rString.Find( "r" );
  1373. if( -1 == nIndex )
  1374. nIndex = rString.Find( "n" );
  1375. if( -1 != nIndex )
  1376. rString = rString.Left( nIndex );
  1377. rString.TrimLeft();
  1378. rString.TrimRight();
  1379. if( rString.GetLength() > 0 )
  1380. {
  1381. if( domain.m_strName.IsEmpty() ) // 新版块名称
  1382. domain.m_strName = rString;
  1383. else
  1384. domain.AddStock( rString );
  1385. }
  1386. else
  1387. { // 版块结束
  1388. if( !domain.m_strName.IsEmpty() )
  1389. AddDomain( domain );
  1390. domain.m_strName.Empty();
  1391. domain.RemoveAll();
  1392. }
  1393. }
  1394. if( !domain.m_strName.IsEmpty() )
  1395. Add( domain );
  1396. domain.m_strName.Empty();
  1397. domain.RemoveAll();
  1398. file.Close();
  1399. bOK = TRUE;
  1400. }
  1401. return bOK;
  1402. }
  1403. BOOL CDomainContainer::Store( LPCTSTR lpszFileName )
  1404. {
  1405. if( NULL == lpszFileName || strlen(lpszFileName) <= 0 )
  1406. return FALSE;
  1407. CSPFile file;
  1408. if( file.Open( lpszFileName, CSPFile::modeCreate | CSPFile::modeWrite ) )
  1409. {
  1410. for( int i=0; i<GetSize(); i++ )
  1411. {
  1412. CDomain & domain = ElementAt(i);
  1413. CSPString strDomain = domain.m_strName;
  1414. file.Write( strDomain.GetBuffer(strDomain.GetLength()+1), strDomain.GetLength() );
  1415. file.Write( STRING_CRLF, strlen(STRING_CRLF) );
  1416. for( int k=0; k<domain.GetSize(); k++ )
  1417. {
  1418. CSPString strStock = domain[k];
  1419. if( strStock.GetLength() > 0 )
  1420. {
  1421. file.Write( strStock.GetBuffer(strStock.GetLength()), strStock.GetLength() );
  1422. file.Write( STRING_CRLF, strlen(STRING_CRLF) );
  1423. }
  1424. }
  1425. file.Write( STRING_CRLF, strlen(STRING_CRLF) );
  1426. }
  1427. file.Close();
  1428. return TRUE;
  1429. }
  1430. return FALSE;
  1431. }