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

金融证券系统

开发平台:

Visual C++

  1. /*
  2. Cross Platform Core Code.
  3. Copyright(R) 2001-2002 Balang Software.
  4. All rights reserved.
  5. Using:
  6. class CKData;
  7. */
  8. #include "StdAfx.h"
  9. #include "../Include/Stock.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #endif
  17. /////////////////////////////////////////////////////////////////////////////
  18. CKData::CKData()
  19. {
  20. m_nKType = ktypeDay;
  21. m_nCurFormat= formatOriginal;
  22. m_nCurMaindataType = mdtypeClose;
  23. m_pDataOriginal = NULL;
  24. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  25. m_pData = NULL;
  26. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  27. }
  28. CKData::CKData( int ktype, int maindatatype )
  29. {
  30. m_nKType = ktype;
  31. m_nCurFormat= formatOriginal;
  32. m_nCurMaindataType = maindatatype;
  33. m_pDataOriginal = NULL;
  34. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  35. m_pData = NULL;
  36. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  37. }
  38. CKData::CKData( const CKData &src )
  39. {
  40. m_nKType = ktypeDay;
  41. m_nCurFormat= formatOriginal;
  42. m_nCurMaindataType = mdtypeClose;
  43. m_pDataOriginal = NULL;
  44. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  45. m_pData = NULL;
  46. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  47. *this = src;
  48. }
  49. CKData & CKData::operator = ( const CKData &src )
  50. {
  51. Clear();
  52. m_nKType = src.m_nKType;
  53. m_nCurFormat = src.m_nCurFormat;
  54. m_nCurMaindataType = src.m_nCurMaindataType;
  55. m_drdata = src.m_drdata;
  56. CopyData( src );
  57. return *this;
  58. }
  59. BOOL CKData::IsDayOrMin( int nKType )
  60. {
  61. return (nKType == CKData::ktypeDay || nKType == CKData::ktypeWeek || nKType == CKData::ktypeMonth);
  62. }
  63. CKData::~CKData()
  64. {
  65. Clear();
  66. }
  67. int CKData::GetSize() const
  68. { return m_nSize; }
  69. int CKData::Add(KDATA newElement)
  70. { int nIndex = m_nSize;
  71. SetAtGrow(nIndex, newElement);
  72. return nIndex; }
  73. void CKData::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  74. {
  75. SP_ASSERT(nNewSize >= 0);
  76. if (nGrowBy != -1)
  77. m_nGrowBy = nGrowBy;  // set new size
  78. if (nNewSize == 0)
  79. {
  80. // shrink to nothing
  81. delete [] (BYTE*)m_pData;
  82. m_pData = NULL;
  83. m_nSize = m_nMaxSize = 0;
  84. }
  85. else if (m_pData == NULL)
  86. {
  87. // create one with exact size
  88. #ifdef SIZE_T_MAX
  89. SP_ASSERT((long)nNewSize * sizeof(KDATA) <= SIZE_T_MAX);  // no overflow
  90. #endif
  91. m_pData = (KDATA*) new BYTE[nNewSize * sizeof(KDATA)];
  92. memset(m_pData, 0, nNewSize * sizeof(KDATA));  // zero fill
  93. m_nSize = m_nMaxSize = nNewSize;
  94. }
  95. else if (nNewSize <= m_nMaxSize)
  96. {
  97. // it fits
  98. if (nNewSize > m_nSize)
  99. {
  100. // initialize the new elements
  101. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(KDATA));
  102. }
  103. m_nSize = nNewSize;
  104. }
  105. else
  106. {
  107. // Otherwise grow array
  108. int nNewMax;
  109. if (nNewSize < m_nMaxSize + m_nGrowBy)
  110. nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  111. else
  112. nNewMax = nNewSize;  // no slush
  113. #ifdef SIZE_T_MAX
  114. SP_ASSERT((long)nNewMax * sizeof(KDATA) <= SIZE_T_MAX);  // no overflow
  115. #endif
  116. KDATA* pNewData = (KDATA*) new BYTE[nNewMax * sizeof(KDATA)];
  117. // copy new data from old
  118. memcpy(pNewData, m_pData, m_nSize * sizeof(KDATA));
  119. // construct remaining elements
  120. SP_ASSERT(nNewSize > m_nSize);
  121. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(KDATA));
  122. // get rid of old stuff (note: no destructors called)
  123. delete [] (BYTE*)m_pData;
  124. m_pData = pNewData;
  125. m_nSize = nNewSize;
  126. m_nMaxSize = nNewMax;
  127. }
  128. }
  129. void CKData::FreeExtra()
  130. {
  131. if (m_nSize != m_nMaxSize)
  132. {
  133. // shrink to desired size
  134. #ifdef SIZE_T_MAX
  135. SP_ASSERT((long)m_nSize * sizeof(KDATA) <= SIZE_T_MAX);  // no overflow
  136. #endif
  137. KDATA* pNewData = NULL;
  138. if (m_nSize != 0)
  139. {
  140. pNewData = (KDATA*) new BYTE[m_nSize * sizeof(KDATA)];
  141. // copy new data from old
  142. memcpy(pNewData, m_pData, m_nSize * sizeof(KDATA));
  143. }
  144. // get rid of old stuff (note: no destructors called)
  145. delete [] (BYTE*)m_pData;
  146. m_pData = pNewData;
  147. m_nMaxSize = m_nSize;
  148. }
  149. }
  150. BOOL CKData::LatestDate( int &nYear, int &nMonth, int &nDay, int &nHour, int &nMinute ) const
  151. {
  152. nYear = nMonth = nDay = nHour = nMinute = 0;
  153. if( GetSize() > 0 )
  154. return DateAt( GetSize()-1, nYear, nMonth, nDay, nHour, nMinute );
  155. return FALSE;
  156. }
  157. DWORD CKData::GetDate( int nIndex )
  158. {
  159. if( nIndex >=0 && nIndex < GetSize() )
  160. return ElementAt(nIndex).m_date;
  161. if( GetSize() > 0 )
  162. return ElementAt(GetSize()-1).m_date;
  163. return 0;
  164. }
  165. DWORD CKData::GetDateDay( int nIndex )
  166. {
  167. DWORD date = GetDate(nIndex);
  168. if( CKData::ktypeMin5 == m_nKType || CKData::ktypeMin15 == m_nKType
  169. || CKData::ktypeMin30 == m_nKType || CKData::ktypeMin60 == m_nKType )
  170. {
  171. CSPTime sptime;
  172. if( sptime.FromStockTimeMin( date ) )
  173. return sptime.ToStockTimeDay();
  174. else
  175. return 0;
  176. }
  177. return date;
  178. }
  179. int CKData::GetIndexByDate( DWORD date )
  180. {
  181. if( GetSize() > 0 && ElementAt(GetSize()-1).m_date < date )
  182. return -1;
  183. if( GetSize() > 0 && ElementAt(0).m_date > date )
  184. return -1;
  185. for( int k=GetSize()-1; k >= 0 ; k-- )
  186. {
  187. if( ElementAt(k).m_date == date )
  188. return k;
  189. else if( ElementAt(k).m_date < date )
  190. break;
  191. }
  192. return -1;
  193. }
  194. int CKData::GetAboutIndexByDate( DWORD date )
  195. {
  196. for( int k=GetSize()-1; k >= 0 ; k-- )
  197. {
  198. if( ElementAt(k).m_date <= date )
  199. return k;
  200. }
  201. return -1;
  202. }
  203. /////////////////////////////////////////////////////////////////////////////
  204. void CKData::SetAtGrow(int nIndex, KDATA newElement)
  205. {
  206. SP_ASSERT(nIndex >= 0);
  207. if (nIndex >= m_nSize)
  208. SetSize(nIndex+1);
  209. m_pData[nIndex] = newElement;
  210. }
  211. void CKData::InsertAt(int nIndex, KDATA newElement, int nCount /*=1*/)
  212. {
  213. SP_ASSERT(nIndex >= 0);    // will expand to meet need
  214. SP_ASSERT(nCount > 0);     // zero or negative size not allowed
  215. if (nIndex >= m_nSize)
  216. {
  217. // adding after the end of the array
  218. SetSize(nIndex + nCount);  // grow so nIndex is valid
  219. }
  220. else
  221. {
  222. // inserting in the middle of the array
  223. int nOldSize = m_nSize;
  224. SetSize(m_nSize + nCount);  // grow it to new size
  225. // shift old data up to fill gap
  226. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  227. (nOldSize-nIndex) * sizeof(KDATA));
  228. // re-init slots we copied from
  229. memset(&m_pData[nIndex], 0, nCount * sizeof(KDATA));
  230. }
  231. // insert new value in the gap
  232. SP_ASSERT(nIndex + nCount <= m_nSize);
  233. while (nCount--)
  234. m_pData[nIndex++] = newElement;
  235. }
  236. int CKData::InsertKDataSort( KDATA newElement )
  237. {
  238. for( int i=0; i<GetSize(); i++ )
  239. {
  240. KDATA & temp = ElementAt(i);
  241. if( temp.m_date == newElement.m_date )
  242. {
  243. SetAt(i,newElement);
  244. return i;
  245. }
  246. if( temp.m_date > newElement.m_date )
  247. {
  248. InsertAt(i,newElement);
  249. return i;
  250. }
  251. }
  252. return Add( newElement );
  253. }
  254. BOOL CKData::IsNewValue( int nIndex, BOOL bTopOrBottom, int nDays )
  255. {
  256. if( nIndex < nDays-1 || nIndex < 0 || nIndex >= GetSize() || nDays < 3 )
  257. return FALSE;
  258. BOOL bFirst = TRUE;
  259. float fLast = 0;
  260. int nLast = 0;
  261. float fNow = MaindataAt( nIndex );
  262. for( int k=nIndex-1; k>=0 && k>nIndex-nDays; k-- )
  263. {
  264. float fCur = MaindataAt(k);
  265. if( bFirst )
  266. {
  267. fLast = fCur;
  268. nLast = k;
  269. bFirst = FALSE;
  270. }
  271. if( bTopOrBottom )
  272. {
  273. if( fCur > fNow )
  274. return FALSE;
  275. if( fCur > fLast )
  276. {
  277. fLast = fCur;
  278. nLast = k;
  279. }
  280. }
  281. else
  282. {
  283. if( fCur < fNow )
  284. return FALSE;
  285. if( fCur < fLast )
  286. {
  287. fLast = fCur;
  288. nLast = k;
  289. }
  290. }
  291. }
  292. if( bFirst )
  293. return FALSE;
  294. if( nLast >= nIndex-30 && nLast <= nIndex-5 )
  295. return TRUE;
  296. return FALSE;
  297. }
  298. BOOL CKData::GetMinMaxInfo( int nStart, int nEnd, float * pfMin, float *pfMax )
  299. {
  300. if( nStart < 0 || nEnd < 0 || nStart > nEnd || nEnd >= GetSize() )
  301. return FALSE;
  302. float fMin = 0, fMax = 0;
  303. BOOL bFirst = TRUE;
  304. for( int k=nStart; k<=nEnd; k++ )
  305. {
  306. KDATA & kd = ElementAt(k);
  307. if( bFirst )
  308. {
  309. fMin = kd.m_fLow;
  310. fMax = kd.m_fHigh;
  311. bFirst = FALSE;
  312. }
  313. if( kd.m_fLow < fMin )
  314. fMin = kd.m_fLow;
  315. if( kd.m_fHigh > fMax )
  316. fMax = kd.m_fHigh;
  317. }
  318. if( pfMin ) *pfMin = fMin;
  319. if( pfMax ) *pfMax = fMax;
  320. return !bFirst;
  321. }
  322. void CKData::RemoveAt(int nIndex, int nCount /* = 1 */)
  323. {
  324. SP_ASSERT(nIndex >= 0);
  325. SP_ASSERT(nCount >= 0);
  326. SP_ASSERT(nIndex + nCount <= m_nSize);
  327. // just remove a range
  328. int nMoveCount = m_nSize - (nIndex + nCount);
  329. if (nMoveCount)
  330. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  331. nMoveCount * sizeof(KDATA));
  332. m_nSize -= nCount;
  333. }
  334. void CKData::InsertAt(int nStartIndex, CKData* pNewArray)
  335. {
  336. SP_ASSERT(pNewArray != NULL);
  337. SP_ASSERT(nStartIndex >= 0);
  338. if (pNewArray->GetSize() > 0)
  339. {
  340. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  341. for (int i = 0; i < pNewArray->GetSize(); i++)
  342. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  343. }
  344. }
  345. /////////////////////////////////////////////////////////////////////////////
  346. // Extra Operations
  347. void CKData::SetKType( int ktype ) { m_nKType = ktype; }
  348. void CKData::AutoSetKType( )
  349. {
  350. if( GetSize() >= 4 )
  351. {
  352. long elapse1 = ElementAt(1).m_time - ElementAt(0).m_time;
  353. long elapse2 = ElementAt(2).m_time - ElementAt(1).m_time;
  354. long elapse3 = ElementAt(3).m_time - ElementAt(2).m_time;
  355. long elapse = min(elapse1,elapse2);
  356. elapse = min(elapse,elapse3);
  357. if( elapse < 600 )
  358. m_nKType = ktypeMin5;
  359. else if( elapse < 1200 )
  360. m_nKType = ktypeMin15;
  361. else if( elapse < 2400 )
  362. m_nKType = ktypeMin30;
  363. else if( elapse < 7200 )
  364. m_nKType = ktypeMin60;
  365. else if( elapse < 172800 )
  366. m_nKType = ktypeDay;
  367. else if( elapse < 864000 )
  368. m_nKType = ktypeWeek;
  369. else if( elapse < 4320000 )
  370. m_nKType = ktypeWeek;
  371. }
  372. }
  373. int CKData::GetKType( ) { return m_nKType; }
  374. int CKData::GetCurFormat( ) { return m_nCurFormat; }
  375. void CKData::SetMaindataType( int type ) { m_nCurMaindataType = type; }
  376. int CKData::GetMaindataType( ) { return m_nCurMaindataType; }
  377. void CKData::SetDRData( CDRData &drdata ) { m_drdata = drdata; }
  378. CDRData &CKData::GetDRData( ) { return m_drdata; }
  379. void CKData::ChangeCurFormat( int format, DWORD dateAutoDRBegin, double dAutoDRLimit )
  380. {
  381. SP_ASSERT( GetKType() != ktypeMonth && GetKType() != ktypeWeek );
  382. if( m_nCurFormat == format )
  383. return;
  384. switch( format )
  385. {
  386. case formatOriginal:
  387. LoadDataOriginal( );
  388. m_nCurFormat = format;
  389. break;
  390. case formatXDRup:
  391. StoreDataOriginal( );
  392. ConvertXDR( TRUE, dateAutoDRBegin, dAutoDRLimit );
  393. m_nCurFormat = format;
  394. break;
  395. case formatXDRdown:
  396. StoreDataOriginal( );
  397. ConvertXDR( FALSE, dateAutoDRBegin, dAutoDRLimit );
  398. m_nCurFormat = format;
  399. break;
  400. default:
  401. SP_ASSERT( FALSE );
  402. }
  403. }
  404. void CKData::Clear( )
  405. {
  406. if( m_pDataOriginal )
  407. {
  408. delete [] (BYTE*)m_pDataOriginal;
  409. m_pDataOriginal = NULL;
  410. }
  411. if( m_pData )
  412. {
  413. delete [] (BYTE*)m_pData;
  414. m_pData = NULL;
  415. }
  416. m_nKType = ktypeDay;
  417. m_nCurFormat= formatOriginal;
  418. m_nCurMaindataType = mdtypeClose;
  419. m_pDataOriginal = NULL;
  420. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  421. m_pData = NULL;
  422. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  423. }
  424. int CKData::CompareLatestDate( CKData &kd )
  425. {
  426. // compare this kdata with kd's latest time
  427. int nYearThis, nMonthThis, nDayThis, nHourThis, nMinuteThis;
  428. int nYear, nMonth, nDay, nHour, nMinute;
  429. LatestDate( nYearThis, nMonthThis, nDayThis, nHourThis, nMinuteThis );
  430. kd.LatestDate( nYear, nMonth, nDay, nHour, nMinute );
  431. if( nYearThis > nYear || nMonthThis > nMonth || nDayThis > nDay
  432. || nHourThis > nHour || nMinuteThis > nMinute )
  433. return 1;
  434. if( nYearThis < nYear || nMonthThis < nMonth || nDayThis < nDay
  435. || nHourThis < nHour || nMinuteThis < nMinute )
  436. return -1;
  437. return 0;
  438. }
  439. int CKData::Min5ToMin15( CKData &kdm5, CKData &kdm15 )
  440. {
  441. SP_ASSERT( ktypeMin5 == kdm5.GetKType() );
  442. SP_ASSERT( ktypeMin15 == kdm15.GetKType() );
  443. return ConvertKData( kdm5, kdm15, 3 );
  444. }
  445. int CKData::Min5ToMin30( CKData &kdm5, CKData &kdm30 )
  446. {
  447. SP_ASSERT( ktypeMin5 == kdm5.GetKType() );
  448. SP_ASSERT( ktypeMin30 == kdm30.GetKType() );
  449. return ConvertKData( kdm5, kdm30, 6 );
  450. }
  451. int CKData::Min5ToMin60( CKData &kdm5, CKData &kdm60 )
  452. {
  453. SP_ASSERT( ktypeMin5 == kdm5.GetKType() );
  454. SP_ASSERT( ktypeMin60 == kdm60.GetKType() );
  455. return ConvertKData( kdm5, kdm60, 12 );
  456. }
  457. int CKData::DayToMonth( CKData &kdday, CKData &kdmonth )
  458. {
  459. // convert day k line to month k line
  460. SP_ASSERT( ktypeDay == kdday.GetKType() );
  461. SP_ASSERT( ktypeMonth == kdmonth.GetKType() );
  462. kdmonth.SetSize( 0, kdday.GetSize() / 20 + 5 );
  463. int nStart = kdday.GetSize() % 3;
  464. int nCount = 0;
  465. KDATA dataDest;
  466. memset( &dataDest, 0, sizeof(dataDest) );
  467. int nYearCur = 0, nMonthCur = 0 ;
  468. for( int pos=nStart; pos<kdday.GetSize(); pos++ )
  469. {
  470. KDATA & dataSrc = kdday.ElementAt( pos );
  471. CSPTime tm;
  472. if( !tm.FromStockTimeDay(dataSrc.m_date) )
  473. continue;
  474. int nYear = tm.GetYear();
  475. int nMonth = tm.GetMonth();
  476. if( nYear != nYearCur || nMonth != nMonthCur ) // a new month
  477. {
  478. if( 0 != pos )
  479. kdmonth.Add( dataDest ); // add a month
  480. memcpy( &dataDest, &dataSrc, sizeof(dataDest) ); // begin a new month
  481. nYearCur = nYear;
  482. nMonthCur = nMonth;
  483. }
  484. else
  485. {
  486. dataDest.m_fAmount += dataSrc.m_fAmount;
  487. if( dataDest.m_fHigh < dataSrc.m_fHigh ) dataDest.m_fHigh = dataSrc.m_fHigh;
  488. if( dataDest.m_fLow > dataSrc.m_fLow ) dataDest.m_fLow = dataSrc.m_fLow;
  489. dataDest.m_fVolume += dataSrc.m_fVolume;
  490. dataDest.m_fClose = dataSrc.m_fClose;
  491. }
  492. if( pos == kdday.GetSize()-1 ) // the latest one
  493. kdmonth.Add( dataDest );
  494. }
  495. return kdmonth.GetSize();
  496. }
  497. int CKData::DayToWeek( CKData &kdday, CKData &kdweek )
  498. {
  499. // convert day k line to week k line
  500. SP_ASSERT( ktypeDay == kdday.GetKType() );
  501. SP_ASSERT( ktypeWeek == kdweek.GetKType() );
  502. kdweek.SetSize( 0, kdday.GetSize() / 5 + 5 );
  503. int nStart = kdday.GetSize() % 3;
  504. int nCount = 0;
  505. KDATA dataDest;
  506. memset( &dataDest, 0, sizeof(dataDest) );
  507. for( int pos=nStart; pos<kdday.GetSize(); pos++ )
  508. {
  509. KDATA & dataSrc = kdday.ElementAt( pos );
  510. CSPTime tm;
  511. if( !tm.FromStockTimeDay(dataSrc.m_date) )
  512. continue;
  513. if( tm.GetDayOfWeek() == 2 ) // a new week
  514. {
  515. if( 0 != pos )
  516. kdweek.Add( dataDest ); // add a week
  517. memcpy( &dataDest, &dataSrc, sizeof(dataDest) ); // begin a new week
  518. }
  519. else
  520. {
  521. dataDest.m_fAmount += dataSrc.m_fAmount;
  522. if( dataDest.m_fHigh < dataSrc.m_fHigh ) dataDest.m_fHigh = dataSrc.m_fHigh;
  523. if( dataDest.m_fLow > dataSrc.m_fLow ) dataDest.m_fLow = dataSrc.m_fLow;
  524. dataDest.m_fVolume += dataSrc.m_fVolume;
  525. dataDest.m_fClose = dataSrc.m_fClose;
  526. }
  527. if( pos == kdday.GetSize()-1 ) // the latest one
  528. kdweek.Add( dataDest );
  529. }
  530. return kdweek.GetSize();
  531. }
  532. DWORD CKData::ToDayDate( DWORD date )
  533. {
  534. switch( GetKType() )
  535. {
  536. case ktypeMin60:
  537. case ktypeMin30:
  538. case ktypeMin15:
  539. case ktypeMin5:
  540. return (date / 10000 + 1990 * 10000);
  541. default:
  542. return date;
  543. }
  544. }
  545. int CKData::MergeKData( CKData * pother )
  546. {
  547. if( !pother || pother->GetSize() == 0 )
  548. return 0;
  549. if( GetKType() != pother->GetKType() )
  550. return 0;
  551. if( GetSize() == 0 )
  552. {
  553. CopyData( *pother );
  554. return GetSize();
  555. }
  556. int nCount = 0;
  557. SetSize( GetSize(), pother->GetSize()+1 );
  558. for( int i=0; i<pother->GetSize(); i++ )
  559. {
  560. KDATA kdnew = pother->ElementAt(i);
  561. if( kdnew.m_fClose < 1e-4 || kdnew.m_fOpen < 1e-4 || kdnew.m_fHigh < 1e-4 || kdnew.m_fLow < 1e-4 )
  562. continue;
  563. for( int j=0; j<GetSize(); j++ )
  564. {
  565. if( kdnew.m_date == ElementAt(j).m_date )
  566. {
  567. SetAt(j,kdnew);
  568. break;
  569. }
  570. if( kdnew.m_date < ElementAt(j).m_date )
  571. {
  572. InsertAt(j,kdnew);
  573. break;
  574. }
  575. }
  576. if( GetSize() == j )
  577. Add( kdnew );
  578. nCount ++;
  579. }
  580. return nCount;
  581. /* The Old Version
  582. if( !pother || pother->GetSize() == 0 )
  583. return GetSize();
  584. if( GetKType() != pother->GetKType() )
  585. return GetSize();
  586. if( GetSize() == 0 )
  587. {
  588. CopyData( *pother );
  589. return GetSize();
  590. }
  591. int nLen = GetSize();
  592. int nLenOther = pother->GetSize();
  593. SP_ASSERT( 0 != nLen && 0 != nLenOther );
  594. if( ElementAt(nLen-1).m_date < pother->ElementAt(0).m_date )
  595. CopyData( *pother );
  596. // else if( ElementAt(0).m_date > pother->ElementAt(nLenOther-1).m_date )
  597. // ;
  598. // else if( ElementAt(0).m_date <= pother->ElementAt(0).m_date
  599. // && ElementAt(nLen-1).m_date >= pother->ElementAt(nLenOther-1).m_date )
  600. // ;
  601. else if( ElementAt(0).m_date > pother->ElementAt(0).m_date
  602. && ElementAt(nLen-1).m_date < pother->ElementAt(nLenOther-1).m_date )
  603. CopyData( *pother );
  604. else if( ElementAt(0).m_date <= pother->ElementAt(0).m_date
  605. && ElementAt(nLen-1).m_date < pother->ElementAt(nLenOther-1).m_date )
  606. {
  607. // append from pother
  608. DWORD date = ElementAt(nLen-1).m_date;
  609. SetSize( GetSize(), pother->GetSize() );
  610. for( int i=0; i<pother->GetSize(); i++ )
  611. {
  612. KDATA & kd = pother->ElementAt(i);
  613. if( kd.m_date > m_data )
  614. Add( kd );
  615. }
  616. }
  617. else if( ElementAt(0).m_date >= pother->ElementAt(0).m_date
  618. && ElementAt(nLen-1).m_date > pother->ElementAt(nLenOther-1).m_date )
  619. {
  620. // insert from pother
  621. CKData temp = (*pother);
  622. DWORD date = pother->ElementAt(nLenOther-1).m_date;
  623. temp.SetSize( temp.GetSize(), GetSize()+5 );
  624. for( int i=0; i<GetSize(); i++ )
  625. {
  626. KDATA & kd = ElementAt(i);
  627. if( kd.m_date > date )
  628. temp.Add( kd );
  629. }
  630. CopyData( temp );
  631. }
  632. return GetSize();
  633. */
  634. }
  635. int CKData::FullFillKData( CKData & kdataMain, BOOL bFillToEnd )
  636. {
  637. SP_ASSERT( GetKType() == kdataMain.GetKType() );
  638. if( GetKType() != kdataMain.GetKType() )
  639. return 0;
  640. if( GetSize() == 0 || kdataMain.GetSize() == 0 )
  641. return 0;
  642. DWORD dateBegin = ElementAt(0).m_date;
  643. DWORD dateMainEnd5 = (kdataMain.GetSize() >= 5 ? kdataMain.ElementAt(kdataMain.GetSize()-5).m_date : 0);
  644. DWORD dateEnd5 = (GetSize() >= 5 ? ElementAt(GetSize()-5).m_date : 0);
  645. int iMain = 0, iSelf = 0;
  646. for( iMain=0; iMain<kdataMain.GetSize(); iMain ++ )
  647. {
  648. if( dateBegin == kdataMain.ElementAt(iMain).m_date )
  649. break;
  650. }
  651. SetSize( GetSize(), kdataMain.GetSize()-iMain-GetSize() > 0 ? kdataMain.GetSize()-iMain-GetSize() : -1 );
  652. int nCount = 0;
  653. for( ; iMain <= kdataMain.GetSize() && iSelf <= GetSize(); iMain++, iSelf++ )
  654. {
  655. if( !bFillToEnd && iSelf == GetSize() && ElementAt(iSelf-1).m_date < dateMainEnd5 )
  656. break;
  657. if( !bFillToEnd && iMain == kdataMain.GetSize() && kdataMain.ElementAt(iMain-1).m_date < dateEnd5 )
  658. break;
  659. while( iMain > 0 && iMain <= kdataMain.GetSize() && iSelf < GetSize()
  660. && ( iMain == kdataMain.GetSize() || kdataMain.ElementAt(iMain).m_date > ElementAt(iSelf).m_date ) )
  661. {
  662. // KDATA kd;
  663. // memset( &kd, 0, sizeof(kd) );
  664. // kd.m_date = ElementAt(iSelf).m_date;
  665. // kd.open = kd.high = kd.low = kd.close = kdataMain.ElementAt(iMain-1).close;
  666. // kdataMain.InsertAt( iMain, kd );
  667. // iMain ++;
  668. iSelf ++;
  669. // nCount ++;
  670. }
  671. while( iMain < kdataMain.GetSize() && iSelf <= GetSize() && iSelf > 0
  672. && ( iSelf == GetSize() || kdataMain.ElementAt(iMain).m_date < ElementAt(iSelf).m_date ) )
  673. {
  674. KDATA kd;
  675. memset( &kd, 0, sizeof(kd) );
  676. kd.m_date = kdataMain.ElementAt(iMain).m_date;
  677. kd.m_fOpen = kd.m_fHigh = kd.m_fLow = kd.m_fClose = ElementAt(iSelf-1).m_fClose;
  678. InsertAt( iSelf, kd );
  679. iMain ++;
  680. iSelf ++;
  681. nCount ++;
  682. }
  683. }
  684. return nCount;
  685. }
  686. BOOL CKData::IsAdjacentDays( int nIndex, int nDays )
  687. {
  688. // check parameters
  689. SP_ASSERT( nIndex >= 0 && nIndex < GetSize() && nDays >= 1 );
  690. if( nIndex < 0 || nIndex >= GetSize() || nDays < 1 )
  691. return FALSE;
  692. // data not enougy
  693. if( nDays > nIndex )
  694. return FALSE;
  695. CSPTime sptime1, sptime2;
  696. sptime1.FromStockTime( ElementAt(nIndex-nDays).m_date, CKData::IsDayOrMin(m_nKType) );
  697. sptime1.FromStockTime( ElementAt(nIndex).m_date, CKData::IsDayOrMin(m_nKType) );
  698. if( CKData::ktypeMonth == m_nKType )
  699. {
  700. if( sptime2 - sptime1 >= CSPTimeSpan(nDays+63,0,0,0) )
  701. return FALSE;
  702. }
  703. else if( CKData::ktypeWeek == m_nKType )
  704. {
  705. if( sptime2 - sptime1 >= CSPTimeSpan(nDays+15,0,0,0) )
  706. return FALSE;
  707. }
  708. else
  709. {
  710. if( sptime2 - sptime1 >= CSPTimeSpan(nDays+8,0,0,0) )
  711. return FALSE;
  712. }
  713. return TRUE;
  714. }
  715. BOOL CKData::GetDiff( double * pValue, DWORD dateCur, int nDays )
  716. {
  717. SP_ASSERT( pValue && nDays > 0 );
  718. // Find date Current to calculate from
  719. int nIndex = GetIndexByDate( dateCur );
  720. if( -1 == nIndex )
  721. return FALSE;
  722. // data not enough
  723. if( nDays > nIndex )
  724. return FALSE;
  725. // 检查是否是相邻成交日
  726. if( !IsAdjacentDays( nIndex, nDays ) )
  727. return FALSE;
  728. if( ElementAt(nIndex-nDays).m_fClose < 1e-4 )
  729. return FALSE;
  730. if( pValue )
  731. *pValue = ElementAt(nIndex).m_fClose - ElementAt(nIndex-nDays).m_fClose;
  732. return TRUE;
  733. }
  734. BOOL CKData::GetDiffPercent( double * pValue, DWORD dateCur, int nDays )
  735. {
  736. SP_ASSERT( pValue && nDays > 0 );
  737. // Find date Current to calculate from
  738. int nIndex = GetIndexByDate( dateCur );
  739. if( -1 == nIndex )
  740. return FALSE;
  741. // data not enough
  742. if( nDays > nIndex )
  743. return FALSE;
  744. // 检查是否是相邻成交日
  745. if( !IsAdjacentDays( nIndex, nDays ) )
  746. return FALSE;
  747. if( ElementAt(nIndex-nDays).m_fAmount < 1e-4 )
  748. return FALSE;
  749. if( pValue )
  750. *pValue = (100. * ElementAt(nIndex).m_fClose) / ElementAt(nIndex-nDays).m_fClose - 100;
  751. return TRUE;
  752. }
  753. BOOL CKData::GetScope( double * pValue, DWORD dateCur, int nDays )
  754. {
  755. SP_ASSERT( pValue && nDays > 0 );
  756. // Find date Current to calculate from
  757. int nIndex = GetIndexByDate( dateCur );
  758. if( -1 == nIndex )
  759. return FALSE;
  760. // data not enough
  761. if( nDays > nIndex )
  762. return FALSE;
  763. // 检查是否是相邻成交日
  764. if( !IsAdjacentDays( nIndex, nDays ) )
  765. return FALSE;
  766. double dMax = 0, dMin = 0;
  767. int nCount = 0;
  768. for( int k=nIndex; k>=0; k-- )
  769. {
  770. if( nIndex == k )
  771. {
  772. dMin = ElementAt(k).m_fLow;
  773. dMax = ElementAt(k).m_fHigh;
  774. }
  775. if( dMin > ElementAt(k).m_fLow ) dMin = ElementAt(k).m_fLow;
  776. if( dMax < ElementAt(k).m_fHigh ) dMax = ElementAt(k).m_fHigh;
  777. nCount ++;
  778. if( nCount == nDays )
  779. break;
  780. }
  781. // data not enough
  782. if( nCount != nDays || nCount <= 0 )
  783. return FALSE;
  784. if( ElementAt(nIndex-nDays).m_fClose <= 0 )
  785. return FALSE;
  786. if( pValue )
  787. *pValue = ( 100. * (dMax-dMin) ) / ElementAt(nIndex-nDays).m_fClose ;
  788. return TRUE;
  789. }
  790. BOOL CKData::GetVolumeSum( double * pValue, DWORD dateCur, int nDays )
  791. {
  792. SP_ASSERT( pValue && nDays > 0 );
  793. // Find date Current to calculate from
  794. int nIndex = GetIndexByDate( dateCur );
  795. if( -1 == nIndex )
  796. return FALSE;
  797. // data not enough
  798. if( nDays > nIndex )
  799. return FALSE;
  800. // 检查是否是相邻成交日
  801. if( !IsAdjacentDays( nIndex, nDays ) )
  802. return FALSE;
  803. // begin calculate
  804. double dAll = 0;
  805. int nCount = 0;
  806. for( int i=nIndex; i>=0; i-- )
  807. {
  808. dAll += ElementAt(i).m_fVolume;
  809. nCount ++;
  810. if( nCount >= nDays )
  811. break;
  812. }
  813. // data not enough
  814. if( nCount != nDays || nCount <= 0 )
  815. return FALSE;
  816. if( pValue )
  817. *pValue = dAll;
  818. return TRUE;
  819. }
  820. BOOL CKData::GetRatioVolume( double * pValue, DWORD dateCur, int nDays )
  821. {
  822. SP_ASSERT( pValue && nDays > 0 );
  823. // Find date Current to calculate from
  824. int nIndex = GetIndexByDate( dateCur );
  825. if( -1 == nIndex )
  826. return FALSE;
  827. // data not enough
  828. if( nDays > nIndex )
  829. return FALSE;
  830. // 检查是否是相邻成交日
  831. if( !IsAdjacentDays( nIndex, nDays ) )
  832. return FALSE;
  833. // begin calculate
  834. double dAll = 0;
  835. int nCount = 0;
  836. for( int i=nIndex-1; i>=0; i-- )
  837. {
  838. dAll += ElementAt(i).m_fVolume;
  839. nCount ++;
  840. if( nCount >= nDays )
  841. break;
  842. }
  843. // data not enough
  844. if( nCount != nDays || nCount <= 0 )
  845. return FALSE;
  846. if( fabs(dAll) < 1 )
  847. return FALSE;
  848. if( pValue )
  849. *pValue = (ElementAt(nIndex).m_fVolume / dAll ) * nCount;
  850. return TRUE;
  851. }
  852. BOOL CKData::GetRS( double * pValue, DWORD dateCur, int nDays )
  853. {
  854. SP_ASSERT( pValue && nDays > 0 );
  855. // Find date Current to calculate from
  856. int nIndex = GetIndexByDate( dateCur );
  857. if( -1 == nIndex )
  858. return FALSE;
  859. // data not enough
  860. if( nDays > nIndex )
  861. return FALSE;
  862. // 检查是否是相邻成交日
  863. if( !IsAdjacentDays( nIndex, nDays ) )
  864. return FALSE;
  865. int nCount = 0;
  866. double dA = 0, dB = 0;
  867. for( int k=nIndex; k>=1; k-- )
  868. {
  869. if( ElementAt(k).m_fClose > ElementAt(k-1).m_fClose )
  870. dA += (ElementAt(k).m_fClose - ElementAt(k-1).m_fClose);
  871. else
  872. dB += (ElementAt(k-1).m_fClose - ElementAt(k).m_fClose);
  873. nCount ++;
  874. if( nCount == nDays )
  875. {
  876. double dResult;
  877. if( fabs(dB) < 1e-4 )
  878. dResult = 100;
  879. else
  880. dResult = dA / dB;
  881. if( pValue )
  882. *pValue = dResult;
  883. return TRUE;
  884. }
  885. }
  886. return FALSE;
  887. }
  888. BOOL CKData::GetMA( double * pValue, int nIndex, int nDays )
  889. {
  890. SP_ASSERT( nIndex >= 0 && nIndex < GetSize() && nDays > 0 );
  891. if( nIndex < 0 || nIndex >=GetSize() || nDays <= 0 )
  892. return FALSE;
  893. int nCount = 0;
  894. if( nDays > nIndex+1 )
  895. return FALSE;
  896. double dResult = 0;
  897. for( int k=nIndex; k>=0; k-- )
  898. {
  899. dResult += MaindataAt(k);
  900. nCount ++;
  901. if( nCount == nDays )
  902. {
  903. if( pValue )
  904. *pValue = dResult / nDays;
  905. return TRUE;
  906. }
  907. }
  908. return FALSE;
  909. }
  910. /////////////////////////////////////////////////////////////////////////////
  911. // Private Operations
  912. int CKData::ConvertKData( CKData &kdSrc, CKData &kdDest, int multiple )
  913. {
  914. // convert kdSrc k line to kdDest k line accordding to their multiple
  915. SP_ASSERT( multiple > 1 );
  916. if( multiple < 2 ) return 0;
  917. kdDest.SetSize( 0, kdSrc.GetSize() / multiple + 5 );
  918. int nStart = kdSrc.GetSize() % multiple;
  919. int nCount = 0;
  920. KDATA dataDest;
  921. for( int pos=nStart; pos<kdSrc.GetSize(); pos++ )
  922. {
  923. KDATA & dataSrc = kdSrc.ElementAt( pos );
  924. nCount ++;
  925. if( 1 == nCount )
  926. {
  927. memcpy( &dataDest, &dataSrc, sizeof(dataDest) );
  928. }
  929. else
  930. {
  931. dataDest.m_fAmount += dataSrc.m_fAmount;
  932. if( dataDest.m_fHigh < dataSrc.m_fHigh ) dataDest.m_fHigh = dataSrc.m_fHigh;
  933. if( dataDest.m_fLow > dataSrc.m_fLow ) dataDest.m_fLow = dataSrc.m_fLow;
  934. dataDest.m_fVolume += dataSrc.m_fVolume;
  935. dataDest.m_fClose = dataSrc.m_fClose;
  936. }
  937. if( multiple == nCount ) // new dataDest is over
  938. {
  939. nCount = 0;
  940. kdDest.Add( dataDest );
  941. }
  942. }
  943. return kdDest.GetSize();
  944. }
  945. void CKData::CopyData( const CKData &src )
  946. {
  947. if( m_pDataOriginal )
  948. {
  949. delete [] (BYTE*)m_pDataOriginal;
  950. m_pDataOriginal = NULL;
  951. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  952. }
  953. if( m_pData )
  954. {
  955. delete [] (BYTE*)m_pData;
  956. m_pData = NULL;
  957. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  958. }
  959. if( src.m_nSizeOriginal > 0 )
  960. {
  961. SP_ASSERT( src.m_pDataOriginal );
  962. SP_ASSERT( src.m_nMaxSizeOriginal >= src.m_nSizeOriginal );
  963. m_pDataOriginal = (KDATA*) new BYTE[src.m_nMaxSizeOriginal * sizeof(KDATA)];
  964. if( m_pDataOriginal )
  965. {
  966. memset( m_pDataOriginal, 0, src.m_nMaxSizeOriginal * sizeof(KDATA) );  // zero fill
  967. memcpy( m_pDataOriginal, src.m_pDataOriginal, src.m_nSizeOriginal * sizeof(KDATA) );
  968. m_nSizeOriginal = src.m_nSizeOriginal;
  969. m_nMaxSizeOriginal = src.m_nMaxSizeOriginal;
  970. }
  971. }
  972. if( src.m_nSize > 0 )
  973. {
  974. SP_ASSERT( src.m_pData );
  975. SP_ASSERT( src.m_nMaxSize >= src.m_nSize );
  976. m_pData = (KDATA*) new BYTE[src.m_nMaxSize * sizeof(KDATA)];
  977. if( m_pData )
  978. {
  979. memset( m_pData, 0, src.m_nMaxSize * sizeof(KDATA) );  // zero fill
  980. memcpy( m_pData, src.m_pData, src.m_nSize * sizeof(KDATA) );
  981. m_nSize = src.m_nSize;
  982. m_nMaxSize = src.m_nMaxSize;
  983. }
  984. }
  985. }
  986. void CKData::LoadDataOriginal( )
  987. {
  988. if( m_pDataOriginal )
  989. {
  990. if( m_pData )
  991. delete [] (BYTE*)m_pData;
  992. m_pData = m_pDataOriginal;
  993. m_nSize = m_nSizeOriginal;
  994. m_nMaxSize = m_nMaxSizeOriginal;
  995. m_pDataOriginal = NULL;
  996. m_nSizeOriginal = m_nMaxSizeOriginal = 0;
  997. }
  998. }
  999. void CKData::StoreDataOriginal( )
  1000. {
  1001. if( NULL == m_pDataOriginal )
  1002. {
  1003. m_pDataOriginal = m_pData;
  1004. m_nSizeOriginal = m_nSize;
  1005. m_nMaxSizeOriginal = m_nMaxSize;
  1006. m_pData = NULL;
  1007. m_nSize = m_nMaxSize = 0;
  1008. }
  1009. }
  1010. float CKData::GetRatio( float fLastClose, DRDATA & dr )
  1011. {
  1012. if( fLastClose < 1e-4 )
  1013. return 1.0000;
  1014. float fRatio = 1.0000;
  1015. if( dr.m_fProfit > 1e-4 )
  1016. {
  1017. fRatio = fRatio * ( 1 - dr.m_fProfit/fLastClose );
  1018. }
  1019. if( dr.m_fGive > 1e-4 )
  1020. {
  1021. fRatio = (float)( fRatio * 1./(1.+dr.m_fGive) );
  1022. }
  1023. if( dr.m_fPei > 1e-4 )
  1024. {
  1025. float priceNow = (float)( (dr.m_fPeiPrice * dr.m_fPei + fLastClose)/(1.+dr.m_fPei) );
  1026. fRatio = fRatio * priceNow / fLastClose;
  1027. }
  1028. return fRatio;
  1029. }
  1030. void CKData::ConvertXDR( BOOL bUP, DWORD dateAutoDRBegin, double dAutoDRLimit )
  1031. {
  1032. CDRData drtemp;
  1033. drtemp = m_drdata;
  1034. drtemp.Sort( );
  1035. if( m_pData )
  1036. {
  1037. delete [] (BYTE*)m_pData;
  1038. m_nSize = m_nMaxSize = 0;
  1039. m_pData = NULL;
  1040. }
  1041. if( NULL == m_pDataOriginal || 0 == m_nSizeOriginal )
  1042. return;
  1043. /* if( drtemp.GetSize() == 0 )
  1044. {
  1045. SetSize( m_nSizeOriginal );
  1046. if( m_pData )
  1047. memcpy( m_pData, m_pDataOriginal, sizeof(KDATA)*m_nSize );
  1048. return;
  1049. }
  1050. */
  1051. dAutoDRLimit = dAutoDRLimit / 100;
  1052. if( bUP )
  1053. {
  1054. SetSize( 0, m_nSizeOriginal );
  1055. int drPos = 0;
  1056. float fRatio = 1.000000;
  1057. for( int i=0; i<m_nSizeOriginal; i++ )
  1058. {
  1059. KDATA & kd = m_pDataOriginal[i];
  1060. KDATA newkd = kd;
  1061. if( drPos < drtemp.GetSize() && ToDayDate(kd.m_date) >= drtemp.ElementAt(drPos).m_date )
  1062. {
  1063. if( i > 0 )
  1064. {
  1065. KDATA kdLast = m_pDataOriginal[i-1];
  1066. fRatio = fRatio * GetRatio( kdLast.m_fClose, drtemp.ElementAt(drPos) );
  1067. }
  1068. drPos ++;
  1069. }
  1070. else if( ToDayDate(kd.m_date) >= dateAutoDRBegin && i > 0 ) // Auto XDR
  1071. {
  1072. KDATA kdLast = m_pDataOriginal[i-1];
  1073. if( kdLast.m_fClose > 1e-4 && kd.m_fOpen < kdLast.m_fClose
  1074. && fabs(kd.m_fOpen/kdLast.m_fClose-1) > dAutoDRLimit )
  1075. fRatio = fRatio * kd.m_fOpen / kdLast.m_fClose;
  1076. }
  1077. newkd.m_fOpen = (kd.m_fOpen / fRatio);
  1078. newkd.m_fHigh = (kd.m_fHigh / fRatio);
  1079. newkd.m_fLow = (kd.m_fLow / fRatio);
  1080. newkd.m_fClose = (kd.m_fClose / fRatio);
  1081. newkd.m_fVolume = (kd.m_fVolume * fRatio);
  1082. Add( newkd );
  1083. }
  1084. }
  1085. else
  1086. {
  1087. SetSize( m_nSizeOriginal );
  1088. int drPos = drtemp.GetSize()-1;
  1089. float fRatio = 1.000000;
  1090. for( int i=m_nSizeOriginal-1; i>=0; i-- )
  1091. {
  1092. KDATA & kd = m_pDataOriginal[i];
  1093. KDATA newkd = kd;
  1094. if( drPos >= 0 && ToDayDate(kd.m_date) < drtemp.ElementAt(drPos).m_date )
  1095. {
  1096. if( i < m_nSizeOriginal-1 )
  1097. fRatio = fRatio * GetRatio( kd.m_fClose, drtemp.ElementAt(drPos) );
  1098. drPos --;
  1099. }
  1100. else if( ToDayDate(kd.m_date) >= dateAutoDRBegin && i+1 < m_nSizeOriginal ) // Auto XDR
  1101. {
  1102. KDATA kdNext = m_pDataOriginal[i+1];
  1103. if( kdNext.m_fOpen > 1e-4 && kdNext.m_fOpen < kd.m_fClose
  1104. && fabs(kdNext.m_fOpen/kd.m_fClose-1) > dAutoDRLimit )
  1105. fRatio = fRatio * kdNext.m_fOpen / kd.m_fClose;
  1106. }
  1107. newkd.m_fOpen = (kd.m_fOpen * fRatio);
  1108. newkd.m_fHigh = (kd.m_fHigh * fRatio);
  1109. newkd.m_fLow = (kd.m_fLow * fRatio);
  1110. newkd.m_fClose = (kd.m_fClose * fRatio);
  1111. newkd.m_fVolume = (kd.m_fVolume / fRatio);
  1112. SetAt( i, newkd );
  1113. }
  1114. }
  1115. }