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

金融证券系统

开发平台:

Visual C++

  1. /*
  2. Cross Platform Core Code.
  3. Copyright(R) 2001-2002 Balang Software.
  4. All rights reserved.
  5. */
  6. #include "StdAfx.h"
  7. #include "../Include/Stock.h"
  8. #include "../Include/Technique.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #endif
  16. //////////////////////////////////////////////////////////////////////
  17. // CKLine
  18. CKLine::CKLine( )
  19. {
  20. SetDefaultParameters( );
  21. }
  22. CKLine::CKLine( CKData * pKData )
  23. : CTechnique( pKData )
  24. {
  25. SetDefaultParameters( );
  26. }
  27. CKLine::~CKLine()
  28. {
  29. Clear( );
  30. }
  31. void CKLine::SetDefaultParameters( )
  32. {
  33. }
  34. void CKLine::AttachParameters( CKLine & src )
  35. {
  36. }
  37. BOOL CKLine::IsValidParameters( )
  38. {
  39. return TRUE;
  40. }
  41. void CKLine::Clear( )
  42. {
  43. CTechnique::Clear( );
  44. }
  45. /***
  46. 得到K线价格的从nStart到nEnd的最小值和最大值
  47. */
  48. BOOL CKLine::GetMinMaxInfo( int nStart, int nEnd, double *pdMin, double *pdMax )
  49. {
  50. STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
  51. double dMin = -1;
  52. double dMax = 1;
  53. for( int k=nStart; k<=nEnd; k++ )
  54. {
  55. KDATA & kd = m_pKData->ElementAt(k);
  56. if( nStart == k || dMin > kd.m_fLow ) dMin = (double)kd.m_fLow;
  57. if( nStart == k || dMax < kd.m_fHigh ) dMax = (double)kd.m_fHigh;
  58. }
  59. dMin -= fabs(dMin) * 0.01;
  60. dMax += fabs(dMax) * 0.01;
  61. if( dMin <= 0 )
  62. dMin = 0;
  63. if( dMax - dMin < 0.03 )
  64. dMax = dMin + 0.03;
  65. if( pdMin ) *pdMin = dMin;
  66. if( pdMax ) *pdMax = dMax;
  67. return TRUE;
  68. }
  69. //////////////////////////////////////////////////////////////////////
  70. // CMA
  71. CMA::CMA( )
  72. {
  73. SetDefaultParameters( );
  74. }
  75. CMA::CMA( CKData * pKData )
  76. : CTechnique( pKData )
  77. {
  78. SetDefaultParameters( );
  79. }
  80. CMA::~CMA()
  81. {
  82. Clear( );
  83. }
  84. void CMA::SetDefaultParameters( )
  85. {
  86. m_nType = typeMA;
  87. m_adwMADays.RemoveAll();
  88. m_adwMADays.Add( 5 );
  89. m_adwMADays.Add( 10 );
  90. m_adwMADays.Add( 20 );
  91. m_itsGoldenFork = ITS_BUYINTENSE;
  92. m_itsDeadFork = ITS_SELLINTENSE;
  93. m_itsLong = ITS_BUY;
  94. m_itsShort = ITS_SELL;
  95. }
  96. void CMA::AttachParameters( CMA & src )
  97. {
  98. m_nType = src.m_nType;
  99. m_adwMADays.Copy( src.m_adwMADays );
  100. m_itsGoldenFork = src.m_itsGoldenFork;
  101. m_itsDeadFork = src.m_itsDeadFork;
  102. m_itsLong = src.m_itsLong;
  103. m_itsShort = src.m_itsShort;
  104. }
  105. BOOL CMA::IsValidParameters( )
  106. {
  107. STT_VALID_DAYSARRAY( m_adwMADays );
  108. return ( (typeMA == m_nType || typeEXPMA == m_nType)
  109. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork)
  110. && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  111. }
  112. void CMA::Clear( )
  113. {
  114. CTechnique::Clear( );
  115. }
  116. int CMA::GetSignal( int nIndex, UINT * pnCode )
  117. {
  118. // 金叉或者死叉
  119. int nSignal = GetForkSignal( nIndex, m_adwMADays, m_itsGoldenFork, m_itsDeadFork, pnCode );
  120. if( ITS_ISBUY(nSignal) || ITS_ISSELL(nSignal) )
  121. return nSignal;
  122. // 趋势
  123. return GetTrendIntensity( nIndex, m_adwMADays, m_itsLong, m_itsShort, pnCode );
  124. }
  125. BOOL CMA::GetMinMaxInfo(int nStart, int nEnd,
  126.    double *pdMin, double *pdMax )
  127. {
  128. return AfxGetMinMaxInfo( nStart, nEnd, pdMin, pdMax, this, m_adwMADays );
  129. }
  130. /***
  131. 两种:
  132. 1. MA
  133.     MA = n日收盘价的平均值
  134. 2. EXPMA
  135.     EXPMA(1) = CLOSE(1)
  136. EXPMA(i) = (1-α)EXPMA(i-1) + αCLOSE(i)
  137. 其中 α = 2 / (n+1)
  138. */
  139. BOOL CMA::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
  140. {
  141. STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
  142. int nCount = 0;
  143. if( nDays > nIndex+1 )
  144. return FALSE;
  145. double dResult = 0;
  146. int k = 0;
  147. switch( m_nType )
  148. {
  149. case typeMA:
  150. return m_pKData->GetMA( pValue, nIndex, nDays );
  151. break;
  152. case typeEXPMA:
  153. if( bUseLast && pValue )
  154. {
  155. if( 0 == nIndex )
  156. dResult = m_pKData->MaindataAt(nIndex);
  157. else
  158. dResult = (*pValue)*(nDays-1)/(nDays+1) + m_pKData->MaindataAt(nIndex) * 2./(nDays+1);
  159. }
  160. else
  161. {
  162. for( k=0; k<=nIndex; k++ )
  163. {
  164. if( 0 == k )
  165. dResult = m_pKData->MaindataAt(k);
  166. else
  167. dResult = dResult*(nDays-1)/(nDays+1) + m_pKData->MaindataAt(k) * 2./(nDays+1);
  168. }
  169. }
  170. if( pValue )
  171. *pValue = dResult;
  172. break;
  173. default:
  174. SP_ASSERT( FALSE );
  175. }
  176. return TRUE;
  177. }
  178. //////////////////////////////////////////////////////////////////////
  179. // CBBI
  180. CBBI::CBBI( )
  181. {
  182. SetDefaultParameters( );
  183. }
  184. CBBI::CBBI( CKData * pKData )
  185. : CTechnique( pKData )
  186. {
  187. SetDefaultParameters( );
  188. }
  189. CBBI::~CBBI()
  190. {
  191. Clear( );
  192. }
  193. void CBBI::SetDefaultParameters( )
  194. {
  195. m_nMA1Days = 3;
  196. m_nMA2Days = 6;
  197. m_nMA3Days = 12;
  198. m_nMA4Days = 24;
  199. m_itsGoldenFork = ITS_BUY;
  200. m_itsDeadFork = ITS_SELL;
  201. }
  202. void CBBI::AttachParameters( CBBI & src )
  203. {
  204. m_nMA1Days = src.m_nMA1Days;
  205. m_nMA2Days = src.m_nMA2Days;
  206. m_nMA3Days = src.m_nMA3Days;
  207. m_nMA4Days = src.m_nMA4Days;
  208. m_itsGoldenFork = src.m_itsGoldenFork;
  209. m_itsDeadFork = src.m_itsDeadFork;
  210. }
  211. BOOL CBBI::IsValidParameters( )
  212. {
  213. return ( VALID_DAYS( m_nMA1Days ) && VALID_DAYS( m_nMA2Days )
  214. && VALID_DAYS( m_nMA3Days ) && VALID_DAYS( m_nMA4Days )
  215. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  216. }
  217. void CBBI::Clear( )
  218. {
  219. CTechnique::Clear( );
  220. }
  221. int CBBI::GetSignal( int nIndex, UINT * pnCode )
  222. {
  223. if( pnCode ) *pnCode = ITSC_NOTHING;
  224. if( nIndex <= 0 )
  225. return ITS_NOTHING;
  226. double dLiminalLow = 0, dLiminalHigh = 0;
  227. if( !IntensityPreparePrice( nIndex, pnCode, 0, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.4, 0.6 ) )
  228. return ITS_NOTHING;
  229. double dBBINow = 0, dBBILast = 0;
  230. if( !Calculate( &dBBILast, nIndex-1, FALSE )
  231. || !Calculate( &dBBINow, nIndex, FALSE ) )
  232. return ITS_NOTHING;
  233. double dNowHigh = m_pKData->ElementAt(nIndex).m_fHigh;
  234. double dNowLow = m_pKData->ElementAt(nIndex).m_fLow;
  235. double dNowClose = m_pKData->ElementAt(nIndex).m_fClose;
  236. double dLastHigh = m_pKData->ElementAt(nIndex-1).m_fHigh;
  237. double dLastLow = m_pKData->ElementAt(nIndex-1).m_fLow;
  238. double dLastClose = m_pKData->ElementAt(nIndex-1).m_fClose;
  239. if( dNowClose < dLiminalLow && dLastLow < dBBILast && dNowLow > dBBINow )
  240. { // 低位趋势向上
  241. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  242. return m_itsGoldenFork;
  243. }
  244. if( dNowClose > dLiminalHigh && dLastHigh > dBBILast && dNowHigh < dBBINow )
  245. { // 高位趋势向下
  246. if( pnCode ) *pnCode = ITSC_DEADFORK;
  247. return m_itsDeadFork;
  248. }
  249. return ITS_NOTHING;
  250. }
  251. BOOL CBBI::GetMinMaxInfo(int nStart, int nEnd,
  252.    double *pdMin, double *pdMax )
  253. {
  254. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  255. }
  256. /***
  257. BBI = 4 个 不同日期的MA 的平均值
  258. */
  259. BOOL CBBI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  260. {
  261. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  262. if( LoadFromCache( nIndex, pValue ) )
  263. return TRUE;
  264. double dResult = 0;
  265. double dTemp = 0;
  266. if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA1Days ) )
  267. return FALSE;
  268. dResult += dTemp;
  269. if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA2Days ) )
  270. return FALSE;
  271. dResult += dTemp;
  272. if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA3Days ) )
  273. return FALSE;
  274. dResult += dTemp;
  275. if( !m_pKData->GetMA( &dTemp, nIndex, m_nMA4Days ) )
  276. return FALSE;
  277. dResult += dTemp;
  278. dResult = dResult / 4;
  279. if( pValue )
  280. *pValue = dResult;
  281. StoreToCache( nIndex, pValue );
  282. return TRUE;
  283. }
  284. //////////////////////////////////////////////////////////////////////
  285. // CBOLL
  286. CBOLL::CBOLL( )
  287. {
  288. SetDefaultParameters( );
  289. }
  290. CBOLL::CBOLL( CKData * pKData )
  291. : CTechnique( pKData )
  292. {
  293. SetDefaultParameters( );
  294. }
  295. CBOLL::~CBOLL()
  296. {
  297. Clear( );
  298. }
  299. void CBOLL::SetDefaultParameters( )
  300. {
  301. m_dMultiUp = 2;
  302. m_dMultiDown = 2;
  303. m_nMADays = 20;
  304. m_itsSupport = ITS_BUY;
  305. m_itsResistance = ITS_SELL;
  306. }
  307. void CBOLL::AttachParameters( CBOLL & src )
  308. {
  309. m_dMultiUp = src.m_dMultiUp;
  310. m_dMultiDown = src.m_dMultiDown;
  311. m_nMADays = src.m_nMADays;
  312. m_itsSupport = src.m_itsSupport;
  313. m_itsResistance = src.m_itsResistance;
  314. }
  315. BOOL CBOLL::IsValidParameters( )
  316. {
  317. return ( m_dMultiUp > 0 && m_dMultiDown > 0 && VALID_DAYS( m_nMADays )
  318. && VALID_ITS(m_itsSupport) && VALID_ITS(m_itsResistance) );
  319. }
  320. void CBOLL::Clear( )
  321. {
  322. CTechnique::Clear( );
  323. }
  324. int CBOLL::GetSignal( int nIndex, UINT * pnCode )
  325. {
  326. if( pnCode ) *pnCode = ITSC_NOTHING;
  327. double dMA = 0, dUp = 0, dDown = 0;
  328. if( !Calculate( &dMA, &dUp, &dDown, nIndex, FALSE ) )
  329. return ITS_NOTHING;
  330. double dClose = m_pKData->ElementAt(nIndex).m_fClose;
  331. if( dClose < dDown )
  332. { // 跌破支撑位
  333. if( pnCode ) *pnCode = ITSC_SUPPORT;
  334. return m_itsSupport;
  335. }
  336. if( dClose > dUp )
  337. { // 涨过阻力位
  338. if( pnCode ) *pnCode = ITSC_RESISTANCE;
  339. return m_itsResistance;
  340. }
  341. return ITS_NOTHING;
  342. }
  343. BOOL CBOLL::GetMinMaxInfo(int nStart, int nEnd,
  344.    double *pdMin, double *pdMax )
  345. {
  346. return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
  347. }
  348. /***
  349. 布林带是以股价平均线MA为中心线,上方阻力线MA+αSn和下方支撑线MA-αSn之间的带状区域
  350. 其中 Sn为n日收盘价的标准差
  351. */
  352. BOOL CBOLL::Calculate( double * pdMA, double * pdUp, double * pdDown, int nIndex, BOOL bUseLast )
  353. {
  354. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  355. if( m_nMADays < 2 )
  356. return FALSE;
  357. if( LoadFromCache( nIndex, pdMA, pdUp, pdDown ) )
  358. return TRUE;
  359. double dMA = 0, dUp = 0, dDown = 0, dS = 0;
  360. if( !m_pKData->GetMA( &dMA, nIndex, m_nMADays ) )
  361. return FALSE;
  362. int nCount = 0;
  363. for( int k=nIndex; k>=0; k-- )
  364. {
  365. dS += (m_pKData->MaindataAt(k) - dMA) * (m_pKData->MaindataAt(k) - dMA);
  366. nCount ++;
  367. if( nCount == m_nMADays )
  368. break;
  369. }
  370. dS = sqrt( dS / (m_nMADays-1) );
  371. dUp = dMA + m_dMultiUp * dS;
  372. dDown = dMA - m_dMultiDown * dS;
  373. if( pdMA ) *pdMA = dMA;
  374. if( pdUp ) *pdUp = dUp;
  375. if( pdDown ) *pdDown = dDown;
  376. StoreToCache( nIndex, pdMA, pdUp, pdDown );
  377. return TRUE;
  378. }
  379. //////////////////////////////////////////////////////////////////////
  380. // CPV
  381. CPV::CPV( )
  382. {
  383. SetDefaultParameters( );
  384. }
  385. CPV::CPV( CKData * pKData )
  386. : CTechnique( pKData )
  387. {
  388. SetDefaultParameters( );
  389. }
  390. CPV::~CPV()
  391. {
  392. Clear( );
  393. }
  394. void CPV::SetDefaultParameters( )
  395. {
  396. }
  397. void CPV::AttachParameters( CPV & src )
  398. {
  399. }
  400. BOOL CPV::IsValidParameters( )
  401. {
  402. return TRUE;
  403. }
  404. void CPV::Clear( )
  405. {
  406. CTechnique::Clear( );
  407. }
  408. int CPV::GetSignal( int nIndex, UINT * pnCode )
  409. {
  410. if( pnCode ) *pnCode = ITSC_NOTHING;
  411. // 无买卖信号
  412. return ITS_NOTHING;
  413. }
  414. BOOL CPV::GetMinMaxInfo(int nStart, int nEnd,
  415.    double *pdMin, double *pdMax )
  416. {
  417. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  418. }
  419. /***
  420. PV就是当日成交均价,成交额除以成交量
  421. */
  422. BOOL CPV::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  423. {
  424. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  425. if( LoadFromCache( nIndex, pValue ) )
  426. return TRUE;
  427. KDATA kd = m_pKData->ElementAt(nIndex);
  428. if( kd.m_fVolume <= 1e-4 || kd.m_fAmount <= 1e-4 )
  429. return  FALSE;
  430. int nCount = 0;
  431. double average = ((double)(kd.m_fAmount)) / kd.m_fVolume;
  432. while( average < kd.m_fLow && nCount < 10 ) { average *= 10; nCount ++; }
  433. while( average > kd.m_fHigh && nCount < 20 ) { average /= 10; nCount ++; }
  434. if( average < kd.m_fLow ) // 说明是指数
  435. average = (kd.m_fOpen+kd.m_fHigh+kd.m_fLow+kd.m_fClose)/4;
  436. double dPV = average;
  437. if( pValue )
  438. *pValue = dPV;
  439. StoreToCache( nIndex, pValue );
  440. return TRUE;
  441. }
  442. //////////////////////////////////////////////////////////////////////
  443. // CSAR
  444. CSAR::CSAR( )
  445. {
  446. SetDefaultParameters( );
  447. }
  448. CSAR::CSAR( CKData * pKData )
  449. : CTechnique( pKData )
  450. {
  451. SetDefaultParameters( );
  452. m_bCurUp = m_bFirstUp;
  453. m_bTurn = FALSE;
  454. m_dCurAF = m_dAFStep;
  455. m_dCurHigh = -1;
  456. m_dCurLow = -1;
  457. }
  458. CSAR::~CSAR()
  459. {
  460. Clear( );
  461. }
  462. void CSAR::SetDefaultParameters( )
  463. {
  464. m_nInitDays = 4;
  465. m_bFirstUp = TRUE;
  466. m_dAFStep = 0.02;
  467. m_dAFMax = 0.2;
  468. m_itsBuy = ITS_BUY;
  469. m_itsSell = ITS_SELL;
  470. }
  471. void CSAR::AttachParameters( CSAR & src )
  472. {
  473. m_nInitDays = src.m_nInitDays;
  474. m_bFirstUp = src.m_bFirstUp;
  475. m_dAFStep = src.m_dAFStep;
  476. m_dAFMax = src.m_dAFMax;
  477. m_itsBuy = src.m_itsBuy;
  478. m_itsSell = src.m_itsSell;
  479. }
  480. BOOL CSAR::IsValidParameters( )
  481. {
  482. return ( VALID_DAYS(m_nInitDays) && m_bFirstUp >= 0 && m_dAFStep > 0 && m_dAFMax > 0
  483. && VALID_ITS(m_itsBuy) && VALID_ITS(m_itsSell) );
  484. }
  485. void CSAR::Clear( )
  486. {
  487. CTechnique::Clear( );
  488. }
  489. BOOL CSAR::CalculateSAR( double * pValue, int nIndex, BOOL bUseLast )
  490. {
  491. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  492. if( m_nInitDays > nIndex + 1 )
  493. return FALSE;
  494. double dResult = 0;
  495. if( bUseLast && pValue && nIndex > 0 && !m_bTurn )
  496. {
  497. KDATA kd = m_pKData->ElementAt(nIndex-1);
  498. if( m_bCurUp )
  499. {
  500. dResult = (*pValue) + m_dCurAF * (kd.m_fHigh - (*pValue) );
  501. if( kd.m_fHigh > m_dCurHigh )
  502. {
  503. m_dCurHigh = kd.m_fHigh;
  504. m_dCurAF = m_dCurAF + m_dAFStep;
  505. if( m_dCurAF > m_dAFMax )
  506. m_dCurAF = m_dAFMax;
  507. }
  508. if( m_pKData->ElementAt(nIndex).m_fLow < dResult )
  509. m_bTurn = TRUE;
  510. }
  511. else
  512. {
  513. dResult = (*pValue) - m_dCurAF * ((*pValue) - kd.m_fLow );
  514. if( kd.m_fLow < m_dCurLow )
  515. {
  516. m_dCurLow = kd.m_fLow;
  517. m_dCurAF = m_dCurAF + m_dAFStep;
  518. if( m_dCurAF > m_dAFMax )
  519. m_dCurAF = m_dAFMax;
  520. }
  521. if( m_pKData->ElementAt(nIndex).m_fHigh > dResult )
  522. m_bTurn = TRUE;
  523. }
  524. }
  525. else
  526. {
  527. for( int k=nIndex; k>=nIndex-m_nInitDays+1; k-- )
  528. {
  529. KDATA kd = m_pKData->ElementAt(k);
  530. if( nIndex == k )
  531. {
  532. m_dCurHigh = kd.m_fHigh;
  533. m_dCurLow = kd.m_fLow;
  534. }
  535. else if( kd.m_fHigh > m_dCurHigh )
  536. m_dCurHigh = kd.m_fHigh;
  537. else if( kd.m_fLow < m_dCurLow )
  538. m_dCurLow = kd.m_fLow;
  539. }
  540. if( m_bTurn )
  541. m_bCurUp = ! m_bCurUp;
  542. else
  543. m_bCurUp = m_bFirstUp;
  544. m_bTurn = FALSE;
  545. m_dCurAF = m_dAFStep;
  546. if( m_bCurUp )
  547. dResult = m_dCurLow;
  548. else
  549. dResult = m_dCurHigh;
  550. }
  551. if( pValue )
  552. *pValue = dResult;
  553. return TRUE;
  554. }
  555. int CSAR::GetSignal( int nIndex, UINT * pnCode )
  556. {
  557. if( pnCode ) *pnCode = ITSC_NOTHING;
  558. Clear( );
  559. double dValue;
  560. if( !Calculate( &dValue, nIndex, FALSE ) )
  561. return ITS_NOTHING;
  562. if( m_bTurn && !m_bCurUp )
  563. { // 反转向上
  564. if( pnCode ) *pnCode = ITSC_LONG;
  565. return m_itsBuy;
  566. }
  567. if( m_bTurn && m_bCurUp )
  568. { // 反转向下
  569. if( pnCode ) *pnCode = ITSC_SHORT;
  570. return m_itsSell;
  571. }
  572. return ITS_NOTHING;
  573. }
  574. BOOL CSAR::GetMinMaxInfo(int nStart, int nEnd,
  575.    double *pdMin, double *pdMax )
  576. {
  577. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  578. }
  579. /***
  580. 计算SAR值
  581. 先选定时间,判断价格是在上涨还是在下跌。
  582. 若是看涨,则进场第一天的SAR必须是近期内的最低价,是看跌 则进场第一天的SAR必须是近期内的最高价。
  583. 本处为缺省定义为看涨。
  584. 进场第二天的SAR则为第一天的最高价(看涨时)或最低价(看跌时)与第一天的SAR的差距乘上调整系数,
  585. 再加上第一天的SAR就可求得。
  586. 按逐步递推的方法,每日的SAR可归纳如下: SAR(N)= SAR(N-1)+ AF * [ EP(N-1)-SAR(N-1)]
  587. 其中SAR(N)为第N日的SAR值,AF是调整系数,EP为极点价
  588. 第一个调整系数AF为0.02,若每隔一天的最高价比前一天的最高价还高,则AF递增0.02,若未创新高,
  589. 则AF沿用前一天的数值,但调整系数最高不超过0.2。
  590. 若是买进期间,计算出某日的SAR比当日或前一日的最低价还高,则应以当日或者前一日的最低价为某日之SAR,
  591. 卖出期间也对应服从类似原则。
  592. */
  593. BOOL CSAR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  594. {
  595. if( LoadFromCache( nIndex, pValue ) )
  596. return TRUE;
  597. if( bUseLast && pValue && nIndex > 0 )
  598. {
  599. if( CalculateSAR( pValue, nIndex, bUseLast ) )
  600. {
  601. StoreToCache( nIndex, pValue );
  602. return TRUE;
  603. }
  604. return FALSE;
  605. }
  606. else
  607. {
  608. double dResult;
  609. BOOL bHasLast = FALSE;
  610. for( int k=0; k<=nIndex; k++ )
  611. {
  612. if( CalculateSAR( &dResult, k, bHasLast ) )
  613. {
  614. bHasLast = TRUE;
  615. StoreToCache( k, &dResult );
  616. }
  617. }
  618. if( !bHasLast )
  619. return FALSE;
  620. if( pValue )
  621. *pValue = dResult;
  622. return TRUE;
  623. }
  624. }
  625. //////////////////////////////////////////////////////////////////////
  626. // CDJ
  627. CStock CDJ::m_stockSha;
  628. CStock CDJ::m_stockSzn;
  629. CSPString CDJ::m_strCodeOrg;
  630. CDJ::CDJ( )
  631. {
  632. SetDefaultParameters( );
  633. }
  634. CDJ::CDJ( CKData * pKData )
  635. : CTechnique( pKData )
  636. {
  637. SetDefaultParameters( );
  638. }
  639. CDJ::~CDJ()
  640. {
  641. Clear( );
  642. }
  643. void CDJ::SetDefaultParameters( )
  644. {
  645. m_strCodeSha = STKLIB_CODE_MAIN;
  646. m_strCodeSzn = STKLIB_CODE_MAINSZN;
  647. }
  648. void CDJ::AttachParameters( CDJ & src )
  649. {
  650. m_strCodeSha = src.m_strCodeSha;
  651. m_strCodeSzn = src.m_strCodeSzn;
  652. }
  653. BOOL CDJ::IsValidParameters( )
  654. {
  655. return ( m_strCodeSha.GetLength() > 0 && m_strCodeSzn.GetLength() > 0 );
  656. }
  657. void CDJ::Clear( )
  658. {
  659. CTechnique::Clear( );
  660. }
  661. /***
  662. K线叠加图,准备叠加K线的数据
  663. */
  664. BOOL CDJ::PrepareStockData(CStDatabase * pDatabase, const char * szCodeOrg,
  665.    int nCurKType, int nCurKFormat, int nCurMaindataType,
  666.    DWORD dwAutoResumeDRBegin, int nAutoResumeDRLimit )
  667. {
  668. SP_ASSERT( pDatabase );
  669. // bReload and kdayMain
  670. BOOL bReload = (NULL!=szCodeOrg && 0!=strncmp(szCodeOrg,m_strCodeOrg,m_strCodeOrg.GetLength()) );
  671. m_strCodeOrg = szCodeOrg;
  672. // m_stockSha
  673. m_stockSha.SetStockCode( CStock::marketSHSE, m_strCodeSha );
  674. AfxPrepareStockData( pDatabase, m_stockSha, nCurKType, nCurKFormat, nCurMaindataType, FALSE, bReload );
  675. // m_stockSzn
  676. m_stockSzn.SetStockCode( CStock::marketSZSE, m_strCodeSzn );
  677. AfxPrepareStockData( pDatabase, m_stockSzn, nCurKType, nCurKFormat, nCurMaindataType, FALSE, bReload );
  678. return TRUE;
  679. }
  680. //////////////////////////////////////////////////////////////////////
  681. // CCW
  682. CCW::CCW( )
  683. {
  684. SetDefaultParameters( );
  685. }
  686. CCW::CCW( CKData * pKData )
  687. : CTechnique( pKData )
  688. {
  689. SetDefaultParameters( );
  690. }
  691. CCW::~CCW()
  692. {
  693. Clear( );
  694. }
  695. void CCW::SetDefaultParameters( )
  696. {
  697. m_dChangeHand = 1.5;
  698. }
  699. void CCW::AttachParameters( CCW & src )
  700. {
  701. m_dChangeHand = src.m_dChangeHand;
  702. }
  703. BOOL CCW::IsValidParameters( )
  704. {
  705. return ( m_dChangeHand > 0 );
  706. }
  707. void CCW::Clear( )
  708. {
  709. CTechnique::Clear( );
  710. }
  711. /***
  712. 根据换手率m_dChangeHand和终止日,计算起始日
  713. */
  714. BOOL CCW::GetRange( int & nStart, int & nEnd, CStockInfo & info )
  715. {
  716. if( !m_pKData || m_pKData->GetSize() <= 0 )
  717. return FALSE;
  718. if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
  719. nEnd = m_pKData->GetSize()-1;
  720. BOOL bIndex = FALSE;
  721. double dShareCurrency = 0;
  722. if( !info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6 )
  723. bIndex = TRUE;
  724. if( bIndex )
  725. dShareCurrency = 100 * m_dChangeHand;
  726. else
  727. dShareCurrency *= m_dChangeHand;
  728. double dVol = 0;
  729. for( int k=nEnd; k>=0; k-- )
  730. {
  731. if( bIndex )
  732. dVol += 1;
  733. else
  734. dVol += m_pKData->ElementAt(k).m_fVolume;
  735. if( dVol > dShareCurrency )
  736. break;
  737. }
  738. nStart = k;
  739. if( nStart < 0 )
  740. nStart = 0;
  741. return TRUE;
  742. }
  743. BOOL CCW::GetMinMaxInfo(int nStart, int nEnd, double dMinPrice, double dMaxPrice, double dStep,
  744. double *pdMinVolume, double *pdMaxVolume )
  745. {
  746. STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
  747. if( dMinPrice >= dMaxPrice || dStep < 1e-4 )
  748. return FALSE;
  749. double dMinVolume = 0, dMaxVolume = 0, dVolume = 0;
  750. BOOL bFirst = TRUE;
  751. for( double dPrice = dMinPrice; dPrice < dMaxPrice; dPrice += dStep )
  752. {
  753. if( CalculateCW( &dVolume, nStart, nEnd, dPrice, dStep ) )
  754. {
  755. if( bFirst || dVolume < dMinVolume ) dMinVolume = dVolume;
  756. if( bFirst || dVolume > dMaxVolume ) dMaxVolume = dVolume;
  757. bFirst = FALSE;
  758. }
  759. }
  760. dMinVolume -= fabs(dMinVolume)*0.01;
  761. dMaxVolume += fabs(dMaxVolume)*0.01;
  762. if( dMaxVolume - dMinVolume < 3 )
  763. dMaxVolume = dMinVolume + 3;
  764. if( pdMinVolume ) *pdMinVolume = dMinVolume;
  765. if( pdMaxVolume ) *pdMaxVolume = dMaxVolume;
  766. return !bFirst;
  767. }
  768. /***
  769. 筹码分布图,计算价格区间包括dPrice的日线的成交量
  770. */
  771. BOOL CCW::CalculateCW( double *pdVolume, int nStart, int nEnd, double dPrice, double dStep )
  772. {
  773. STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
  774. double dVolume = 0;
  775. for( int k=nStart; k<=nEnd; k++ )
  776. {
  777. KDATA kd = m_pKData->ElementAt(k);
  778. if( kd.m_fHigh-kd.m_fLow > 1e-4
  779. && kd.m_fLow < dPrice && kd.m_fHigh > dPrice )
  780. {
  781. // 均匀分布 dVolAve
  782. double dVolAve = kd.m_fVolume;
  783. if( dStep < kd.m_fHigh-kd.m_fLow )
  784. dVolAve = kd.m_fVolume * dStep / (kd.m_fHigh-kd.m_fLow);
  785. // 三角分布
  786. double dFactor = min(dPrice-kd.m_fLow, kd.m_fHigh-dPrice);
  787. dVolume += dVolAve * dFactor * 4 / (kd.m_fHigh-kd.m_fLow);
  788. }
  789. }
  790. if( pdVolume )
  791. *pdVolume = dVolume;
  792. return TRUE;
  793. }
  794. /***
  795. 筹码分布图计算,计算筹码分布
  796. */
  797. BOOL CCW::CalculateCW( int nStart, int nEnd, CStockInfo & info, double dStep,
  798. CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
  799. double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
  800. {
  801. STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
  802. if( dStep < 1e-4 )
  803. return FALSE;
  804. float dMinPrice = 0, dMaxPrice = 0;
  805. if( !m_pKData->GetMinMaxInfo( nStart, nEnd, &dMinPrice, &dMaxPrice ) )
  806. return FALSE;
  807. // Calculate
  808. int nMaxCount = (int)((dMaxPrice-dMinPrice)/dStep) + 10;
  809. adwPrice.SetSize( 0, nMaxCount );
  810. adwVolume.SetSize( 0, nMaxCount );
  811. double dMinVolume = 0, dMaxVolume = 0, dTotalVolume = 0, dVolume = 0;
  812. BOOL bFirst = TRUE;
  813. for( double dPrice = dMinPrice; dPrice < dMaxPrice; dPrice += dStep )
  814. {
  815. if( CalculateCW( &dVolume, nStart, nEnd, dPrice, dStep ) )
  816. {
  817. if( bFirst || dVolume < dMinVolume ) dMinVolume = dVolume;
  818. if( bFirst || dVolume > dMaxVolume ) dMaxVolume = dVolume;
  819. adwPrice.Add( DWORD(dPrice * 1000) );
  820. adwVolume.Add( DWORD(dVolume) );
  821. dTotalVolume += dVolume;
  822. bFirst = FALSE;
  823. }
  824. }
  825. // Return
  826. // Min Max
  827. dMinVolume -= fabs(dMinVolume)*0.01;
  828. dMaxVolume += fabs(dMaxVolume)*0.01;
  829. if( dMaxVolume - dMinVolume < 3 )
  830. dMaxVolume = dMinVolume + 3;
  831. if( pdMinVolume ) *pdMinVolume = dMinVolume;
  832. if( pdMaxVolume ) *pdMaxVolume = dMaxVolume;
  833. if( pdTotalVolume ) *pdTotalVolume = dTotalVolume;
  834. // VolPercent
  835. double dVolPercent = 1.0;
  836. double dShareCurrency = 0;
  837. if( (!info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6) && nEnd-nStart+1 > 0 )
  838. dShareCurrency = dTotalVolume * 100 / (nEnd-nStart+1);
  839. if( dShareCurrency > 1e-4 )
  840. dVolPercent = dTotalVolume / (dShareCurrency*m_dChangeHand);
  841. if( dVolPercent > 1.0 ) dVolPercent = 1.0;
  842. if( dVolPercent < 0.0 ) dVolPercent = 0.0;
  843. if( pdVolPercent ) *pdVolPercent = dVolPercent;
  844. return adwPrice.GetSize() > 0;
  845. }
  846. /***
  847. 筹码分布图计算,计算最近nDays天内的筹码分布
  848. */
  849. BOOL CCW::CalculateRecentCW(int nEnd, int nDays, CStockInfo & info, double dStep,
  850. CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
  851. double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
  852. {
  853. // Prepare
  854. if( !m_pKData || m_pKData->GetSize() <= 0 )
  855. return FALSE;
  856. if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
  857. nEnd = m_pKData->GetSize()-1;
  858. int nStart = nEnd - nDays + 1;
  859. if( nStart < 0 || nStart >= m_pKData->GetSize() )
  860. return FALSE;
  861. return CalculateCW( nStart, nEnd, info, dStep, adwPrice, adwVolume, pdMinVolume, pdMaxVolume, pdTotalVolume, pdVolPercent );
  862. }
  863. /***
  864. 筹码分布图计算,计算nDays天前内的筹码分布
  865. */
  866. BOOL CCW::CalculatePastCW(int nEnd, int nDays, CStockInfo & info, double dStep,
  867. CSPDWordArray & adwPrice, CSPDWordArray & adwVolume,
  868. double * pdMinVolume, double * pdMaxVolume, double * pdTotalVolume, double * pdVolPercent )
  869. {
  870. // Prepare
  871. if( !m_pKData || m_pKData->GetSize() <= 0 )
  872. return FALSE;
  873. if( nEnd < 0 || nEnd >= m_pKData->GetSize() )
  874. nEnd = m_pKData->GetSize()-1;
  875. int nStart = nEnd - nDays;
  876. if( nStart < 0 || nStart >= m_pKData->GetSize() )
  877. return FALSE;
  878. nEnd = nStart;
  879. if( !GetRange( nStart, nEnd, info ) )
  880. return FALSE;
  881. BOOL bOK = CalculateCW( nStart, nEnd, info, dStep, adwPrice, adwVolume, pdMinVolume, pdMaxVolume, pdTotalVolume, pdVolPercent );
  882. // TotalVolumeRecent
  883. double dTotalVolumeRecent = 0;
  884. for( int k=nEnd+1; k<=nEnd+nDays && k<m_pKData->GetSize(); k ++ )
  885. dTotalVolumeRecent += m_pKData->ElementAt(k).m_fVolume;
  886. // VolPercent
  887. double dVolPercent = 1.0;
  888. double dShareCurrency = 0;
  889. if( (!info.GetShareCurrency( &dShareCurrency ) || dShareCurrency < 1e+6) && nDays > 0 )
  890. dShareCurrency = dTotalVolumeRecent * 100 / nDays;
  891. if( dShareCurrency > 1e-4 )
  892. dVolPercent = dTotalVolumeRecent / (dShareCurrency*m_dChangeHand);
  893. dVolPercent = 1.0 - dVolPercent;
  894. if( dVolPercent > 1.0 ) dVolPercent = 1.0;
  895. if( dVolPercent < 0.0 ) dVolPercent = 0.0;
  896. if( pdVolPercent ) *pdVolPercent = dVolPercent;
  897. return bOK;
  898. }
  899. /***
  900. 筹码分布图统计,获利比例统计
  901. */
  902. BOOL CCW::StatGainPercent( double *pdGainPercent, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume, double dPriceSel )
  903. {
  904. double dTotalVolume = 0;
  905. double dGainVolume = 0;
  906. for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
  907. {
  908. dTotalVolume += adwVolume[k];
  909. if( adwPrice[k] * 0.001 <= dPriceSel )
  910. dGainVolume += adwVolume[k];
  911. }
  912. double dGainPercent = 0;
  913. if( dTotalVolume > 1e-4 )
  914. dGainPercent = dGainVolume / dTotalVolume;
  915. if( pdGainPercent ) *pdGainPercent = dGainPercent;
  916. return TRUE;
  917. }
  918. /***
  919. 筹码分布图统计,平均成本统计
  920. */
  921. BOOL CCW::StatCostAverage( double *pdCostAve, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume )
  922. {
  923. double dTotalVolume = 0;
  924. double dTotalCost = 0;
  925. for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
  926. {
  927. dTotalVolume += adwVolume[k];
  928. dTotalCost += 0.001 * adwPrice[k] * adwVolume[k];
  929. }
  930. double dCostAve = 0;
  931. if( dTotalVolume > 1e-4 )
  932. dCostAve = dTotalCost / dTotalVolume;
  933. if( pdCostAve ) *pdCostAve = dCostAve;
  934. return TRUE;
  935. }
  936. /***
  937. 筹码分布图统计,集中度统计
  938. */
  939. BOOL CCW::StatMass( double *pdLower, double *pdUpper, double *pdMassPrice, CSPDWordArray &adwPrice, CSPDWordArray &adwVolume, double dMassVol )
  940. {
  941. if( adwPrice.GetSize() != adwVolume.GetSize() || dMassVol < 0 || dMassVol > 1 )
  942. return FALSE;
  943. double dTotalVolume = 0;
  944. for( int k=0; k<adwPrice.GetSize() && k<adwVolume.GetSize(); k++ )
  945. dTotalVolume += adwVolume[k];
  946. if( dTotalVolume > 1e-4 )
  947. {
  948. double dUpperVolume = dTotalVolume * (1-dMassVol) * 0.5;
  949. double dLowerVolume = dUpperVolume;
  950. int nLower = 0, nUpper = adwPrice.GetSize()-1;
  951. for( k=0; k<adwPrice.GetSize(); k++ )
  952. {
  953. dLowerVolume -= (double)adwVolume[k];
  954. if( dLowerVolume < 0 )
  955. break;
  956. }
  957. nLower = k;
  958. for( k=adwPrice.GetSize()-1; k>=0; k-- )
  959. {
  960. dUpperVolume -= (double)adwVolume[k];
  961. if( dUpperVolume < 0 )
  962. break;
  963. }
  964. nUpper = k;
  965. if( nLower < 0 || nLower > nUpper || nUpper >= adwPrice.GetSize() )
  966. return FALSE;
  967. double dLower = 0.001 * adwPrice[nLower];
  968. double dUpper = 0.001 * adwPrice[nUpper];
  969. if( pdLower ) *pdLower = dLower;
  970. if( pdUpper ) *pdUpper = dUpper;
  971. if( pdMassPrice && adwPrice.GetSize() >= 2 )
  972. {
  973. double dPriceRange = 0.001 * ((double)adwPrice[adwPrice.GetSize()-1] - (double)adwPrice[0]);
  974. if( dPriceRange > 1e-4 )
  975. *pdMassPrice = (dUpper-dLower)/dPriceRange;
  976. if( *pdMassPrice < 0 ) *pdMassPrice = 0;
  977. if( *pdMassPrice > 1 ) *pdMassPrice = 1;
  978. }
  979. }
  980. return TRUE;
  981. }