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

金融证券系统

开发平台:

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. // CREI
  18. CREI::CREI( )
  19. {
  20. SetDefaultParameters( );
  21. }
  22. CREI::CREI( CKData * pKData )
  23. : CTechnique( pKData )
  24. {
  25. SetDefaultParameters( );
  26. }
  27. CREI::~CREI()
  28. {
  29. Clear( );
  30. }
  31. void CREI::SetDefaultParameters( )
  32. {
  33. m_nDays = 8;
  34. m_itsLong = ITS_BUY;
  35. m_itsShort = ITS_SELL;
  36. }
  37. void CREI::AttachParameters( CREI & src )
  38. {
  39. m_nDays = src.m_nDays;
  40. m_itsLong = src.m_itsLong;
  41. m_itsShort = src.m_itsShort;
  42. }
  43. BOOL CREI::IsValidParameters( )
  44. {
  45. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  46. }
  47. void CREI::Clear( )
  48. {
  49. CTechnique::Clear( );
  50. }
  51. int CREI::GetSignal( int nIndex, UINT * pnCode )
  52. {
  53. if( pnCode ) *pnCode = ITSC_NOTHING;
  54. if( nIndex <= 0 )
  55. return ITS_NOTHING;
  56. double dLast, dNow;
  57. if( !Calculate( &dLast, nIndex-1, FALSE )
  58. || !Calculate( &dNow, nIndex, FALSE ) )
  59. return ITS_NOTHING;
  60. if( dLast < -0.6 && dNow > -0.6 )
  61. { // 低位做多
  62. if( pnCode ) *pnCode = ITSC_LONG;
  63. return m_itsLong;
  64. }
  65. if( dLast > 0.6 && dNow < 0.6 )
  66. { // 高位做空
  67. if( pnCode ) *pnCode = ITSC_SHORT;
  68. return m_itsShort;
  69. }
  70. return ITS_NOTHING;
  71. }
  72. BOOL CREI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  73. {
  74. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  75. }
  76. /***
  77. DIF1 = 今日最高价 - 2日前最高价
  78. DIF2 = 今日最低价 - 2日前最低价
  79. A = N日内除满足以下情况日的(DIF1+DIF2)之和
  80. 1. 2日前最高价 小于 7日前收盘价
  81. 2. 2日前最高价 小于 8日前收盘价
  82. 3. 今日前最高价 小于 5日前最低价
  83. 4. 今日前最高价 小于 6日前最低价
  84. 5. 2日前最低价 小于 7日前收盘价
  85. 6. 2日前最低价 小于 8日前收盘价
  86. 7. 今日前最低价 小于 5日前最高价
  87. 8. 今日前最低价 小于 6日前最高价
  88. REIA = N日的DIF1绝对值之和 + N日的DIF2绝对值之和
  89. REI  = A / REIA
  90. */
  91. BOOL CREI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  92. {
  93. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  94. if( m_nDays+7 > nIndex )
  95. return FALSE;
  96. if( LoadFromCache( nIndex, pValue ) )
  97. return TRUE;
  98. double dREI = 0, dREIA = 0;
  99. int nCount = 0;
  100. for( int k=nIndex; k>=8; k-- )
  101. {
  102. double dDIF1 = 0, dDIF2 = 0;
  103. int num1 = 1, num2 = 1;
  104. dDIF1 = ((double)m_pKData->ElementAt(k).m_fHigh) - m_pKData->ElementAt(k-2).m_fHigh;
  105. dDIF2 = ((double)m_pKData->ElementAt(k).m_fLow) - m_pKData->ElementAt(k-2).m_fLow;
  106. if( m_pKData->ElementAt(k-2).m_fHigh < m_pKData->ElementAt(k-7).m_fClose
  107. && m_pKData->ElementAt(k-2).m_fHigh < m_pKData->ElementAt(k-8).m_fClose
  108. && m_pKData->ElementAt(k).m_fHigh < m_pKData->ElementAt(k-5).m_fLow
  109. && m_pKData->ElementAt(k).m_fHigh < m_pKData->ElementAt(k-6).m_fLow )
  110. num1 = 0;
  111. if( m_pKData->ElementAt(k-2).m_fLow > m_pKData->ElementAt(k-7).m_fClose
  112. && m_pKData->ElementAt(k-2).m_fLow > m_pKData->ElementAt(k-8).m_fClose
  113. && m_pKData->ElementAt(k).m_fLow > m_pKData->ElementAt(k-5).m_fHigh
  114. && m_pKData->ElementAt(k).m_fLow > m_pKData->ElementAt(k-6).m_fHigh )
  115. num2 = 0;
  116. dREI += (dDIF1+dDIF2) * num1 * num2;
  117. dREIA += fabs(dDIF1) + fabs(dDIF2);
  118. nCount ++;
  119. if( nCount == m_nDays )
  120. {
  121. if( fabs(dREIA) < 1e-4 )
  122. return FALSE;
  123. if( pValue )
  124. *pValue = dREI / dREIA;
  125. StoreToCache( nIndex, pValue );
  126. return TRUE;
  127. }
  128. }
  129. return FALSE;
  130. }
  131. //////////////////////////////////////////////////////////////////////
  132. // CDMKI
  133. CDMKI::CDMKI( )
  134. {
  135. SetDefaultParameters( );
  136. }
  137. CDMKI::CDMKI( CKData * pKData )
  138. : CTechnique( pKData )
  139. {
  140. SetDefaultParameters( );
  141. }
  142. CDMKI::~CDMKI()
  143. {
  144. Clear( );
  145. }
  146. void CDMKI::SetDefaultParameters( )
  147. {
  148. m_nDays = 13;
  149. m_itsSold = ITS_BUY;
  150. m_itsBought = ITS_SELL;
  151. }
  152. void CDMKI::AttachParameters( CDMKI & src )
  153. {
  154. m_nDays = src.m_nDays;
  155. m_itsSold = src.m_itsSold;
  156. m_itsBought = src.m_itsBought;
  157. }
  158. BOOL CDMKI::IsValidParameters( )
  159. {
  160. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  161. }
  162. void CDMKI::Clear( )
  163. {
  164. CTechnique::Clear( );
  165. }
  166. int CDMKI::GetSignal( int nIndex, UINT * pnCode )
  167. {
  168. if( pnCode ) *pnCode = ITSC_NOTHING;
  169. double dDMKI;
  170. if( !Calculate( &dDMKI, nIndex, FALSE ) )
  171. return ITS_NOTHING;
  172. if( dDMKI < 0.3 )
  173. { // 超卖
  174. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  175. return m_itsSold;
  176. }
  177. if( dDMKI > 0.7 )
  178. { // 超买
  179. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  180. return m_itsBought;
  181. }
  182. return ITS_NOTHING;
  183. }
  184. BOOL CDMKI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  185. {
  186. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  187. }
  188. /***
  189. DMH = N日内最高价大于昨日最高价日的 (最高价-昨日最高价)
  190. DML = N日内最低价小于昨日最低价日的 (昨日最低价-最低价)
  191. DMKI = DMH / (DMH+DML)
  192. */
  193. BOOL CDMKI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  194. {
  195. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  196. if( m_nDays > nIndex )
  197. return FALSE;
  198. if( LoadFromCache( nIndex, pValue ) )
  199. return TRUE;
  200. double dDMH = 0, dDML = 0;
  201. int nCount = 0;
  202. for( int k=nIndex; k>=1; k-- )
  203. {
  204. KDATA kd = m_pKData->ElementAt(k);
  205. KDATA kdLast = m_pKData->ElementAt(k-1);
  206. if( kd.m_fHigh > kdLast.m_fHigh )
  207. dDMH += (((double)kd.m_fHigh)-kdLast.m_fHigh);
  208. if( kd.m_fLow < kdLast.m_fLow )
  209. dDML += (((double)kdLast.m_fLow)-kd.m_fLow);
  210. nCount ++;
  211. if( nCount == m_nDays )
  212. {
  213. if( fabs(dDMH + dDML) < 1e-4 )
  214. return FALSE;
  215. if( pValue ) *pValue = dDMH / (dDMH+dDML);
  216. StoreToCache( nIndex, pValue );
  217. return TRUE;
  218. }
  219. }
  220. return FALSE;
  221. }
  222. //////////////////////////////////////////////////////////////////////
  223. // CPCNT
  224. CPCNT::CPCNT( )
  225. {
  226. SetDefaultParameters( );
  227. }
  228. CPCNT::CPCNT( CKData * pKData )
  229. : CTechnique( pKData )
  230. {
  231. SetDefaultParameters( );
  232. }
  233. CPCNT::~CPCNT()
  234. {
  235. Clear( );
  236. }
  237. void CPCNT::SetDefaultParameters( )
  238. {
  239. m_nMADays = 6;
  240. m_itsGoldenFork = ITS_BUY;
  241. m_itsDeadFork = ITS_SELL;
  242. }
  243. void CPCNT::AttachParameters( CPCNT & src )
  244. {
  245. m_nMADays = src.m_nMADays;
  246. m_itsGoldenFork = src.m_itsGoldenFork;
  247. m_itsDeadFork = src.m_itsDeadFork;
  248. }
  249. BOOL CPCNT::IsValidParameters( )
  250. {
  251. return ( VALID_DAYS(m_nMADays) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  252. }
  253. void CPCNT::Clear( )
  254. {
  255. CTechnique::Clear( );
  256. }
  257. int CPCNT::GetSignal( int nIndex, UINT * pnCode )
  258. {
  259. if( pnCode ) *pnCode = ITSC_NOTHING;
  260. int nMaxDays = m_nMADays;
  261. double dLiminalLow = 0, dLiminalHigh = 0;
  262. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.5, 0.5 ) )
  263. return ITS_NOTHING;
  264. double dPCNT;
  265. if( !Calculate( &dPCNT, nIndex, FALSE ) )
  266. return ITS_NOTHING;
  267. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  268. if( dPCNT < dLiminalLow && nSignal == m_itsGoldenFork )
  269. { // 低位金叉
  270. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  271. return m_itsGoldenFork;
  272. }
  273. if( dPCNT > dLiminalHigh && nSignal == m_itsDeadFork )
  274. { // 高位死叉
  275. if( pnCode ) *pnCode = ITSC_DEADFORK;
  276. return m_itsDeadFork;
  277. }
  278. return ITS_NOTHING;
  279. }
  280. BOOL CPCNT::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  281. {
  282. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  283. }
  284. /***
  285.          今日收盘 - N日前收盘
  286. PCNT = ———————————— × 100%
  287.               昨日收盘
  288. */
  289. BOOL CPCNT::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  290. {
  291. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  292. if( LoadFromCache( nIndex, pValue ) )
  293. return TRUE;
  294. int nDays = 1; // same as ROC with m_nDays==1
  295. if( nDays > nIndex )
  296. return FALSE;
  297. double dROC = 0;
  298. if( m_pKData->MaindataAt(nIndex-nDays) <= 0
  299. || m_pKData->MaindataAt(nIndex) <= 0 )
  300. return FALSE;
  301. double x = m_pKData->MaindataAt(nIndex);
  302. double y = m_pKData->MaindataAt(nIndex-nDays);
  303. if( pValue )
  304. *pValue = (x - y) * 100 / y;
  305. StoreToCache( nIndex, pValue );
  306. return TRUE;
  307. }
  308. /***
  309. 计算PCNT及其移动平均值
  310. */
  311. BOOL CPCNT::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  312. {
  313. return CTechnique::CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  314. }
  315. //////////////////////////////////////////////////////////////////////
  316. // CHLC
  317. CHLC::CHLC( )
  318. {
  319. SetDefaultParameters( );
  320. }
  321. CHLC::CHLC( CKData * pKData )
  322. : CTechnique( pKData )
  323. {
  324. SetDefaultParameters( );
  325. }
  326. CHLC::~CHLC()
  327. {
  328. Clear( );
  329. }
  330. void CHLC::SetDefaultParameters( )
  331. {
  332. m_nDays = 12;
  333. m_nMADays = 6;
  334. m_itsGoldenFork = ITS_BUY;
  335. m_itsDeadFork = ITS_SELL;
  336. }
  337. void CHLC::AttachParameters( CHLC & src )
  338. {
  339. m_nDays = src.m_nDays;
  340. m_nMADays = src.m_nMADays;
  341. m_itsGoldenFork = src.m_itsGoldenFork;
  342. m_itsDeadFork = src.m_itsDeadFork;
  343. }
  344. BOOL CHLC::IsValidParameters( )
  345. {
  346. return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
  347. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  348. }
  349. void CHLC::Clear( )
  350. {
  351. CTechnique::Clear( );
  352. }
  353. int CHLC::GetSignal( int nIndex, UINT * pnCode )
  354. {
  355. if( pnCode ) *pnCode = ITSC_NOTHING;
  356. int nMaxDays = m_nDays + m_nMADays;
  357. double dLiminalLow = 0, dLiminalHigh = 0;
  358. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE*3, &dLiminalLow, &dLiminalHigh, 0.4, 0.6 ) )
  359. return ITS_NOTHING;
  360. double dHLC;
  361. if( !Calculate( &dHLC, nIndex, FALSE ) )
  362. return ITS_NOTHING;
  363. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  364. if( nSignal == m_itsGoldenFork )
  365. { // 低位金叉
  366. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  367. return m_itsGoldenFork;
  368. }
  369. if( nSignal == m_itsDeadFork )
  370. { // 高位死叉
  371. if( pnCode ) *pnCode = ITSC_DEADFORK;
  372. return m_itsDeadFork;
  373. }
  374. return ITS_NOTHING;
  375. }
  376. BOOL CHLC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  377. {
  378. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  379. }
  380. /***
  381. TP = (收盘价+收盘价+最高价+最低价)/4
  382. HLC = N日TP平均值
  383. */
  384. BOOL CHLC::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  385. {
  386. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  387. if( m_nDays > nIndex+1 )
  388. return FALSE;
  389. if( LoadFromCache( nIndex, pValue ) )
  390. return TRUE;
  391. double dMATP = 0;
  392. int nCount = 0;
  393. for( int k=nIndex; k>=0; k-- )
  394. {
  395. KDATA kd = m_pKData->ElementAt(k);
  396. double dTP = (kd.m_fHigh+kd.m_fLow+kd.m_fClose*2)/4.;
  397. dMATP += dTP;
  398. nCount ++;
  399. if( nCount == m_nDays )
  400. {
  401. if( pValue ) *pValue = dMATP / m_nDays;
  402. StoreToCache( nIndex, pValue );
  403. return TRUE;
  404. }
  405. }
  406. return FALSE;
  407. }
  408. /***
  409. 计算HLC及其移动平均值
  410. */
  411. BOOL CHLC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  412. {
  413. return CTechnique::CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  414. }
  415. //////////////////////////////////////////////////////////////////////
  416. // CCDP
  417. CCDP::CCDP( )
  418. {
  419. SetDefaultParameters( );
  420. }
  421. CCDP::CCDP( CKData * pKData )
  422. : CTechnique( pKData )
  423. {
  424. SetDefaultParameters( );
  425. }
  426. CCDP::~CCDP()
  427. {
  428. Clear( );
  429. }
  430. void CCDP::SetDefaultParameters( )
  431. {
  432. }
  433. void CCDP::AttachParameters( CCDP & src )
  434. {
  435. }
  436. BOOL CCDP::IsValidParameters( )
  437. {
  438. return TRUE;
  439. }
  440. void CCDP::Clear( )
  441. {
  442. CTechnique::Clear( );
  443. }
  444. int CCDP::GetSignal( int nIndex, UINT * pnCode )
  445. {
  446. if( pnCode ) *pnCode = ITSC_NOTHING;
  447. // 无买卖信号
  448. return ITS_NOTHING;
  449. }
  450. BOOL CCDP::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  451. {
  452. return AfxGetMinMaxInfo4( nStart, nEnd, pdMin, pdMax, this );
  453. }
  454. /***
  455. TP = (昨日收盘价+昨日收盘价+昨日最高价+昨日最低价)/4
  456. AH = TP + 昨日最高价 - 昨日最低价
  457. AL = TP - 最日最高价 + 昨日最低价
  458. NH = TP + TP - 最日最低价
  459. NL = TP + TP - 最日最高价
  460. */
  461. BOOL CCDP::Calculate( double * pAH, double * pNH, double * pAL, double * pNL, int nIndex, BOOL bUseLast )
  462. {
  463. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  464. if( nIndex < 1 )
  465. return FALSE;
  466. if( LoadFromCache( nIndex, pAH, pNH, pAL, pNL ) )
  467. return TRUE;
  468. KDATA kdLast = m_pKData->ElementAt(nIndex-1);
  469. double dTP = (kdLast.m_fHigh+kdLast.m_fLow+kdLast.m_fClose*2)/4.;
  470. if( pAH ) *pAH = (dTP + kdLast.m_fHigh - kdLast.m_fLow);
  471. if( pNH ) *pNH = (dTP + dTP - kdLast.m_fLow);
  472. if( pAL ) *pAL = (dTP - kdLast.m_fHigh + kdLast.m_fLow);
  473. if( pNL ) *pNL = (dTP - kdLast.m_fHigh + dTP);
  474. StoreToCache( nIndex, pAH, pNH, pAL, pNL );
  475. return TRUE;
  476. }
  477. //////////////////////////////////////////////////////////////////////
  478. // CASI
  479. CASI::CASI( )
  480. {
  481. SetDefaultParameters( );
  482. }
  483. CASI::CASI( CKData * pKData )
  484. : CTechnique( pKData )
  485. {
  486. SetDefaultParameters( );
  487. }
  488. CASI::~CASI()
  489. {
  490. Clear( );
  491. }
  492. void CASI::SetDefaultParameters( )
  493. {
  494. m_nDays = 6;
  495. m_itsDeviateOnBottom = ITS_BUY;
  496. m_itsDeviateOnTop = ITS_SELL;
  497. }
  498. void CASI::AttachParameters( CASI & src )
  499. {
  500. m_nDays = src.m_nDays;
  501. m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
  502. m_itsDeviateOnTop = src.m_itsDeviateOnTop;
  503. }
  504. BOOL CASI::IsValidParameters( )
  505. {
  506. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop) );
  507. }
  508. void CASI::Clear( )
  509. {
  510. CTechnique::Clear( );
  511. }
  512. int CASI::GetSignal( int nIndex, UINT * pnCode )
  513. {
  514. if( pnCode ) *pnCode = ITSC_NOTHING;
  515. int nMaxDays = m_nDays;
  516. double dLiminalLow = 0, dLiminalHigh = 0;
  517. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
  518. return ITS_NOTHING;
  519. if( IsDeviateOnBottom( nIndex, m_pdCache1, m_pdCache2 ) )
  520. { // 底背离
  521. if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
  522. return m_itsDeviateOnBottom;
  523. }
  524. if( IsDeviateOnTop( nIndex, m_pdCache1, m_pdCache2 ) )
  525. { // 顶背离
  526. if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
  527. return m_itsDeviateOnTop;
  528. }
  529. return ITS_NOTHING;
  530. }
  531. BOOL CASI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  532. {
  533. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  534. }
  535. /***
  536. A = 今最高 - 昨收盘
  537. B = 今最低 - 昨最低
  538. C = 今最高 - 昨最低
  539. D = 昨收盘 - 昨开盘
  540. E = 今收盘 - 昨收盘
  541. F = 今收盘 - 昨开盘
  542. G = 昨收盘 - 昨开盘
  543. X = E + 1/(2F) + G
  544. K = A、B二者之间较大者
  545. 比较A、B、C三者的大小
  546. 若A大,则R = A+1/(2B)+1/(4D)
  547. 若B大,则R = B+1/(2A)+1/(4D)
  548. 若C大,则R = C+1/(4D)
  549. L = 3
  550. SI = 50·X·K/(R·L)
  551. ASI = N日SI之和
  552. */
  553. BOOL CASI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  554. {
  555. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  556. if( m_nDays > nIndex )
  557. return FALSE;
  558. if( LoadFromCache( nIndex, pValue ) )
  559. return TRUE;
  560. double dASI = 0;
  561. double A, B, C, D, E, F, G;
  562. double R, X, K, SI;
  563. int nCount = 0;
  564. for( int k=nIndex; k>=1; k-- )
  565. {
  566. KDATA kd = m_pKData->ElementAt(k);
  567. KDATA kdLast = m_pKData->ElementAt(k-1);
  568. A = fabs(((double)kd.m_fHigh) - kdLast.m_fClose);
  569. B = fabs(((double)kd.m_fLow) - kdLast.m_fClose);
  570. C = fabs(((double)kd.m_fHigh) - kdLast.m_fLow);
  571. D = fabs(((double)kdLast.m_fClose) - kdLast.m_fOpen);
  572. E = ((double)kd.m_fClose) - kdLast.m_fClose;
  573. F = ((double)kd.m_fClose) - kd.m_fOpen;
  574. G = ((double)kdLast.m_fClose) - kdLast.m_fOpen;
  575. if( fabs(A) < 1e-4 || fabs(B) < 1e-4 || fabs(D) < 1e-4 || fabs(F) < 1e-4 )
  576. continue;
  577. if( A >= B && A >= C )
  578. R = A + 1/(2*B) + 1/(4*D);
  579. else if( B >= A && B >= C )
  580. R = B + 1/(2*A) + 1/(4*D);
  581. else
  582. R = C + 1/(4*D);
  583. if( fabs(R) < 1e-4 )
  584. continue;
  585. X = E + 1/(2*F) + G;
  586. K = ( A > B ? A : B );
  587. SI = X * K * 50 / (3*R);
  588. dASI += SI;
  589. nCount ++;
  590. if( nCount == m_nDays )
  591. {
  592. if( pValue ) *pValue = dASI;
  593. StoreToCache( nIndex, pValue );
  594. return TRUE;
  595. }
  596. }
  597. return FALSE;
  598. }
  599. //////////////////////////////////////////////////////////////////////
  600. // CATR
  601. CATR::CATR( )
  602. {
  603. SetDefaultParameters( );
  604. }
  605. CATR::CATR( CKData * pKData )
  606. : CTechnique( pKData )
  607. {
  608. SetDefaultParameters( );
  609. }
  610. CATR::~CATR()
  611. {
  612. Clear( );
  613. }
  614. void CATR::SetDefaultParameters( )
  615. {
  616. m_nDays = 14;
  617. m_itsSold = ITS_BUY;
  618. m_itsBought = ITS_SELL;
  619. }
  620. void CATR::AttachParameters( CATR & src )
  621. {
  622. m_nDays = src.m_nDays;
  623. m_itsSold = src.m_itsSold;
  624. m_itsBought = src.m_itsBought;
  625. }
  626. BOOL CATR::IsValidParameters( )
  627. {
  628. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  629. }
  630. void CATR::Clear( )
  631. {
  632. CTechnique::Clear( );
  633. }
  634. int CATR::GetSignal( int nIndex, UINT * pnCode )
  635. {
  636. if( pnCode ) *pnCode = ITSC_NOTHING;
  637. int nMaxDays = m_nDays;
  638. double dLiminalLow = 0, dLiminalHigh = 0;
  639. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
  640. return ITS_NOTHING;
  641. double dATR;
  642. if( !Calculate( &dATR, nIndex, FALSE ) )
  643. return ITS_NOTHING;
  644. if( dATR > dLiminalHigh )
  645. { // 超卖
  646. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  647. return m_itsSold;
  648. }
  649. if( dATR < dLiminalLow )
  650. { // 超买
  651. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  652. return m_itsBought;
  653. }
  654. return ITS_NOTHING;
  655. }
  656. BOOL CATR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  657. {
  658. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  659. }
  660. /***
  661. TR 为以下三者中的最大值
  662. 最高价-最低价,(昨日收盘价-今日最高价)的绝对值,昨日收盘价-昨日最低价
  663. ATR = TR的N日平均
  664. */
  665. BOOL CATR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  666. {
  667. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  668. if( m_nDays > nIndex )
  669. return FALSE;
  670. if( LoadFromCache( nIndex, pValue ) )
  671. return TRUE;
  672. double dATR = 0;
  673. int nCount = 0;
  674. for( int k=nIndex; k>=1; k-- )
  675. {
  676. KDATA kd = m_pKData->ElementAt(k);
  677. KDATA kdLast = m_pKData->ElementAt(k-1);
  678. double dTR = fabs(((double)kd.m_fHigh)-kd.m_fLow);
  679. if( fabs(((double)kdLast.m_fClose)-kd.m_fHigh) > dTR )
  680. dTR = fabs(((double)kdLast.m_fClose)-kd.m_fHigh);
  681. if( fabs(((double)kdLast.m_fClose)-kdLast.m_fLow) > dTR )
  682. dTR = fabs(((double)kdLast.m_fClose)-kdLast.m_fLow);
  683. dATR += dTR;
  684. nCount ++;
  685. if( nCount == m_nDays )
  686. {
  687. if( pValue ) *pValue = dATR/m_nDays;
  688. StoreToCache( nIndex, pValue );
  689. return TRUE;
  690. }
  691. }
  692. return FALSE;
  693. }