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

金融证券系统

开发平台:

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. // CKDJ
  18. CKDJ::CKDJ( )
  19. {
  20. SetDefaultParameters( );
  21. }
  22. CKDJ::CKDJ( CKData * pKData )
  23. : CTechnique( pKData )
  24. {
  25. SetDefaultParameters( );
  26. }
  27. CKDJ::~CKDJ()
  28. {
  29. Clear( );
  30. }
  31. void CKDJ::SetDefaultParameters( )
  32. {
  33. m_nRSVDays = 9;
  34. m_nKDays = 3;
  35. m_nDDays = 3;
  36. m_nJ = 1;
  37. m_itsGoldenFork = ITS_BUY;
  38. m_itsDeadFork = ITS_SELL;
  39. }
  40. void CKDJ::AttachParameters( CKDJ & src )
  41. {
  42. m_nRSVDays = src.m_nRSVDays;
  43. m_nKDays = src.m_nKDays;
  44. m_nDDays = src.m_nDDays;
  45. m_nJ = src.m_nJ;
  46. m_itsGoldenFork = src.m_itsGoldenFork;
  47. m_itsDeadFork = src.m_itsDeadFork;
  48. }
  49. BOOL CKDJ::IsValidParameters( )
  50. {
  51. return ( VALID_DAYS(m_nRSVDays) && VALID_DAYS(m_nKDays)
  52. && VALID_DAYS(m_nDDays) && VALID_DAYS(m_nJ)
  53. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  54. }
  55. void CKDJ::Clear( )
  56. {
  57. CTechnique::Clear( );
  58. }
  59. // 计算RSV值
  60. BOOL CKDJ::CalculateRSV( double * pValue, int nIndex )
  61. {
  62. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  63. double dH = 0, dL = 0, dRSV = 0;
  64. int nCount = 0;
  65. for( int k=nIndex; k>=0; k-- )
  66. {
  67. if( nIndex == k )
  68. {
  69. dH = m_pKData->ElementAt(k).m_fHigh;
  70. dL = m_pKData->ElementAt(k).m_fLow;
  71. }
  72. if( dH < m_pKData->ElementAt(k).m_fHigh )
  73. dH = m_pKData->ElementAt(k).m_fHigh;
  74. if( dL > m_pKData->ElementAt(k).m_fLow )
  75. dL = m_pKData->ElementAt(k).m_fLow;
  76. nCount ++;
  77. if( nCount == m_nRSVDays )
  78. {
  79. if( dH-dL < 1e-4 )
  80. dRSV = 100;
  81. else
  82. dRSV = (m_pKData->ElementAt(nIndex).m_fClose - dL) * 100 / (dH - dL);
  83. if( pValue ) *pValue = dRSV;
  84. return TRUE;
  85. }
  86. }
  87. return FALSE;
  88. }
  89. int CKDJ::GetSignal( int nIndex, UINT * pnCode )
  90. {
  91. if( pnCode ) *pnCode = ITSC_NOTHING;
  92. if( !PrepareCache( 0, -1, FALSE ) )
  93. return ITS_NOTHING;
  94. double dK, dD, dJ;
  95. if( !Calculate( &dK, &dD, &dJ, nIndex, FALSE ) )
  96. return ITS_NOTHING;
  97. if( dK < 25 && dD < 25 && IsGoldenFork(nIndex, m_pdCache1, m_pdCache2) )
  98. { // 低位金叉
  99. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  100. return m_itsGoldenFork;
  101. }
  102. if( dK > 75 && dD > 75 && IsDeadFork(nIndex, m_pdCache1, m_pdCache2) )
  103. { // 高位死叉
  104. if( pnCode ) *pnCode = ITSC_DEADFORK;
  105. return m_itsDeadFork;
  106. }
  107. return ITS_NOTHING;
  108. }
  109. BOOL CKDJ::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  110. {
  111. return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
  112. }
  113. /***
  114. AX = 今天的收盘价 - N天中的最低价
  115. BX = N天中的最高价 - N天中的最低价
  116. RSV = (AX ÷ BX)× 100%
  117. NK = K计算天数,一般取3
  118. ND = D计算天数,一般取3
  119. K = 前一日K×(NK-1)/NK + RSV×1/NK 
  120. D = 前一日D×(ND-1)/ND + K×1/3
  121. J = 3D - 2K (或 J = 3K - 2D)
  122. 第一次计算时,前一日的K、D值皆以50代替。
  123. */
  124. BOOL CKDJ::Calculate( double *pValue1, double *pValue2, double *pValue3, int nIndex, BOOL bUseLast )
  125. {
  126. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  127. if( m_nRSVDays > nIndex+1 )
  128. return FALSE;
  129. if( LoadFromCache( nIndex, pValue1, pValue2, pValue3 ) )
  130. return TRUE;
  131. double dRSV = 0;
  132. double dK = 50, dD = 50, dJ = 50;
  133. if( bUseLast && pValue1 && pValue2 )
  134. {
  135. if( CalculateRSV( &dRSV, nIndex ) )
  136. {
  137. dK = (m_nKDays-1)*(*pValue1)/m_nKDays + dRSV/m_nKDays;
  138. dD = (m_nDDays-1)*(*pValue2)/m_nDDays + dK/m_nDDays;
  139. if( mode3K2D == m_nJ )
  140. dJ = 3 * dK - 2 * dD;
  141. else
  142. dJ = 3 * dD - 2 * dK;
  143. if( pValue1 ) *pValue1 = dK;
  144. if( pValue2 ) *pValue2 = dD;
  145. if( pValue3 ) *pValue3 = dJ;
  146. StoreToCache( nIndex, pValue1, pValue2, pValue3 );
  147. return TRUE;
  148. }
  149. }
  150. else
  151. {
  152. double factor1 = 1, factor2 = 1;
  153. for( int k=nIndex; k > 0; k-- )
  154. {
  155. factor1 *= ((double)(m_nKDays-1))/m_nKDays;
  156. factor2 *= ((double)(m_nDDays-1))/m_nDDays;
  157. if( factor1 < 0.001 && factor2 < 0.001 )
  158. break;
  159. }
  160. for( ; k<=nIndex; k++ )
  161. {
  162. if( CalculateRSV( &dRSV, k ) )
  163. {
  164. dK = (m_nKDays-1)*(dK)/m_nKDays + dRSV/m_nKDays;
  165. dD = (m_nDDays-1)*(dD)/m_nDDays + dK/m_nDDays;
  166. if( mode3K2D == m_nJ )
  167. dJ = 3 * dK - 2 * dD;
  168. else
  169. dJ = 3 * dD - 2 * dK;
  170. if( nIndex == k )
  171. {
  172. if( pValue1 ) *pValue1 = dK;
  173. if( pValue2 ) *pValue2 = dD;
  174. if( pValue3 ) *pValue3 = dJ;
  175. StoreToCache( nIndex, pValue1, pValue2, pValue3 );
  176. return TRUE;
  177. }
  178. }
  179. }
  180. }
  181. return FALSE;
  182. }
  183. //////////////////////////////////////////////////////////////////////
  184. // CR
  185. CR::CR( )
  186. {
  187. SetDefaultParameters( );
  188. }
  189. CR::CR( CKData * pKData )
  190. : CTechnique( pKData )
  191. {
  192. SetDefaultParameters( );
  193. }
  194. CR::~CR()
  195. {
  196. Clear( );
  197. }
  198. void CR::SetDefaultParameters( )
  199. {
  200. m_nDays = 20;
  201. }
  202. void CR::AttachParameters( CR & src )
  203. {
  204. m_nDays = src.m_nDays;
  205. }
  206. BOOL CR::IsValidParameters( )
  207. {
  208. return ( VALID_DAYS(m_nDays) );
  209. }
  210. void CR::Clear( )
  211. {
  212. CTechnique::Clear( );
  213. }
  214. int CR::GetSignal( int nIndex, UINT * pnCode )
  215. {
  216. if( pnCode ) *pnCode = ITSC_NOTHING;
  217. /* double dR;
  218. if( !Calculate( &dR, nIndex, FALSE ) )
  219. return ITS_NOTHING;
  220. if( dR > 80 )
  221. {
  222. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  223. return m_itsSold;
  224. }
  225. if( dR < 20 )
  226. {
  227. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  228. return m_itsBought;
  229. }
  230. */
  231. // 无买卖信号
  232. return ITS_NOTHING;
  233. }
  234. BOOL CR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  235. {
  236. if( pdMin ) *pdMin = 0;
  237. if( pdMax ) *pdMax = 100;
  238. return TRUE;
  239. }
  240. /***
  241.             H - C
  242. W%R指标值= ———— ×100
  243.             H - L                
  244. H = N日内最高价 L = N日内最低价 C = 当天收盘价
  245. */
  246. BOOL CR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  247. {
  248. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  249. if( m_nDays > nIndex+1 )
  250. return FALSE;
  251. if( LoadFromCache( nIndex, pValue ) )
  252. return TRUE;
  253. double dH = 0, dL = 0, dR = 0;
  254. int nCount = 0;
  255. for( int k=nIndex; k>=0; k-- )
  256. {
  257. if( nIndex == k )
  258. {
  259. dH = m_pKData->ElementAt(k).m_fHigh;
  260. dL = m_pKData->ElementAt(k).m_fLow;
  261. }
  262. if( dH < m_pKData->ElementAt(k).m_fHigh )
  263. dH = m_pKData->ElementAt(k).m_fHigh;
  264. if( dL > m_pKData->ElementAt(k).m_fLow )
  265. dL = m_pKData->ElementAt(k).m_fLow;
  266. nCount ++;
  267. if( nCount == m_nDays )
  268. {
  269. if( dH-dL < 1e-4 )
  270. dR = 100;
  271. else
  272. dR = (dH - m_pKData->ElementAt(nIndex).m_fClose) * 100 / (dH - dL);
  273. if( pValue ) *pValue = dR;
  274. StoreToCache( nIndex, pValue );
  275. return TRUE;
  276. }
  277. }
  278. return FALSE;
  279. }
  280. //////////////////////////////////////////////////////////////////////
  281. // CRSI
  282. CRSI::CRSI( )
  283. {
  284. SetDefaultParameters( );
  285. }
  286. CRSI::CRSI( CKData * pKData )
  287. : CTechnique( pKData )
  288. {
  289. SetDefaultParameters( );
  290. }
  291. CRSI::~CRSI()
  292. {
  293. Clear( );
  294. }
  295. void CRSI::SetDefaultParameters( )
  296. {
  297. m_adwDays.RemoveAll();
  298. m_adwDays.Add( 10 );
  299. m_adwDays.Add( 20 );
  300. m_itsSold = ITS_BUY;
  301. m_itsGoldenFork = ITS_BUYINTENSE;
  302. m_itsDeadFork = ITS_SELLINTENSE;
  303. }
  304. void CRSI::AttachParameters( CRSI & src )
  305. {
  306. m_adwDays.Copy( src.m_adwDays );
  307. m_itsSold = src.m_itsSold;
  308. m_itsGoldenFork = src.m_itsGoldenFork;
  309. m_itsDeadFork = src.m_itsDeadFork;
  310. }
  311. BOOL CRSI::IsValidParameters( )
  312. {
  313. STT_VALID_DAYSARRAY( m_adwDays );
  314. return ( VALID_ITS(m_itsSold) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  315. }
  316. void CRSI::Clear( )
  317. {
  318. CTechnique::Clear( );
  319. }
  320. int CRSI::GetSignal( int nIndex, UINT * pnCode )
  321. {
  322. if( pnCode ) *pnCode = ITSC_NOTHING;
  323. if( nIndex <= 0 )
  324. return ITS_NOTHING;
  325. int nForkSignal = GetForkSignal(nIndex, m_adwDays, m_itsGoldenFork, m_itsDeadFork, pnCode );
  326. for( int k=0; k<m_adwDays.GetSize(); k++ )
  327. {
  328. double dRSI, dRSILast;
  329. if( !Calculate( &dRSILast, nIndex-1, m_adwDays[k], FALSE )
  330. || !Calculate( &dRSI, nIndex, m_adwDays[k], FALSE ) )
  331. return ITS_NOTHING;
  332. if( dRSI < 20 )
  333. { // 超卖
  334. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  335. return m_itsSold;
  336. }
  337. if( dRSI < 40 && nForkSignal == m_itsGoldenFork )
  338. { // 低位金叉
  339. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  340. return m_itsGoldenFork;
  341. }
  342. if( dRSI > 60 && nForkSignal == m_itsDeadFork )
  343. { // 高位死叉
  344. if( pnCode ) *pnCode = ITSC_DEADFORK;
  345. return m_itsDeadFork;
  346. }
  347. }
  348. return ITS_NOTHING;
  349. }
  350. BOOL CRSI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  351. {
  352. if( pdMin ) *pdMin = 0;
  353. if( pdMax ) *pdMax = 100;
  354. return TRUE;
  355. }
  356. /***
  357. RSI =(N日内上涨幅度累计÷N日内上涨及下跌幅度累计)×100%
  358. */
  359. BOOL CRSI::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
  360. {
  361. STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
  362. if( nDays > nIndex )
  363. return FALSE;
  364. double dUC = 0, dDC = 0, dRSI = 0;
  365. int nCount = 0;
  366. for( int k=nIndex; k>=1; k-- )
  367. {
  368. if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) )
  369. dUC += ( m_pKData->MaindataAt(k) - m_pKData->MaindataAt(k-1) );
  370. else
  371. dDC += ( m_pKData->MaindataAt(k-1) - m_pKData->MaindataAt(k) );
  372. nCount ++;
  373. if( nCount == nDays )
  374. {
  375. if( dUC+dDC < 1e-4 )
  376. dRSI = 100;
  377. else
  378. dRSI = 100*dUC/(dUC+dDC);
  379. if( pValue ) *pValue = dRSI;
  380. return TRUE;
  381. }
  382. }
  383. return FALSE;
  384. }
  385. //////////////////////////////////////////////////////////////////////
  386. // CBIAS
  387. CBIAS::CBIAS( )
  388. {
  389. SetDefaultParameters( );
  390. }
  391. CBIAS::CBIAS( CKData * pKData )
  392. : CTechnique( pKData )
  393. {
  394. SetDefaultParameters( );
  395. }
  396. CBIAS::~CBIAS()
  397. {
  398. Clear( );
  399. }
  400. void CBIAS::SetDefaultParameters( )
  401. {
  402. m_nDays = 10;
  403. m_itsSold = ITS_BUY;
  404. m_itsBought = ITS_SELL;
  405. }
  406. void CBIAS::AttachParameters( CBIAS & src )
  407. {
  408. m_nDays = src.m_nDays;
  409. m_itsSold = src.m_itsSold;
  410. m_itsBought = src.m_itsBought;
  411. }
  412. BOOL CBIAS::IsValidParameters( )
  413. {
  414. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  415. }
  416. void CBIAS::Clear( )
  417. {
  418. CTechnique::Clear( );
  419. }
  420. int CBIAS::GetSignal( int nIndex, UINT * pnCode )
  421. {
  422. if( pnCode ) *pnCode = ITSC_NOTHING;
  423. double dBIAS;
  424. if( !Calculate( &dBIAS, nIndex, FALSE ) )
  425. return ITS_NOTHING;
  426. if( dBIAS < -10 )
  427. { // 超卖
  428. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  429. return m_itsSold;
  430. }
  431. if( dBIAS > 5 )
  432. { // 超买
  433. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  434. return m_itsBought;
  435. }
  436. return ITS_NOTHING;
  437. }
  438. BOOL CBIAS::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  439. {
  440. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  441. }
  442. /***
  443.               当日收盘价-N日移动平均值
  444. N日乖离率 = —————————————— ×100%
  445.                    N日移动平均值
  446. */
  447. BOOL CBIAS::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  448. {
  449. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  450. if( m_nDays > nIndex+1 )
  451. return FALSE;
  452. if( LoadFromCache( nIndex, pValue ) )
  453. return TRUE;
  454. double dMA = 0;
  455. int nCount = 0;
  456. for( int k=nIndex; k>=0; k -- )
  457. {
  458. dMA += m_pKData->MaindataAt(k);
  459. nCount ++;
  460. if( nCount == m_nDays )
  461. {
  462. double dResult = 0;
  463. dMA = dMA / m_nDays;
  464. if( dMA > 1e-4 )
  465. dResult = 100. * ( m_pKData->MaindataAt(nIndex) - dMA ) / dMA;
  466. if( pValue ) *pValue = dResult;
  467. StoreToCache( nIndex, pValue );
  468. return TRUE;
  469. }
  470. }
  471. return FALSE;
  472. }
  473. //////////////////////////////////////////////////////////////////////
  474. // CMTM
  475. CMTM::CMTM( )
  476. {
  477. SetDefaultParameters( );
  478. }
  479. CMTM::CMTM( CKData * pKData )
  480. : CTechnique( pKData )
  481. {
  482. SetDefaultParameters( );
  483. }
  484. CMTM::~CMTM()
  485. {
  486. Clear( );
  487. }
  488. void CMTM::SetDefaultParameters( )
  489. {
  490. m_nDays = 10;
  491. m_nMADays = 10;
  492. m_itsGoldenFork = ITS_BUY;
  493. m_itsDeadFork = ITS_SELL;
  494. }
  495. void CMTM::AttachParameters( CMTM & src )
  496. {
  497. m_nDays = m_nDays;
  498. m_nMADays = m_nMADays;
  499. m_itsGoldenFork = src.m_itsGoldenFork;
  500. m_itsDeadFork = src.m_itsDeadFork;
  501. }
  502. BOOL CMTM::IsValidParameters( )
  503. {
  504. return ( VALID_DAYS( m_nDays ) && VALID_DAYS( m_nMADays )
  505. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  506. }
  507. void CMTM::Clear( )
  508. {
  509. CTechnique::Clear( );
  510. }
  511. int CMTM::GetSignal( int nIndex, UINT * pnCode )
  512. {
  513. if( pnCode ) *pnCode = ITSC_NOTHING;
  514. int nMaxDays = m_nDays + m_nMADays;
  515. double dLiminalLow = 0, dLiminalHigh = 0;
  516. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.3, 0.6 ) )
  517. return ITS_NOTHING;
  518. double dMTM, dMA;
  519. if( !Calculate( &dMTM, &dMA, nIndex, FALSE ) )
  520. return ITS_NOTHING;
  521. if( dMTM < dLiminalLow && dMA < dLiminalLow && IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) )
  522. { // 低位金叉
  523. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  524. return m_itsGoldenFork;
  525. }
  526. if( dMTM > dLiminalHigh && dMA > dLiminalHigh && IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) )
  527. { // 高位死叉
  528. if( pnCode ) *pnCode = ITSC_DEADFORK;
  529. return m_itsDeadFork;
  530. }
  531. return ITS_NOTHING;
  532. }
  533. BOOL CMTM::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  534. {
  535. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  536. }
  537. /***
  538. MTM = C/Cn
  539. 其中:C为当日收市价,Cn为N日前收市价,
  540. N为设定参数,一般选设10日,亦可在6日至14日之间选择。
  541. */
  542. BOOL CMTM::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  543. {
  544. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  545. if( m_nDays > nIndex )
  546. return FALSE;
  547. if( LoadFromCache( nIndex, pValue ) )
  548. return TRUE;
  549. if( m_pKData->MaindataAt(nIndex-m_nDays) > 0 )
  550. {
  551. if( pValue )
  552. *pValue = 100. * m_pKData->MaindataAt(nIndex) / m_pKData->MaindataAt(nIndex-m_nDays);
  553. StoreToCache( nIndex, pValue );
  554. return TRUE;
  555. }
  556. return FALSE;
  557. }
  558. BOOL CMTM::Calculate( double * pValue, double *pMA, int nIndex, BOOL bUseLast )
  559. {
  560. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  561. }
  562. //////////////////////////////////////////////////////////////////////
  563. // CDMI
  564. CDMI::CDMI( )
  565. {
  566. SetDefaultParameters( );
  567. m_pdDMICache = NULL;
  568. m_pnDMICacheIndex = NULL;
  569. m_nDMICacheCurrent = -1;
  570. }
  571. CDMI::CDMI( CKData * pKData )
  572. : CTechnique( pKData )
  573. {
  574. SetDefaultParameters( );
  575. m_pdDMICache = NULL;
  576. m_pnDMICacheIndex = NULL;
  577. m_nDMICacheCurrent = -1;
  578. }
  579. CDMI::~CDMI()
  580. {
  581. Clear( );
  582. }
  583. void CDMI::SetDefaultParameters( )
  584. {
  585. m_nDays = 7;
  586. }
  587. void CDMI::AttachParameters( CDMI & src )
  588. {
  589. m_nDays = src.m_nDays;
  590. }
  591. BOOL CDMI::IsValidParameters( )
  592. {
  593. return ( VALID_DAYS(m_nDays) );
  594. }
  595. void CDMI::Clear( )
  596. {
  597. CTechnique::Clear( );
  598. if( m_pdDMICache )
  599. {
  600. delete [] m_pdDMICache;
  601. m_pdDMICache = NULL;
  602. }
  603. if( m_pnDMICacheIndex )
  604. {
  605. delete [] m_pnDMICacheIndex;
  606. m_pnDMICacheIndex = NULL;
  607. }
  608. m_nDMICacheCurrent = -1;
  609. }
  610. /***
  611. 求出真正波幅TR,TR是下列三者中绝对值最大的一个:
  612. 昨收盘-今 最高、昨收盘-今最低、今最高-今最低
  613. +DM = 今最高-昨最高
  614. -DM = 昨最低-今最低
  615. */
  616. BOOL CDMI::CalculateDM( double *pDMPlus, double *pDMMinus, double *pTR, int nIndex )
  617. {
  618. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  619. if( nIndex < 1 )
  620. return FALSE;
  621. double dDMPlus = 0, dDMMinus = 0, dTR = 0;
  622. KDATA kdNow = m_pKData->ElementAt(nIndex);
  623. KDATA kdLast = m_pKData->ElementAt(nIndex-1);
  624. dDMPlus = max( 0, ((double)kdNow.m_fHigh) - kdLast.m_fHigh );
  625. dDMMinus = max( 0, ((double)kdLast.m_fLow) - kdNow.m_fLow );
  626. dTR = max( fabs(((double)kdNow.m_fClose)-kdNow.m_fLow), fabs(((double)kdNow.m_fHigh)-kdLast.m_fClose) );
  627. dTR = max( dTR, fabs(((double)kdNow.m_fLow)-kdLast.m_fClose) );
  628. if( pDMPlus ) *pDMPlus = dDMPlus;
  629. if( pDMMinus ) *pDMMinus = dDMMinus;
  630. if( pTR ) *pTR = dTR;
  631. return TRUE;
  632. }
  633. /***
  634. TRn = N天TR之和
  635. +DMn = N天+DM之和
  636. -DMn = N天-DM之和
  637. +DI = (+DMn ÷ TRn)×100
  638. -DI = (-DMn ÷ TRn)×100
  639. DI差 = +DI-(-DI)
  640. DI和 = +DI+(-DI)
  641. DX = (DI差÷DI和)×100
  642. */
  643. BOOL CDMI::CalculateDIDX( double *pDIPlus, double *pDIMinus, double *pDX, int nIndex, int nDays )
  644. {
  645. STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
  646. if( m_nDays > nIndex )
  647. return FALSE;
  648. double dDX, dADX = 0;
  649. double dDIPlus = 0, dDIMinus = 0, dTRSum = 0;
  650. int nCount = 0;
  651. for( int k=nIndex; k>=1; k-- )
  652. {
  653. double dDMPlus = 0, dDMMinus = 0, dTR = 0;
  654. if( !CalculateDM( &dDMPlus, &dDMMinus, &dTR, k ) )
  655. return FALSE;
  656. dDIPlus += dDMPlus;
  657. dDIMinus += dDMMinus;
  658. dTRSum += dTR;
  659. nCount ++;
  660. if( nCount == nDays )
  661. {
  662. if( fabs(dTRSum) < 1e-4 || fabs(dDIPlus+dDIMinus) < 1e-4 )
  663. return FALSE;
  664. dDIPlus = (dDIPlus * 100/dTRSum);
  665. dDIMinus = (dDIMinus * 100/dTRSum);
  666. dDX = fabs(dDIPlus-dDIMinus) * 100 / (dDIPlus+dDIMinus);
  667. if( pDIPlus ) *pDIPlus = dDIPlus;
  668. if( pDIMinus ) *pDIMinus = dDIMinus;
  669. if( pDX ) *pDX = dDX;
  670. return TRUE;
  671. }
  672. }
  673. return FALSE;
  674. }
  675. int CDMI::GetSignal( int nIndex, UINT * pnCode )
  676. {
  677. if( pnCode ) *pnCode = ITSC_NOTHING;
  678. /* PrepareCache( 0, -1, FALSE );
  679. if( nIndex <= 0 )
  680. return ITS_NOTHING;
  681. double dDIPlus, dDIMinus, dADX, dADXR;
  682. double dDIPlusLast, dDIMinusLast, dADXLast, dADXRLast;
  683. if( !Calculate( &dDIPlusLast, &dDIMinusLast, &dADXLast, &dADXRLast, nIndex-1, FALSE )
  684. || !Calculate( &dDIPlus, &dDIMinus, &dADX, &dADXR, nIndex, FALSE ) )
  685. return ITS_NOTHING;
  686. if( dDIPlusLast < dDIMinusLast && dDIPlus > dDIMinus )
  687. {
  688. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  689. return m_itsGoldenFork;
  690. }
  691. if( dDIMinusLast < dDIPlusLast && dDIMinus > dDIPlus )
  692. {
  693. if( pnCode ) *pnCode = ITSC_DEADFORK;
  694. return m_itsDeadFork;
  695. }
  696. */
  697. // 无买卖信号
  698. return ITS_NOTHING;
  699. }
  700. BOOL CDMI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  701. {
  702. return AfxGetMinMaxInfo4( nStart, nEnd, pdMin, pdMax, this );
  703. }
  704. /***
  705. 求出真正波幅TR,TR是下列三者中绝对值最大的一个:
  706. 昨收盘-今 最高、昨收盘-今最低、今最高-今最低
  707. +DM = 今最高-昨最高
  708. -DM = 昨最低-今最低
  709. TRn = N天TR之和
  710. +DMn = N天+DM之和
  711. -DMn = N天-DM之和
  712. +DI = (+DMn ÷ TRn)×100
  713. -DI = (-DMn ÷ TRn)×100
  714. DI差 = +DI-(-DI)
  715. DI和 = +DI+(-DI)
  716. DX = (DI差÷DI和)×100
  717. ADX = DX的平滑均值
  718. ADXR = ADX的均值
  719. */
  720. BOOL CDMI::Calculate( double * pDIPlus, double * pDIMinus, double *pADX, double *pADXR, int nIndex, BOOL bUseLast )
  721. {
  722. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  723. if( m_nDays > nIndex )
  724. return FALSE;
  725. if( LoadFromCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR ) )
  726. return TRUE;
  727. double dDX = 0, dADX = 0, dADXR = 0;
  728. if( !CalculateDIDX( pDIPlus, pDIMinus, &dDX, nIndex, m_nDays ) )
  729. return FALSE;
  730. if( NULL == m_pdDMICache )
  731. {
  732. m_pdDMICache = new double[m_nDays];
  733. m_pnDMICacheIndex = new int[m_nDays];
  734. if( NULL == m_pdDMICache || NULL == m_pnDMICacheIndex )
  735. return FALSE;
  736. for( int i=0; i<m_nDays; i++ )
  737. m_pnDMICacheIndex[i] = -1;
  738. m_nDMICacheCurrent = -1;
  739. }
  740. if( bUseLast && pADX )
  741. {
  742. // Calculate ADX and ADXR
  743. dADX = ( (m_nDays-1)*(*pADX) + dDX ) / m_nDays;
  744. for( int i=0; i<m_nDays; i++ )
  745. {
  746. if( m_pnDMICacheIndex[i] == nIndex-m_nDays )
  747. {
  748. dADXR = (m_pdDMICache[i] + dADX) / 2;
  749. break;
  750. }
  751. }
  752. // Save ADX to cache
  753. m_nDMICacheCurrent ++;
  754. if( m_nDMICacheCurrent < 0 || m_nDMICacheCurrent >= m_nDays )
  755. m_nDMICacheCurrent = 0;
  756. m_pdDMICache[m_nDMICacheCurrent] = dADX;
  757. m_pnDMICacheIndex[m_nDMICacheCurrent] = nIndex;
  758. if( pADX ) *pADX = dADX;
  759. if( pADXR ) *pADXR = dADXR;
  760. StoreToCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR );
  761. return TRUE;
  762. }
  763. else
  764. {
  765. double factor = 1;
  766. for( int k=nIndex; k > 0; k-- )
  767. {
  768. factor *= ((double)(m_nDays-1))/m_nDays;
  769. if( factor < 0.001 )
  770. break;
  771. }
  772. double dADXLast = 0;
  773. BOOL bHasADXR = FALSE;
  774. for( ; k<=nIndex; k++ )
  775. {
  776. if( !CalculateDIDX( NULL, NULL, &dDX, k, m_nDays ) )
  777. continue;
  778. // Calculate ADX and ADXR
  779. dADX = ( (m_nDays-1)*dADX + dDX )/m_nDays;
  780. if( k == nIndex-m_nDays )
  781. {
  782. dADXLast = dADX;
  783. bHasADXR = TRUE;
  784. }
  785. // Save ADX to cache
  786. m_nDMICacheCurrent ++;
  787. if( m_nDMICacheCurrent < 0 || m_nDMICacheCurrent >= m_nDays )
  788. m_nDMICacheCurrent = 0;
  789. m_pdDMICache[m_nDMICacheCurrent] = dADX;
  790. m_pnDMICacheIndex[m_nDMICacheCurrent] = k;
  791. }
  792. dADXR = (dADX + dADXLast) / 2;
  793. if( pADX ) *pADX = dADX;
  794. if( pADXR && bHasADXR ) *pADXR = dADXR;
  795. StoreToCache( nIndex, pDIPlus, pDIMinus, pADX, pADXR );
  796. return TRUE;
  797. }
  798. return FALSE;
  799. }
  800. //////////////////////////////////////////////////////////////////////
  801. // CROC
  802. CROC::CROC( )
  803. {
  804. SetDefaultParameters( );
  805. }
  806. CROC::CROC( CKData * pKData )
  807. : CTechnique( pKData )
  808. {
  809. SetDefaultParameters( );
  810. }
  811. CROC::~CROC()
  812. {
  813. Clear( );
  814. }
  815. void CROC::SetDefaultParameters( )
  816. {
  817. m_nDays = 10;
  818. m_nMADays = 10;
  819. m_itsGoldenFork = ITS_BUY;
  820. m_itsDeadFork = ITS_SELL;
  821. }
  822. void CROC::AttachParameters( CROC & src )
  823. {
  824. m_nDays = src.m_nDays;
  825. m_nMADays = src.m_nMADays;
  826. m_itsGoldenFork = src.m_itsGoldenFork;
  827. m_itsDeadFork = src.m_itsDeadFork;
  828. }
  829. BOOL CROC::IsValidParameters( )
  830. {
  831. return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
  832. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  833. }
  834. void CROC::Clear( )
  835. {
  836. CTechnique::Clear( );
  837. }
  838. int CROC::GetSignal( int nIndex, UINT * pnCode )
  839. {
  840. if( pnCode ) *pnCode = ITSC_NOTHING;
  841. int nMaxDays = m_nDays + m_nMADays;
  842. double dLiminalLow = 0, dLiminalHigh = 0;
  843. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.309, 0.6 ) )
  844. return ITS_NOTHING;
  845. double dROC, dMA;
  846. if( !Calculate( &dROC, &dMA, nIndex, FALSE ) )
  847. return ITS_NOTHING;
  848. if( dROC < dLiminalLow && dMA < dLiminalLow && IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) )
  849. { // 低位金叉
  850. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  851. return m_itsGoldenFork;
  852. }
  853. if( dROC > dLiminalHigh && dMA > dLiminalHigh && IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) )
  854. { // 高位死叉
  855. if( pnCode ) *pnCode = ITSC_DEADFORK;
  856. return m_itsDeadFork;
  857. }
  858. return ITS_NOTHING;
  859. }
  860. BOOL CROC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  861. {
  862. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  863. }
  864. /***
  865. ROC=(今收盘-前N日收盘)÷前N日的收盘×100 
  866. */
  867. BOOL CROC::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  868. {
  869. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  870. if( m_nDays > nIndex )
  871. return FALSE;
  872. if( LoadFromCache( nIndex, pValue ) )
  873. return TRUE;
  874. if( m_pKData->MaindataAt(nIndex-m_nDays) <= 0
  875. || m_pKData->MaindataAt(nIndex) <= 0 )
  876. return FALSE;
  877. double x = m_pKData->MaindataAt(nIndex);
  878. double y = m_pKData->MaindataAt(nIndex-m_nDays);
  879. if( pValue )
  880. *pValue = (x - y) * 100 / y;
  881. StoreToCache( nIndex, pValue );
  882. return TRUE;
  883. }
  884. BOOL CROC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  885. {
  886. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  887. }
  888. //////////////////////////////////////////////////////////////////////
  889. // CCCI
  890. CCCI::CCCI( )
  891. {
  892. SetDefaultParameters( );
  893. }
  894. CCCI::CCCI( CKData * pKData )
  895. : CTechnique( pKData )
  896. {
  897. SetDefaultParameters( );
  898. }
  899. CCCI::~CCCI()
  900. {
  901. Clear( );
  902. }
  903. void CCCI::SetDefaultParameters( )
  904. {
  905. m_nDays = 14;
  906. m_dQuotiety = 0.015;
  907. m_nMADays = 10;
  908. m_itsGoldenFork = ITS_BUY;
  909. m_itsDeadFork = ITS_SELL;
  910. }
  911. void CCCI::AttachParameters( CCCI & src )
  912. {
  913. m_nDays = src.m_nDays;
  914. m_dQuotiety = src.m_dQuotiety;
  915. m_nMADays = src.m_nMADays;
  916. m_itsGoldenFork = src.m_itsGoldenFork;
  917. m_itsDeadFork = src.m_itsDeadFork;
  918. }
  919. BOOL CCCI::IsValidParameters( )
  920. {
  921. return ( VALID_DAYS(m_nDays) && m_dQuotiety > 0 && VALID_DAYS(m_nMADays)
  922. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  923. }
  924. void CCCI::Clear( )
  925. {
  926. CTechnique::Clear( );
  927. }
  928. int CCCI::GetSignal( int nIndex, UINT * pnCode )
  929. {
  930. if( pnCode ) *pnCode = ITSC_NOTHING;
  931. double dCCI;
  932. if( !Calculate( &dCCI, nIndex, FALSE ) )
  933. return ITS_NOTHING;
  934. int nForkSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  935. if( dCCI < -100 && nForkSignal == m_itsGoldenFork )
  936. { // 低位金叉
  937. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  938. return m_itsGoldenFork;
  939. }
  940. if( dCCI > 100 && nForkSignal == m_itsDeadFork )
  941. { // 高位死叉
  942. if( pnCode ) *pnCode = ITSC_DEADFORK;
  943. return m_itsDeadFork;
  944. }
  945. return ITS_NOTHING;
  946. }
  947. BOOL CCCI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  948. {
  949. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  950. }
  951. /***
  952. TP = 收盘价+收盘价+最高价+最低价
  953. A是TP的N日均值
  954. D是TP与A的离差均值
  955. CCI=(C-D)/(0.015D)
  956. */
  957. BOOL CCCI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  958. {
  959. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  960. if( m_nDays > nIndex+1 )
  961. return FALSE;
  962. if( LoadFromCache( nIndex, pValue ) )
  963. return TRUE;
  964. double dTP = 0, dMATP = 0, dD = 0;
  965. int nCount = 0;
  966. for( int k=nIndex; k>=0; k-- )
  967. {
  968. KDATA kd = m_pKData->ElementAt(k);
  969. double dTemp = (kd.m_fHigh+kd.m_fClose+kd.m_fClose+kd.m_fLow)/4;
  970. if( nIndex == k )
  971. dTP = dTemp;
  972. dMATP += dTemp;
  973. nCount ++;
  974. if( nCount == m_nDays )
  975. break;
  976. }
  977. dMATP = dMATP / m_nDays;
  978. nCount = 0;
  979. for( k=nIndex; k>=0; k-- )
  980. {
  981. KDATA kd = m_pKData->ElementAt(k);
  982. double dTemp = (kd.m_fHigh+kd.m_fClose+kd.m_fClose+kd.m_fLow)/4;
  983. dD += fabs(dTemp-dMATP);
  984. nCount ++;
  985. if( nCount == m_nDays )
  986. break;
  987. }
  988. dD = dD / m_nDays;
  989. if( fabs(dD) < 1e-4 )
  990. return FALSE;
  991. if( pValue )
  992. *pValue = (dTP - dMATP) / (m_dQuotiety * dD);
  993. StoreToCache( nIndex, pValue );
  994. return TRUE;
  995. }
  996. /***
  997. CCI 及其 移动平均值
  998. */
  999. BOOL CCCI::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1000. {
  1001. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1002. }
  1003. //////////////////////////////////////////////////////////////////////
  1004. // CCV
  1005. CCV::CCV( )
  1006. {
  1007. SetDefaultParameters( );
  1008. }
  1009. CCV::CCV( CKData * pKData )
  1010. : CTechnique( pKData )
  1011. {
  1012. SetDefaultParameters( );
  1013. }
  1014. CCV::~CCV()
  1015. {
  1016. Clear( );
  1017. }
  1018. void CCV::SetDefaultParameters( )
  1019. {
  1020. m_nMAHLDays = 10;
  1021. m_nCVDays = 10;
  1022. m_itsSold = ITS_BUY;
  1023. m_itsBought = ITS_SELL;
  1024. }
  1025. void CCV::AttachParameters( CCV & src )
  1026. {
  1027. m_nMAHLDays = src.m_nMAHLDays;
  1028. m_nCVDays = src.m_nCVDays;
  1029. m_itsSold = src.m_itsSold;
  1030. m_itsBought = src.m_itsBought;
  1031. }
  1032. BOOL CCV::IsValidParameters( )
  1033. {
  1034. return ( VALID_DAYS(m_nMAHLDays) && VALID_DAYS(m_nCVDays)
  1035. && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  1036. }
  1037. void CCV::Clear( )
  1038. {
  1039. CTechnique::Clear( );
  1040. }
  1041. int CCV::GetSignal( int nIndex, UINT * pnCode )
  1042. {
  1043. if( pnCode ) *pnCode = ITSC_NOTHING;
  1044. if( nIndex <= 1 )
  1045. return ITS_NOTHING;
  1046. double dNow, dLast, dLastLast;
  1047. if( !Calculate( &dLastLast, nIndex-2, FALSE )
  1048. || !Calculate( &dLast, nIndex-1, FALSE )
  1049. || !Calculate( &dNow, nIndex, FALSE ) )
  1050. return ITS_NOTHING;
  1051. if( dLastLast < 0 && dLast < 0 && dNow < 0 && dLast <= dLastLast && dNow > dLast )
  1052. { // 超卖
  1053. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  1054. return m_itsSold;
  1055. }
  1056. if( dLastLast > 0 && dLast > 0 && dNow > 0 && dLast >= dLastLast && dNow < dLast )
  1057. { // 超买
  1058. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  1059. return m_itsBought;
  1060. }
  1061. return ITS_NOTHING;
  1062. }
  1063. BOOL CCV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1064. {
  1065. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  1066. }
  1067. /***
  1068. A = 最高价 - 最低价
  1069. MAHL = A的m_nMAHLDays日平均值
  1070. MAHLLast= m_nCVDays日前的MAHL
  1071. CCI = 100 * (MAHL - MAHLLast) / MAHLLast;
  1072. */
  1073. BOOL CCV::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1074. {
  1075. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1076. if( m_nMAHLDays+m_nCVDays > nIndex+2 )
  1077. return FALSE;
  1078. if( LoadFromCache( nIndex, pValue ) )
  1079. return TRUE;
  1080. double dMAHLNow = 0, dMAHLLast = 0;
  1081. int nCount = 0;
  1082. for( int k=nIndex; k>=0; k-- )
  1083. {
  1084. KDATA kd = m_pKData->ElementAt(k);
  1085. dMAHLNow += (kd.m_fHigh-kd.m_fLow);
  1086. nCount ++;
  1087. if( nCount == m_nMAHLDays )
  1088. break;
  1089. }
  1090. nCount = 0;
  1091. for( k=nIndex-m_nCVDays+1; k>=0; k-- )
  1092. {
  1093. KDATA kd = m_pKData->ElementAt(k);
  1094. dMAHLLast += (((double)kd.m_fHigh)-kd.m_fLow);
  1095. nCount ++;
  1096. if( nCount == m_nMAHLDays )
  1097. break;
  1098. }
  1099. dMAHLNow = dMAHLNow / m_nMAHLDays;
  1100. dMAHLLast = dMAHLLast / m_nMAHLDays;
  1101. if( fabs(dMAHLLast) < 1e-4 )
  1102. return FALSE;
  1103. if( pValue )
  1104. *pValue = (dMAHLNow - dMAHLLast) * 100 / dMAHLLast;
  1105. StoreToCache( nIndex, pValue );
  1106. return TRUE;
  1107. }
  1108. //////////////////////////////////////////////////////////////////////
  1109. // CARBR
  1110. CARBR::CARBR( )
  1111. {
  1112. SetDefaultParameters( );
  1113. }
  1114. CARBR::CARBR( CKData * pKData )
  1115. : CTechnique( pKData )
  1116. {
  1117. SetDefaultParameters( );
  1118. }
  1119. CARBR::~CARBR()
  1120. {
  1121. Clear( );
  1122. }
  1123. void CARBR::SetDefaultParameters( )
  1124. {
  1125. m_nDays = 26;
  1126. m_itsGoldenFork = ITS_BUYINTENSE;
  1127. m_itsDeadFork = ITS_SELLINTENSE;
  1128. m_itsSold = ITS_BUY;
  1129. m_itsBought = ITS_SELL;
  1130. }
  1131. void CARBR::AttachParameters( CARBR & src )
  1132. {
  1133. m_nDays = src.m_nDays;
  1134. m_itsGoldenFork = src.m_itsGoldenFork;
  1135. m_itsDeadFork = src.m_itsDeadFork;
  1136. m_itsSold = src.m_itsSold;
  1137. m_itsBought = src.m_itsBought;
  1138. }
  1139. BOOL CARBR::IsValidParameters( )
  1140. {
  1141. return ( VALID_DAYS(m_nDays)
  1142. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork)
  1143. && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  1144. }
  1145. void CARBR::Clear( )
  1146. {
  1147. CTechnique::Clear( );
  1148. }
  1149. int CARBR::GetSignal( int nIndex, UINT * pnCode )
  1150. {
  1151. if( pnCode ) *pnCode = ITSC_NOTHING;
  1152. double dAR, dBR;
  1153. if( !Calculate( &dAR, &dBR, nIndex, FALSE ) )
  1154. return ITS_NOTHING;
  1155. int nForkSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1156. if( (dAR < 50 || dBR < 50 ) && nForkSignal == m_itsGoldenFork )
  1157. { // 低位金叉
  1158. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1159. return m_itsGoldenFork;
  1160. }
  1161. if( (dAR > 180 || dBR > 300) && nForkSignal == m_itsDeadFork )
  1162. { // 高位死叉
  1163. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1164. return m_itsDeadFork;
  1165. }
  1166. if( dAR < 50 )
  1167. { // 超卖
  1168. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  1169. return m_itsSold;
  1170. }
  1171. if( dAR > 200 )
  1172. { // 超买
  1173. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  1174. return m_itsBought;
  1175. }
  1176. return ITS_NOTHING;
  1177. }
  1178. BOOL CARBR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1179. {
  1180. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1181. }
  1182. /***
  1183.       (H-O)n天之和
  1184. AR = ———————— × 100
  1185.       (O-L)n天之和
  1186.       (H-C)n天之和
  1187. BR = ———————— × 100
  1188.       (C-L)n天之和
  1189. H:最高价 L:最低价 O:开盘价 C:收盘价 
  1190. */
  1191. BOOL CARBR::Calculate( double * pAR, double *pBR, int nIndex, BOOL bUseLast )
  1192. {
  1193. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1194. if( m_nDays > nIndex )
  1195. return FALSE;
  1196. if( LoadFromCache( nIndex, pAR, pBR ) )
  1197. return TRUE;
  1198. double dUP = 0, dDG = 0, dBS = 0, dSS = 0;
  1199. int nCount = 0;
  1200. for( int k=nIndex; k>=1; k-- )
  1201. {
  1202. KDATA kd = m_pKData->ElementAt(k);
  1203. KDATA kdLast = m_pKData->ElementAt(k-1);
  1204. dUP += (((double)kd.m_fHigh)-kd.m_fOpen);
  1205. dDG += (((double)kd.m_fOpen)-kd.m_fLow);
  1206. dBS += max( 0, ((double)kd.m_fHigh) - kdLast.m_fClose );
  1207. dSS += max( 0, ((double)kdLast.m_fClose) - kd.m_fLow );
  1208. nCount ++;
  1209. if( nCount == m_nDays )
  1210. break;
  1211. }
  1212. if( dDG < 1e-4 || dSS < 1e-4 )
  1213. return FALSE;
  1214. if( pAR )
  1215. *pAR = dUP * 100 / dDG;
  1216. if( pBR )
  1217. *pBR = dBS * 100 / dSS;
  1218. StoreToCache( nIndex, pAR, pBR );
  1219. return TRUE;
  1220. }
  1221. //////////////////////////////////////////////////////////////////////
  1222. // CCR
  1223. CCR::CCR( )
  1224. {
  1225. SetDefaultParameters( );
  1226. }
  1227. CCR::CCR( CKData * pKData )
  1228. : CTechnique( pKData )
  1229. {
  1230. SetDefaultParameters( );
  1231. }
  1232. CCR::~CCR()
  1233. {
  1234. Clear( );
  1235. }
  1236. void CCR::SetDefaultParameters( )
  1237. {
  1238. m_nDays = 26;
  1239. m_nMADaysA = 10;
  1240. m_nMADaysB = 20;
  1241. m_nMADaysC = 40;
  1242. m_nMADaysD = 62;
  1243. m_itsSold = ITS_BUY;
  1244. m_itsBought = ITS_SELL;
  1245. }
  1246. void CCR::AttachParameters( CCR & src )
  1247. {
  1248. m_nDays = src.m_nDays;
  1249. m_nMADaysA = src.m_nMADaysA;
  1250. m_nMADaysB = src.m_nMADaysB;
  1251. m_nMADaysC = src.m_nMADaysC;
  1252. m_nMADaysD = src.m_nMADaysD;
  1253. m_itsSold = src.m_itsSold;
  1254. m_itsBought = src.m_itsBought;
  1255. }
  1256. BOOL CCR::IsValidParameters( )
  1257. {
  1258. return ( VALID_DAYS( m_nDays ) && VALID_DAYS( m_nMADaysA ) && VALID_DAYS( m_nMADaysB )
  1259. && VALID_DAYS( m_nMADaysC ) && VALID_DAYS( m_nMADaysD )
  1260. && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  1261. }
  1262. void CCR::Clear( )
  1263. {
  1264. CTechnique::Clear( );
  1265. }
  1266. int CCR::GetSignal( int nIndex, UINT * pnCode )
  1267. {
  1268. if( pnCode ) *pnCode = ITSC_NOTHING;
  1269. double dCR;
  1270. if( !Calculate( &dCR, nIndex, FALSE ) )
  1271. return ITS_NOTHING;
  1272. if( dCR < 40 )
  1273. { // 超卖
  1274. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  1275. return m_itsSold;
  1276. }
  1277. if( dCR > 300 )
  1278. { // 超买
  1279. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  1280. return m_itsBought;
  1281. }
  1282. return ITS_NOTHING;
  1283. }
  1284. BOOL CCR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1285. {
  1286. return AfxGetMinMaxInfo5( nStart, nEnd, pdMin, pdMax, this );
  1287. }
  1288. /***
  1289. MID = (开盘价 + 收盘价 + 最高价 + 最低价)÷ 2
  1290. 上升值 = 今最高 - 昨日MID (负值记为0)
  1291. 下跌值 = 昨MID - 今最低
  1292.        n天上升值之和
  1293. CR = ———————— × 100
  1294.        n天下跌值之和
  1295. */
  1296. BOOL CCR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1297. {
  1298. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1299. if( m_nDays > nIndex )
  1300. return FALSE;
  1301. if( LoadFromCache( nIndex, pValue ) )
  1302. return TRUE;
  1303. double dBS = 0, dSS = 0, dCR = 0;
  1304. int nCount = 0;
  1305. for( int k=nIndex; k>=1; k-- )
  1306. {
  1307. KDATA kd = m_pKData->ElementAt(k);
  1308. KDATA kdLast = m_pKData->ElementAt(k-1);
  1309. double dTP = (kdLast.m_fHigh+kdLast.m_fLow+kdLast.m_fOpen+kdLast.m_fClose)/4;
  1310. dBS += max( 0, kd.m_fHigh - dTP );
  1311. dSS += max( 0, dTP - kd.m_fLow );
  1312. nCount ++;
  1313. if( nCount == m_nDays )
  1314. break;
  1315. }
  1316. if( dSS < 1e-4 )
  1317. return FALSE;
  1318. dCR = dBS * 100 / dSS;
  1319. if( pValue )
  1320. *pValue = dCR;
  1321. StoreToCache( nIndex, pValue );
  1322. return TRUE;
  1323. }
  1324. /***
  1325. A, B, C, D 分别是CR的N日平均值
  1326. N分别为m_nMADaysA,m_nMADaysB,m_nMADaysC,m_nMADaysD
  1327. */
  1328. BOOL CCR::Calculate( double * pValue, double * pA, double * pB, double * pC, double * pD, int nIndex, BOOL bUseLast )
  1329. {
  1330. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1331. int nMaxMADays = max( max(m_nMADaysA,m_nMADaysB), max(m_nMADaysC,m_nMADaysD) );
  1332. if( m_nDays+nMaxMADays > nIndex+1 )
  1333. return FALSE;
  1334. if( LoadFromCache( nIndex, pValue, pA, pB, pC, pD ) )
  1335. return TRUE;
  1336. double dCR = 0, dA = 0, dB = 0, dC = 0, dD = 0;
  1337. int nCount = 0;
  1338. for( int k=nIndex; k>=m_nDays; k-- )
  1339. {
  1340. double dTemp;
  1341. if( Calculate( &dTemp, k, FALSE ) )
  1342. {
  1343. if( nIndex == k )
  1344. dCR = dTemp;
  1345. nCount ++;
  1346. if( nCount <= m_nMADaysA )
  1347. dA += dTemp;
  1348. if( nCount <= m_nMADaysB )
  1349. dB += dTemp;
  1350. if( nCount <= m_nMADaysC )
  1351. dC += dTemp;
  1352. if( nCount <= m_nMADaysD )
  1353. dD += dTemp;
  1354. if( nCount > nMaxMADays )
  1355. {
  1356. if( pValue ) *pValue = dCR;
  1357. if( pA ) *pA = dA / m_nMADaysA;
  1358. if( pB ) *pB = dB / m_nMADaysB;
  1359. if( pC ) *pC = dC / m_nMADaysC;
  1360. if( pD ) *pD = dD / m_nMADaysD;
  1361. StoreToCache( nIndex, pValue, pA, pB, pC, pD );
  1362. return TRUE;
  1363. }
  1364. }
  1365. }
  1366. return FALSE;
  1367. }
  1368. //////////////////////////////////////////////////////////////////////
  1369. // COSC
  1370. COSC::COSC( )
  1371. {
  1372. SetDefaultParameters( );
  1373. }
  1374. COSC::COSC( CKData * pKData )
  1375. : CTechnique( pKData )
  1376. {
  1377. SetDefaultParameters( );
  1378. }
  1379. COSC::~COSC()
  1380. {
  1381. Clear( );
  1382. }
  1383. void COSC::SetDefaultParameters( )
  1384. {
  1385. m_nDays = 10;
  1386. m_nMADays = 6;
  1387. m_itsGoldenFork = ITS_BUY;
  1388. m_itsDeadFork = ITS_SELL;
  1389. }
  1390. void COSC::AttachParameters( COSC & src )
  1391. {
  1392. m_nDays = src.m_nDays;
  1393. m_nMADays = src.m_nMADays;
  1394. m_itsGoldenFork = src.m_itsGoldenFork;
  1395. m_itsDeadFork = src.m_itsDeadFork;
  1396. }
  1397. BOOL COSC::IsValidParameters( )
  1398. {
  1399. return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
  1400. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  1401. }
  1402. void COSC::Clear( )
  1403. {
  1404. CTechnique::Clear( );
  1405. }
  1406. int COSC::GetSignal( int nIndex, UINT * pnCode )
  1407. {
  1408. if( pnCode ) *pnCode = ITSC_NOTHING;
  1409. int nMaxDays = m_nDays+m_nMADays;
  1410. double dLiminalLow = 0, dLiminalHigh = 0;
  1411. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.3, 0.6 ) )
  1412. return ITS_NOTHING;
  1413. double dOSC;
  1414. if( !Calculate( &dOSC, nIndex, FALSE ) )
  1415. return ITS_NOTHING;
  1416. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1417. if( dOSC < dLiminalLow && nSignal == m_itsGoldenFork )
  1418. { // 低位金叉
  1419. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1420. return m_itsGoldenFork;
  1421. }
  1422. if( dOSC > dLiminalHigh && nSignal == m_itsDeadFork )
  1423. { // 高位死叉
  1424. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1425. return m_itsDeadFork;
  1426. }
  1427. return ITS_NOTHING;
  1428. }
  1429. BOOL COSC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1430. {
  1431. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1432. }
  1433. /***
  1434. OSC = 今日收盘价/N日收盘价平均值
  1435. */
  1436. BOOL COSC::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1437. {
  1438. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1439. if( m_nDays > nIndex+1 )
  1440. return FALSE;
  1441. if( LoadFromCache( nIndex, pValue ) )
  1442. return TRUE;
  1443. double dCt = m_pKData->MaindataAt(nIndex);
  1444. double dMA = 0;
  1445. int nCount = 0;
  1446. for( int k=nIndex; k>=0; k-- )
  1447. {
  1448. dMA += m_pKData->MaindataAt(k);
  1449. nCount ++;
  1450. if( nCount == m_nDays )
  1451. {
  1452. dMA = dMA / m_nDays;
  1453. if( dMA < 1e-4 )
  1454. return FALSE;
  1455. if( pValue )
  1456. *pValue = (dCt/dMA);
  1457. StoreToCache( nIndex, pValue );
  1458. return TRUE;
  1459. }
  1460. }
  1461. return FALSE;
  1462. }
  1463. /***
  1464. 计算OSC及其移动平均值
  1465. */
  1466. BOOL COSC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1467. {
  1468. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1469. }
  1470. //////////////////////////////////////////////////////////////////////
  1471. // CUOS
  1472. CUOS::CUOS( )
  1473. {
  1474. SetDefaultParameters( );
  1475. }
  1476. CUOS::CUOS( CKData * pKData )
  1477. : CTechnique( pKData )
  1478. {
  1479. SetDefaultParameters( );
  1480. }
  1481. CUOS::~CUOS()
  1482. {
  1483. Clear( );
  1484. }
  1485. void CUOS::SetDefaultParameters( )
  1486. {
  1487. m_nDays1 = 7;
  1488. m_nDays2 = 14;
  1489. m_nDays3 = 28;
  1490. m_nMADays = 6;
  1491. m_itsGoldenFork = ITS_BUY;
  1492. m_itsDeadFork = ITS_SELL;
  1493. }
  1494. void CUOS::AttachParameters( CUOS & src )
  1495. {
  1496. m_nDays1 = src.m_nDays1;
  1497. m_nDays2 = src.m_nDays2;
  1498. m_nDays3 = src.m_nDays3;
  1499. m_nMADays = src.m_nMADays;
  1500. m_itsGoldenFork = src.m_itsGoldenFork;
  1501. m_itsDeadFork = src.m_itsDeadFork;
  1502. }
  1503. BOOL CUOS::IsValidParameters( )
  1504. {
  1505. return ( VALID_DAYS(m_nDays1) && VALID_DAYS(m_nDays2) && VALID_DAYS(m_nDays3) && VALID_DAYS(m_nMADays)
  1506. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  1507. }
  1508. void CUOS::Clear( )
  1509. {
  1510. CTechnique::Clear( );
  1511. }
  1512. int CUOS::GetSignal( int nIndex, UINT * pnCode )
  1513. {
  1514. if( pnCode ) *pnCode = ITSC_NOTHING;
  1515. int nMaxDays = max( max(m_nDays1,m_nDays2),m_nDays3) +m_nMADays;
  1516. double dLiminalLow = 0, dLiminalHigh = 0;
  1517. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.4, 0.6 ) )
  1518. return ITS_NOTHING;
  1519. double dUOS;
  1520. if( !Calculate( &dUOS, nIndex, FALSE ) )
  1521. return ITS_NOTHING;
  1522. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1523. if( dUOS < dLiminalLow && nSignal == m_itsGoldenFork )
  1524. { // 低位金叉
  1525. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1526. return m_itsGoldenFork;
  1527. }
  1528. if( dUOS > dLiminalHigh && nSignal == m_itsDeadFork )
  1529. { // 高位死叉
  1530. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1531. return m_itsDeadFork;
  1532. }
  1533. return ITS_NOTHING;
  1534. }
  1535. BOOL CUOS::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1536. {
  1537. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1538. }
  1539. /***
  1540. OSC1 = m_nDays1日OSC
  1541. OSC2 = m_nDays2日OSC
  1542. OSC3 = m_nDays3日OSC
  1543. UOS = (OSC1+OSC2+OSC3)/3
  1544. */
  1545. BOOL CUOS::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1546. {
  1547. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1548. if( LoadFromCache( nIndex, pValue ) )
  1549. return TRUE;
  1550. double dOSC1 = 0, dOSC2 = 0, dOSC3 = 0;
  1551. COSC osc1(m_pKData), osc2(m_pKData), osc3(m_pKData);
  1552. osc1.m_nDays = m_nDays1;
  1553. osc2.m_nDays = m_nDays2;
  1554. osc3.m_nDays = m_nDays3;
  1555. if( osc1.Calculate( &dOSC1, nIndex, FALSE )
  1556. && osc2.Calculate( &dOSC2, nIndex, FALSE )
  1557. && osc3.Calculate( &dOSC3, nIndex, FALSE ) )
  1558. {
  1559. if( pValue )
  1560. *pValue = (dOSC1+dOSC2+dOSC3)/3;
  1561. StoreToCache( nIndex, pValue );
  1562. return TRUE;
  1563. }
  1564. return FALSE;
  1565. }
  1566. /***
  1567. 计算UOS及其移动平均值
  1568. */
  1569. BOOL CUOS::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1570. {
  1571. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1572. }
  1573. //////////////////////////////////////////////////////////////////////
  1574. // CMAOSC
  1575. CMAOSC::CMAOSC( )
  1576. {
  1577. SetDefaultParameters( );
  1578. }
  1579. CMAOSC::CMAOSC( CKData * pKData )
  1580. : CTechnique( pKData )
  1581. {
  1582. SetDefaultParameters( );
  1583. }
  1584. CMAOSC::~CMAOSC()
  1585. {
  1586. Clear( );
  1587. }
  1588. void CMAOSC::SetDefaultParameters( )
  1589. {
  1590. m_nDays1 = 6;
  1591. m_nDays2 = 12;
  1592. m_nMADays = 6;
  1593. m_itsGoldenFork = ITS_BUY;
  1594. m_itsDeadFork = ITS_SELL;
  1595. }
  1596. void CMAOSC::AttachParameters( CMAOSC & src )
  1597. {
  1598. m_nDays1 = src.m_nDays1;
  1599. m_nDays2 = src.m_nDays2;
  1600. m_nMADays = src.m_nMADays;
  1601. m_itsGoldenFork = src.m_itsGoldenFork;
  1602. m_itsDeadFork = src.m_itsDeadFork;
  1603. }
  1604. BOOL CMAOSC::IsValidParameters( )
  1605. {
  1606. return ( VALID_DAYS(m_nDays1) && VALID_DAYS(m_nDays2) && VALID_DAYS(m_nMADays)
  1607. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  1608. }
  1609. void CMAOSC::Clear( )
  1610. {
  1611. CTechnique::Clear( );
  1612. }
  1613. int CMAOSC::GetSignal( int nIndex, UINT * pnCode )
  1614. {
  1615. if( pnCode ) *pnCode = ITSC_NOTHING;
  1616. int nMaxDays = m_nMADays + max(m_nDays1,m_nDays2);
  1617. double dLiminalLow = 0, dLiminalHigh = 0;
  1618. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.4, 0.5 ) )
  1619. return ITS_NOTHING;
  1620. double dMAOSC;
  1621. if( !Calculate( &dMAOSC, nIndex, FALSE ) )
  1622. return ITS_NOTHING;
  1623. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1624. if( dMAOSC < dLiminalLow && nSignal == m_itsGoldenFork )
  1625. { // 低位金叉
  1626. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1627. return m_itsGoldenFork;
  1628. }
  1629. if( dMAOSC > dLiminalHigh && nSignal == m_itsDeadFork )
  1630. { // 高位死叉
  1631. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1632. return m_itsDeadFork;
  1633. }
  1634. return ITS_NOTHING;
  1635. }
  1636. BOOL CMAOSC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1637. {
  1638. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1639. }
  1640. /***
  1641. MAOSC = m_nDays1日收盘价移动平均值 - m_nDays2日收盘价移动平均值
  1642. */
  1643. BOOL CMAOSC::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1644. {
  1645. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1646. if( LoadFromCache( nIndex, pValue ) )
  1647. return TRUE;
  1648. double dMA1 = 0, dMA2 = 0;
  1649. int nCount = 0;
  1650. for( int k=nIndex; k>=0; k-- )
  1651. {
  1652. if( nCount < m_nDays1 )
  1653. dMA1 += m_pKData->MaindataAt(k);
  1654. if( nCount < m_nDays2 )
  1655. dMA2 += m_pKData->MaindataAt(k);
  1656. nCount ++;
  1657. if( nCount >= m_nDays1 && nCount >= m_nDays2 )
  1658. {
  1659. if( pValue )
  1660. *pValue = (dMA1/m_nDays1 - dMA2/m_nDays2);
  1661. StoreToCache( nIndex, pValue );
  1662. return TRUE;
  1663. }
  1664. }
  1665. return FALSE;
  1666. }
  1667. /***
  1668. 计算MAOSC及其移动平均值
  1669. */
  1670. BOOL CMAOSC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1671. {
  1672. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1673. }
  1674. //////////////////////////////////////////////////////////////////////
  1675. // C36BIAS
  1676. C36BIAS::C36BIAS( )
  1677. {
  1678. SetDefaultParameters( );
  1679. }
  1680. C36BIAS::C36BIAS( CKData * pKData )
  1681. : CTechnique( pKData )
  1682. {
  1683. SetDefaultParameters( );
  1684. }
  1685. C36BIAS::~C36BIAS()
  1686. {
  1687. Clear( );
  1688. }
  1689. void C36BIAS::SetDefaultParameters( )
  1690. {
  1691. m_itsSold = ITS_BUY;
  1692. m_itsBought = ITS_SELL;
  1693. }
  1694. void C36BIAS::AttachParameters( C36BIAS & src )
  1695. {
  1696. m_itsSold = src.m_itsSold;
  1697. m_itsBought = src.m_itsBought;
  1698. }
  1699. BOOL C36BIAS::IsValidParameters( )
  1700. {
  1701. return ( VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  1702. }
  1703. void C36BIAS::Clear( )
  1704. {
  1705. CTechnique::Clear( );
  1706. }
  1707. int C36BIAS::GetSignal( int nIndex, UINT * pnCode )
  1708. {
  1709. if( pnCode ) *pnCode = ITSC_NOTHING;
  1710. int nMaxDays = 6;
  1711. double dLiminalLow = 0, dLiminalHigh = 0;
  1712. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, 40, &dLiminalLow, &dLiminalHigh, 0.02, 0.98 ) )
  1713. return ITS_NOTHING;
  1714. double d36BIAS;
  1715. if( !Calculate( &d36BIAS, nIndex, FALSE ) )
  1716. return ITS_NOTHING;
  1717. if( d36BIAS < dLiminalLow )
  1718. { // 超卖
  1719. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  1720. return m_itsSold;
  1721. }
  1722. if( d36BIAS > dLiminalHigh )
  1723. { // 超买
  1724. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  1725. return m_itsBought;
  1726. }
  1727. return ITS_NOTHING;
  1728. }
  1729. BOOL C36BIAS::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1730. {
  1731. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  1732. }
  1733. /***
  1734. 3-6BIAS = 3日收盘价移动平均值 - 6日收盘价移动平均值
  1735. */
  1736. BOOL C36BIAS::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1737. {
  1738. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1739. if( LoadFromCache( nIndex, pValue ) )
  1740. return TRUE;
  1741. double dMA1 = 0, dMA2 = 0;
  1742. int nCount = 0;
  1743. for( int k=nIndex; k>=0; k-- )
  1744. {
  1745. if( nCount < 3 )
  1746. dMA1 += m_pKData->MaindataAt(k);
  1747. if( nCount < 6 )
  1748. dMA2 += m_pKData->MaindataAt(k);
  1749. nCount ++;
  1750. if( nCount >= 3 && nCount >= 6 )
  1751. {
  1752. if( pValue )
  1753. *pValue = (dMA1/3 - dMA2/6);
  1754. StoreToCache( nIndex, pValue );
  1755. return TRUE;
  1756. }
  1757. }
  1758. return FALSE;
  1759. }
  1760. //////////////////////////////////////////////////////////////////////
  1761. // CDPO
  1762. CDPO::CDPO( )
  1763. {
  1764. SetDefaultParameters( );
  1765. }
  1766. CDPO::CDPO( CKData * pKData )
  1767. : CTechnique( pKData )
  1768. {
  1769. SetDefaultParameters( );
  1770. }
  1771. CDPO::~CDPO()
  1772. {
  1773. Clear( );
  1774. }
  1775. void CDPO::SetDefaultParameters( )
  1776. {
  1777. m_nDays = 10;
  1778. m_nMADays = 6;
  1779. m_itsGoldenFork = ITS_BUY;
  1780. m_itsDeadFork = ITS_SELL;
  1781. }
  1782. void CDPO::AttachParameters( CDPO & src )
  1783. {
  1784. m_nDays = src.m_nDays;
  1785. m_nMADays = src.m_nMADays;
  1786. m_itsGoldenFork = src.m_itsGoldenFork;
  1787. m_itsDeadFork = src.m_itsDeadFork;
  1788. }
  1789. BOOL CDPO::IsValidParameters( )
  1790. {
  1791. return ( VALID_DAYS( m_nDays ) && VALID_DAYS( m_nMADays )
  1792. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  1793. }
  1794. void CDPO::Clear( )
  1795. {
  1796. CTechnique::Clear( );
  1797. }
  1798. int CDPO::GetSignal( int nIndex, UINT * pnCode )
  1799. {
  1800. if( pnCode ) *pnCode = ITSC_NOTHING;
  1801. int nMaxDays = 3*m_nDays + m_nMADays;
  1802. double dLiminalLow = 0, dLiminalHigh = 0;
  1803. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.2, 0.7 ) )
  1804. return ITS_NOTHING;
  1805. double dDPO;
  1806. if( !Calculate( &dDPO, nIndex, FALSE ) )
  1807. return FALSE;
  1808. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1809. if( dDPO < dLiminalLow && nSignal == m_itsGoldenFork )
  1810. { // 低位金叉
  1811. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1812. return m_itsGoldenFork;
  1813. }
  1814. if( dDPO > dLiminalHigh && nSignal == m_itsDeadFork )
  1815. { // 高位死叉
  1816. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1817. return m_itsDeadFork;
  1818. }
  1819. return ITS_NOTHING;
  1820. }
  1821. BOOL CDPO::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1822. {
  1823. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1824. }
  1825. /***
  1826. DPO = 今日收盘价 - N日前的(N+N)日平均收盘价
  1827. */
  1828. BOOL CDPO::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1829. {
  1830. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1831. if( 3*m_nDays-2 > nIndex+1 )
  1832. return FALSE;
  1833. if( LoadFromCache( nIndex, pValue ) )
  1834. return TRUE;
  1835. double dCt = 0, dMA = 0;
  1836. double nCount = 0;
  1837. for( int k=nIndex-m_nDays+1; k>=0; k-- )
  1838. {
  1839. dMA += m_pKData->MaindataAt(k);
  1840. nCount ++;
  1841. if( nCount == m_nDays+m_nDays )
  1842. {
  1843. dCt = m_pKData->MaindataAt(nIndex);
  1844. dMA = dMA / (m_nDays+m_nDays);
  1845. if( pValue )
  1846. *pValue = (dCt-dMA);
  1847. StoreToCache( nIndex, pValue );
  1848. return TRUE;
  1849. }
  1850. }
  1851. return FALSE;
  1852. }
  1853. /***
  1854. 计算DPO及其移动平均值
  1855. */
  1856. BOOL CDPO::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1857. {
  1858. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1859. }
  1860. //////////////////////////////////////////////////////////////////////
  1861. // CKST
  1862. CKST::CKST( )
  1863. {
  1864. SetDefaultParameters( );
  1865. }
  1866. CKST::CKST( CKData * pKData )
  1867. : CTechnique( pKData )
  1868. {
  1869. SetDefaultParameters( );
  1870. }
  1871. CKST::~CKST()
  1872. {
  1873. Clear( );
  1874. }
  1875. void CKST::SetDefaultParameters( )
  1876. {
  1877. m_adwROCDays.RemoveAll();
  1878. m_adwROCDays.Add( 9 );
  1879. m_adwROCDays.Add( 12 );
  1880. m_adwROCDays.Add( 18 );
  1881. m_adwROCDays.Add( 24 );
  1882. m_nMADays = 6;
  1883. m_itsGoldenFork = ITS_BUY;
  1884. m_itsDeadFork = ITS_SELL;
  1885. }
  1886. void CKST::AttachParameters( CKST & src )
  1887. {
  1888. m_adwROCDays.Copy( src.m_adwROCDays );
  1889. m_nMADays = src.m_nMADays;
  1890. m_itsGoldenFork = src.m_itsGoldenFork;
  1891. m_itsDeadFork = src.m_itsDeadFork;
  1892. }
  1893. BOOL CKST::IsValidParameters( )
  1894. {
  1895. STT_VALID_DAYSARRAY( m_adwROCDays );
  1896. return ( VALID_DAYS(m_nMADays) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  1897. }
  1898. void CKST::Clear( )
  1899. {
  1900. CTechnique::Clear( );
  1901. }
  1902. int CKST::GetSignal( int nIndex, UINT * pnCode )
  1903. {
  1904. if( pnCode ) *pnCode = ITSC_NOTHING;
  1905. int nMaxDays = AfxGetMaxDays( m_adwROCDays )+m_nMADays;
  1906. double dLiminalLow = 0, dLiminalHigh = 0;
  1907. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.2, 0.6 ) )
  1908. return ITS_NOTHING;
  1909. if( nIndex <= 1 )
  1910. return ITS_NOTHING;
  1911. double dKST;
  1912. if( !Calculate( &dKST, nIndex, FALSE ) )
  1913. return ITS_NOTHING;
  1914. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1915. if( dKST < dLiminalLow && nSignal == m_itsGoldenFork )
  1916. { // 低位金叉
  1917. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1918. return m_itsGoldenFork;
  1919. }
  1920. if( dKST > dLiminalHigh && nSignal == m_itsDeadFork )
  1921. { // 高位死叉
  1922. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1923. return m_itsDeadFork;
  1924. }
  1925. return ITS_NOTHING;
  1926. }
  1927. BOOL CKST::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1928. {
  1929. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1930. }
  1931. /***
  1932.        9日ROC + 12日ROC×2 + 18日ROC×3 + 24日ROC×4
  1933. KST = ------------------------------------------------
  1934.                            10
  1935. */
  1936. BOOL CKST::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1937. {
  1938. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1939. UINT nMaxDays = AfxGetMaxDays( m_adwROCDays );
  1940. if( (int)nMaxDays > nIndex )
  1941. return FALSE;
  1942. if( LoadFromCache( nIndex, pValue ) )
  1943. return TRUE;
  1944. double dKST = 0;
  1945. int nCount = 0;
  1946. for( int m=0; m<m_adwROCDays.GetSize(); m++ )
  1947. {
  1948. CROC roc(m_pKData);
  1949. roc.m_nDays = m_adwROCDays[m];
  1950. double dROC = 0;
  1951. if( !roc.Calculate( &dROC, nIndex, FALSE ) )
  1952. return FALSE;
  1953. dKST += dROC*(m+1);
  1954. nCount += (m+1);
  1955. }
  1956. if( nCount <= 0 )
  1957. return FALSE;
  1958. dKST = dKST / nCount;
  1959. if( pValue )
  1960. *pValue = dKST;
  1961. StoreToCache( nIndex, pValue );
  1962. return TRUE;
  1963. }
  1964. /***
  1965. 计算KST及其移动平均值
  1966. */
  1967. BOOL CKST::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1968. {
  1969. return CTechnique::CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1970. }