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

金融证券系统

开发平台:

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. // CVOLUME
  18. CVOLUME::CVOLUME( )
  19. {
  20. SetDefaultParameters( );
  21. }
  22. CVOLUME::CVOLUME( CKData * pKData )
  23. : CTechnique( pKData )
  24. {
  25. SetDefaultParameters( );
  26. }
  27. CVOLUME::~CVOLUME()
  28. {
  29. Clear( );
  30. }
  31. void CVOLUME::SetDefaultParameters( )
  32. {
  33. m_adwMADays.RemoveAll();
  34. m_adwMADays.Add( 5 );
  35. m_adwMADays.Add( 10 );
  36. m_itsDeviateOnBottom = ITS_BUYINTENSE;
  37. m_itsDeviateOnTop = ITS_SELLINTENSE;
  38. m_itsLong = ITS_BUY;
  39. m_itsShort = ITS_SELL;
  40. }
  41. void CVOLUME::AttachParameters( CVOLUME & src )
  42. {
  43. m_adwMADays.Copy( src.m_adwMADays );
  44. m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
  45. m_itsDeviateOnTop = src.m_itsDeviateOnTop;
  46. m_itsLong = src.m_itsLong;
  47. m_itsShort = src.m_itsShort;
  48. }
  49. BOOL CVOLUME::IsValidParameters( )
  50. {
  51. STT_VALID_DAYSARRAY( m_adwMADays );
  52. return ( VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop)
  53. && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  54. }
  55. void CVOLUME::Clear( )
  56. {
  57. CTechnique::Clear( );
  58. }
  59. int CVOLUME::GetSignal( int nIndex, UINT * pnCode )
  60. {
  61. if( pnCode ) *pnCode = ITSC_NOTHING;
  62. if( !m_pKData || nIndex < 0 || nIndex >= m_pKData->GetSize() )
  63. return ITS_NOTHING;
  64. int nIntensity = GetTrendIntensity( nIndex, m_adwMADays, m_itsLong, m_itsShort, pnCode );
  65. if( ITS_BUY == nIntensity
  66. && m_pKData->IsNewValue( nIndex, FALSE, ITS_DAYS_DEVIATE ) )
  67. { // 底背离,股价创新低并且成交量趋势向上
  68. if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
  69. return m_itsDeviateOnBottom;
  70. }
  71. if( ITS_SELL == nIntensity
  72. && m_pKData->IsNewValue( nIndex, TRUE, ITS_DAYS_DEVIATE ) )
  73. { // 顶背离,股价创新高并且成交量趋势向下
  74. if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
  75. return m_itsDeviateOnTop;
  76. }
  77. return nIntensity;
  78. }
  79. BOOL CVOLUME::GetMinMaxInfo(int nStart, int nEnd,
  80.    double *pdMin, double *pdMax )
  81. {
  82. STT_ASSERT_GETMINMAXINFO( m_pKData, nStart, nEnd );
  83. double dMin = 0;
  84. double dMax = 1;
  85. for( int k=nStart; k<=nEnd; k++ )
  86. {
  87. KDATA & kd = m_pKData->ElementAt(k);
  88. if( dMax < kd.m_fVolume )
  89. dMax = (double)kd.m_fVolume;
  90. }
  91. dMax = dMax + 1;
  92. if( dMax - dMin < 3 )
  93. dMax = dMin + 3;
  94. if( pdMin ) *pdMin = dMin;
  95. if( pdMax ) *pdMax = dMax;
  96. return TRUE;
  97. }
  98. /***
  99. 计算nDays的平均成交量
  100. */
  101. BOOL CVOLUME::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
  102. {
  103. STT_ASSERT_CALCULATE( m_pKData, nIndex, nDays );
  104. int nCount = 0;
  105. if( nDays > nIndex+1 )
  106. return FALSE;
  107. double dResult = 0;
  108. for( int k=nIndex; k>=0; k-- )
  109. {
  110. dResult += m_pKData->ElementAt(k).m_fVolume;
  111. nCount ++;
  112. if( nCount == nDays )
  113. {
  114. if( pValue )
  115. *pValue = dResult / nDays;
  116. return TRUE;
  117. }
  118. }
  119. return FALSE;
  120. }
  121. //////////////////////////////////////////////////////////////////////
  122. // CNVI
  123. CNVI::CNVI( )
  124. {
  125. SetDefaultParameters( );
  126. }
  127. CNVI::CNVI( CKData * pKData )
  128. : CTechnique( pKData )
  129. {
  130. SetDefaultParameters( );
  131. }
  132. CNVI::~CNVI()
  133. {
  134. Clear( );
  135. }
  136. void CNVI::SetDefaultParameters( )
  137. {
  138. m_nMADays = 25;
  139. m_itsGoldenFork = ITS_BUY;
  140. m_itsDeadFork = ITS_SELL;
  141. }
  142. void CNVI::AttachParameters( CNVI & src )
  143. {
  144. m_nMADays = src.m_nMADays;
  145. m_itsGoldenFork = src.m_itsGoldenFork;
  146. m_itsDeadFork = src.m_itsDeadFork;
  147. }
  148. BOOL CNVI::IsValidParameters( )
  149. {
  150. return ( VALID_DAYS( m_nMADays ) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  151. }
  152. void CNVI::Clear( )
  153. {
  154. CTechnique::Clear( );
  155. }
  156. int CNVI::GetSignal( int nIndex, UINT * pnCode )
  157. {
  158. PrepareCache( 0, -1, FALSE );
  159. // 金叉死叉
  160. return GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  161. }
  162. BOOL CNVI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  163. {
  164. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  165. }
  166. /***
  167. NVI初值 = 100
  168. 如果今天成交量比昨日小 NVI = 前一日NVI + 100 * 涨跌幅 否则,NVI = 前一天NVI
  169. */
  170. BOOL CNVI::Calculate( double * pValue, double *pMA, int nIndex, BOOL bUseLast )
  171. {
  172. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  173. // Calculate
  174. if( m_nMADays > nIndex+1 )
  175. return FALSE;
  176. if( LoadFromCache( nIndex, pValue, pMA ) )
  177. return TRUE;
  178. double dValueNew = 0, dMANew = 0;
  179. if( bUseLast && pValue && pMA )
  180. {
  181. if( 0 == nIndex )
  182. dValueNew = 100;
  183. else if( m_pKData->ElementAt(nIndex).m_fVolume < m_pKData->ElementAt(nIndex-1).m_fVolume
  184. && m_pKData->MaindataAt(nIndex-1) > 1e-4 && m_pKData->MaindataAt(nIndex) > 1e-4 )
  185. dValueNew = (*pValue) * m_pKData->MaindataAt(nIndex) / m_pKData->MaindataAt(nIndex-1);
  186. else
  187. dValueNew = *pValue;
  188. dMANew = (*pMA) * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1);
  189. StoreToCache( nIndex, &dValueNew, &dMANew );
  190. }
  191. else
  192. {
  193. for( int k=0; k<=nIndex; k++ )
  194. {
  195. if( 0 == k )
  196. dValueNew = 100;
  197. else if( m_pKData->ElementAt(k).m_fVolume < m_pKData->ElementAt(k-1).m_fVolume
  198. && m_pKData->MaindataAt(k-1) > 1e-4 && m_pKData->MaindataAt(k) > 1e-4 )
  199. dValueNew = dValueNew * m_pKData->MaindataAt(k) / m_pKData->MaindataAt(k-1);
  200. if( 0 == k )
  201. dMANew = dValueNew;
  202. else
  203. dMANew = dMANew * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1);
  204. StoreToCache( k, &dValueNew, &dMANew );
  205. }
  206. }
  207. if( pValue ) *pValue = dValueNew;
  208. if( pMA ) *pMA = dMANew;
  209. return TRUE;
  210. }
  211. //////////////////////////////////////////////////////////////////////
  212. // CPVI
  213. CPVI::CPVI( )
  214. {
  215. SetDefaultParameters( );
  216. }
  217. CPVI::CPVI( CKData * pKData )
  218. : CTechnique( pKData )
  219. {
  220. SetDefaultParameters( );
  221. }
  222. CPVI::~CPVI()
  223. {
  224. Clear( );
  225. }
  226. void CPVI::SetDefaultParameters( )
  227. {
  228. m_nMADays = 25;
  229. m_itsGoldenFork = ITS_BUY;
  230. m_itsDeadFork = ITS_SELL;
  231. }
  232. void CPVI::AttachParameters( CPVI & src )
  233. {
  234. m_nMADays = src.m_nMADays;
  235. m_itsGoldenFork = src.m_itsGoldenFork;
  236. m_itsDeadFork = src.m_itsDeadFork;
  237. }
  238. BOOL CPVI::IsValidParameters( )
  239. {
  240. return ( VALID_DAYS( m_nMADays ) && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  241. }
  242. void CPVI::Clear( )
  243. {
  244. CTechnique::Clear( );
  245. }
  246. int CPVI::GetSignal( int nIndex, UINT * pnCode )
  247. {
  248. PrepareCache( 0, -1, FALSE );
  249. // 金叉死叉
  250. return GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  251. }
  252. BOOL CPVI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  253. {
  254. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  255. }
  256. /***
  257. PVI初值100
  258. 如果今天成交量比昨日大 PVI = 前一日PVI + 100 * 涨跌幅 否则,PVI = 前一日PVI
  259. */
  260. BOOL CPVI::Calculate( double * pValue, double *pMA, int nIndex, BOOL bUseLast )
  261. {
  262. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  263. // Calculate
  264. if( m_nMADays > nIndex+1 )
  265. return FALSE;
  266. if( LoadFromCache( nIndex, pValue, pMA ) )
  267. return TRUE;
  268. double dValueNew = 0, dMANew = 0;
  269. if( bUseLast && pValue && pMA )
  270. {
  271. if( 0 == nIndex )
  272. dValueNew = 100;
  273. else if( m_pKData->ElementAt(nIndex).m_fVolume > m_pKData->ElementAt(nIndex-1).m_fVolume
  274. && m_pKData->MaindataAt(nIndex-1) > 1e-4 && m_pKData->MaindataAt(nIndex) > 1e-4 )
  275. dValueNew = (*pValue) * m_pKData->MaindataAt(nIndex) / m_pKData->MaindataAt(nIndex-1);
  276. else
  277. dValueNew = *pValue;
  278. dMANew = (*pMA) * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1);
  279. StoreToCache( nIndex, &dValueNew, &dMANew );
  280. }
  281. else
  282. {
  283. for( int k=0; k<=nIndex; k++ )
  284. {
  285. if( 0 == k )
  286. dValueNew = 100;
  287. else if( m_pKData->ElementAt(k).m_fVolume > m_pKData->ElementAt(k-1).m_fVolume
  288. && m_pKData->MaindataAt(k-1) > 1e-4 && m_pKData->MaindataAt(k) > 1e-4 )
  289. dValueNew = dValueNew * m_pKData->MaindataAt(k) / m_pKData->MaindataAt(k-1);
  290. if( 0 == k )
  291. dMANew = dValueNew;
  292. else
  293. dMANew = dMANew * (m_nMADays-1) / (m_nMADays+1) + dValueNew * 2 / (m_nMADays+1);
  294. StoreToCache( k, &dValueNew, &dMANew );
  295. }
  296. }
  297. if( pValue ) *pValue = dValueNew;
  298. if( pMA ) *pMA = dMANew;
  299. return TRUE;
  300. }
  301. //////////////////////////////////////////////////////////////////////
  302. // CVR
  303. CVR::CVR( )
  304. {
  305. SetDefaultParameters( );
  306. }
  307. CVR::CVR( CKData * pKData )
  308. : CTechnique( pKData )
  309. {
  310. SetDefaultParameters( );
  311. }
  312. CVR::~CVR()
  313. {
  314. Clear( );
  315. }
  316. void CVR::SetDefaultParameters( )
  317. {
  318. m_nDays = 12;
  319. m_itsLong = ITS_BUY;
  320. m_itsShort = ITS_SELL;
  321. }
  322. void CVR::AttachParameters( CVR & src )
  323. {
  324. m_nDays = src.m_nDays;
  325. m_itsLong = src.m_itsLong;
  326. m_itsShort = src.m_itsShort;
  327. }
  328. BOOL CVR::IsValidParameters( )
  329. {
  330. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  331. }
  332. void CVR::Clear( )
  333. {
  334. CTechnique::Clear( );
  335. }
  336. int CVR::GetSignal( int nIndex, UINT * pnCode )
  337. {
  338. if( pnCode ) *pnCode = ITSC_NOTHING;
  339. if( !m_pKData || nIndex < 0 || nIndex >= m_pKData->GetSize() )
  340. return ITS_NOTHING;
  341. int nMaxDays = m_nDays;
  342. double dLiminalLow = 0, dLiminalHigh = 0;
  343. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.309, 0.682 ) )
  344. return ITS_NOTHING;
  345. double dNowClose = m_pKData->ElementAt(nIndex).m_fClose;
  346. double dVRNow;
  347. if( !Calculate( &dVRNow, nIndex, FALSE ) )
  348. return ITS_NOTHING;
  349. int nIntensity = GetTrendIntensity1( nIndex, m_itsLong, m_itsShort, pnCode );
  350. if( dVRNow < dLiminalLow && nIntensity == m_itsLong )
  351. { // 低位趋势向上
  352. if( pnCode ) *pnCode = ITSC_LONG;
  353. return m_itsLong;
  354. }
  355. if( dVRNow > dLiminalHigh && nIntensity == m_itsShort )
  356. { // 高位趋势向下
  357. if( pnCode ) *pnCode = ITSC_SHORT;
  358. return m_itsShort;
  359. }
  360. return ITS_NOTHING;
  361. }
  362. BOOL CVR::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  363. {
  364. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  365. }
  366. /***
  367.      n日中上涨日成交量+1/2最近n日总成交量
  368. VR = ————————————---------—- ×100
  369.      n日中下跌日成交量+1/2最近n日总成交量
  370. */
  371. BOOL CVR::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  372. {
  373. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  374. if( m_nDays > nIndex )
  375. return FALSE;
  376. if( LoadFromCache( nIndex, pValue ) )
  377. return TRUE;
  378. double dINTV = 0, dDETV = 0, dTV = 0;
  379. int nCount = 0;
  380. for( int k=nIndex; k>=1; k-- )
  381. {
  382. double dAmount = m_pKData->ElementAt(k).m_fVolume;
  383. if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) )
  384. dINTV += dAmount;
  385. if( m_pKData->MaindataAt(k) < m_pKData->MaindataAt(k-1) )
  386. dDETV += dAmount;
  387. dTV += dAmount;
  388. nCount ++;
  389. if( nCount == m_nDays )
  390. {
  391. if( dDETV + dTV/2 < 1e-4 )
  392. return FALSE;
  393. if( pValue ) *pValue = (dINTV + dTV/2) * 100 /(dDETV + dTV/2);
  394. StoreToCache( nIndex, pValue );
  395. return TRUE;
  396. }
  397. }
  398. return FALSE;
  399. }
  400. //////////////////////////////////////////////////////////////////////
  401. // CVROC
  402. CVROC::CVROC( )
  403. {
  404. SetDefaultParameters( );
  405. }
  406. CVROC::CVROC( CKData * pKData )
  407. : CTechnique( pKData )
  408. {
  409. SetDefaultParameters( );
  410. }
  411. CVROC::~CVROC()
  412. {
  413. Clear( );
  414. }
  415. void CVROC::SetDefaultParameters( )
  416. {
  417. m_nDays = 10;
  418. m_nMADays = 10;
  419. m_itsDeviateOnBottom = ITS_BUY;
  420. m_itsDeviateOnTop = ITS_SELL;
  421. }
  422. void CVROC::AttachParameters( CVROC & src )
  423. {
  424. m_nDays = src.m_nDays;
  425. m_nMADays = src.m_nMADays;
  426. m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
  427. m_itsDeviateOnTop = src.m_itsDeviateOnTop;
  428. }
  429. BOOL CVROC::IsValidParameters( )
  430. {
  431. return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
  432. && VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop) );
  433. }
  434. void CVROC::Clear( )
  435. {
  436. CTechnique::Clear( );
  437. }
  438. int CVROC::GetSignal( int nIndex, UINT * pnCode )
  439. {
  440. if( pnCode ) *pnCode = ITSC_NOTHING;
  441. int nMaxDays = m_nDays+m_nMADays;
  442. double dLiminalLow = 0, dLiminalHigh = 0;
  443. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
  444. return ITS_NOTHING;
  445. if( IsDeviateOnBottom( nIndex, m_pdCache1, m_pdCache2 ) )
  446. { // 底背离
  447. if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
  448. return m_itsDeviateOnBottom;
  449. }
  450. if( IsDeviateOnTop( nIndex, m_pdCache1, m_pdCache2 ) )
  451. { // 顶背离
  452. if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
  453. return m_itsDeviateOnTop;
  454. }
  455. return ITS_NOTHING;
  456. }
  457. BOOL CVROC::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  458. {
  459. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  460. }
  461. /***
  462.           今日成交量-n日前成交量
  463. VROC =   ---------------------- * 100
  464.               今日成交量
  465. */
  466. BOOL CVROC::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  467. {
  468. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  469. if( m_nDays > nIndex )
  470. return FALSE;
  471. if( LoadFromCache( nIndex, pValue ) )
  472. return TRUE;
  473. if( m_pKData->ElementAt(nIndex-m_nDays).m_fVolume <= 0
  474. || m_pKData->ElementAt(nIndex).m_fVolume <= 0 )
  475. return FALSE;
  476. double x = m_pKData->ElementAt(nIndex).m_fVolume;
  477. double y = m_pKData->ElementAt(nIndex-m_nDays).m_fVolume;
  478. if( pValue )
  479. *pValue = (x - y) * 100 / y;
  480. StoreToCache( nIndex, pValue );
  481. return TRUE;
  482. }
  483. BOOL CVROC::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  484. {
  485. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  486. }
  487. //////////////////////////////////////////////////////////////////////
  488. // COBV
  489. COBV::COBV( )
  490. {
  491. SetDefaultParameters( );
  492. }
  493. COBV::COBV( CKData * pKData )
  494. : CTechnique( pKData )
  495. {
  496. SetDefaultParameters( );
  497. }
  498. COBV::~COBV()
  499. {
  500. Clear( );
  501. }
  502. void COBV::SetDefaultParameters( )
  503. {
  504. m_itsDeviateOnBottom = ITS_BUY;
  505. m_itsDeviateOnTop = ITS_SELL;
  506. }
  507. void COBV::AttachParameters( COBV & src )
  508. {
  509. m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
  510. m_itsDeviateOnTop = src.m_itsDeviateOnTop;
  511. }
  512. BOOL COBV::IsValidParameters( )
  513. {
  514. return ( VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop) );
  515. }
  516. void COBV::Clear( )
  517. {
  518. CTechnique::Clear( );
  519. }
  520. int COBV::GetSignal( int nIndex, UINT * pnCode )
  521. {
  522. if( pnCode ) *pnCode = ITSC_NOTHING;
  523. PrepareCache( 0, -1, FALSE );
  524. if( IsDeviateOnBottom( nIndex, m_pdCache1, m_pdCache2 ) )
  525. { // 底背离
  526. if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
  527. return m_itsDeviateOnBottom;
  528. }
  529. if( IsDeviateOnTop( nIndex, m_pdCache1, m_pdCache2 ) )
  530. { // 顶背离
  531. if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
  532. return m_itsDeviateOnTop;
  533. }
  534. return ITS_NOTHING;
  535. }
  536. BOOL COBV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  537. {
  538. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  539. }
  540. /***
  541. 当日收盘价比前一日收盘价高,其成交量记为正数
  542. 当日收盘价较前一日收盘价低,其成交量记为负数
  543. 累计每日之正或负成交量,即得OBV值
  544. */
  545. BOOL COBV::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  546. {
  547. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  548. if( LoadFromCache( nIndex, pValue ) )
  549. return TRUE;
  550. // Calculate
  551. double dValueNew = 0;
  552. if( bUseLast && pValue )
  553. {
  554. if( 0 == nIndex )
  555. dValueNew = m_pKData->ElementAt(nIndex).m_fVolume;
  556. else if( m_pKData->MaindataAt(nIndex) > m_pKData->MaindataAt(nIndex-1) )
  557. dValueNew = *pValue + m_pKData->ElementAt(nIndex).m_fVolume;
  558. else if( m_pKData->MaindataAt(nIndex) < m_pKData->MaindataAt(nIndex-1) )
  559. dValueNew = *pValue - m_pKData->ElementAt(nIndex).m_fVolume;
  560. else
  561. dValueNew = *pValue;
  562. StoreToCache( nIndex, &dValueNew );
  563. }
  564. else
  565. {
  566. for( int k=0; k<=nIndex; k++ )
  567. {
  568. if( 0 == k )
  569. dValueNew = m_pKData->ElementAt(k).m_fVolume;
  570. else if( m_pKData->MaindataAt(k) > m_pKData->MaindataAt(k-1) )
  571. dValueNew += m_pKData->ElementAt(k).m_fVolume;
  572. else if( m_pKData->MaindataAt(k) < m_pKData->MaindataAt(k-1) )
  573. dValueNew -= m_pKData->ElementAt(k).m_fVolume;
  574. StoreToCache( k, &dValueNew );
  575. }
  576. }
  577. if( pValue )
  578. *pValue = dValueNew;
  579. return TRUE;
  580. }
  581. //////////////////////////////////////////////////////////////////////
  582. // CMOBV
  583. CMOBV::CMOBV( )
  584. {
  585. SetDefaultParameters( );
  586. }
  587. CMOBV::CMOBV( CKData * pKData )
  588. : COBV( pKData )
  589. {
  590. SetDefaultParameters( );
  591. }
  592. CMOBV::~CMOBV()
  593. {
  594. Clear( );
  595. }
  596. void CMOBV::SetDefaultParameters( )
  597. {
  598. COBV::SetDefaultParameters();
  599. m_nDays1 = 12;
  600. m_nDays2 = 26;
  601. m_itsGoldenFork = ITS_BUY;
  602. m_itsDeadFork = ITS_SELL;
  603. }
  604. void CMOBV::AttachParameters( CMOBV & src )
  605. {
  606. COBV::AttachParameters( src );
  607. m_nDays1 = src.m_nDays1;
  608. m_nDays2 = src.m_nDays2;
  609. m_itsGoldenFork = src.m_itsGoldenFork;
  610. m_itsDeadFork = src.m_itsDeadFork;
  611. }
  612. BOOL CMOBV::IsValidParameters( )
  613. {
  614. return ( COBV::IsValidParameters()
  615. && VALID_DAYS(m_nDays1) && VALID_DAYS(m_nDays2)
  616. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  617. }
  618. void CMOBV::Clear( )
  619. {
  620. CTechnique::Clear( );
  621. }
  622. int CMOBV::GetSignal( int nIndex, UINT * pnCode )
  623. {
  624. if( pnCode ) *pnCode = ITSC_NOTHING;
  625. if( !m_pKData || nIndex < 0 || nIndex >= m_pKData->GetSize() )
  626. return ITS_NOTHING;
  627. PrepareCache( 0, -1, FALSE );
  628. int nMaxDays = max( m_nDays1 , m_nDays2 );
  629. double dLiminalLow = 0, dLiminalHigh = 0;
  630. if( !IntensityPreparePrice( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.5, 0.5 ) )
  631. return ITS_NOTHING;
  632. double dPriceNow = m_pKData->MaindataAt(nIndex);
  633. if( dPriceNow < dLiminalLow
  634. && ( IsGoldenFork( nIndex, m_pdCache1, m_pdCache2 ) || IsGoldenFork( nIndex, m_pdCache2, m_pdCache3 ) ) )
  635. { // 低位金叉
  636. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  637. return m_itsGoldenFork;
  638. }
  639. if( dPriceNow > dLiminalHigh
  640. && ( IsDeadFork( nIndex, m_pdCache1, m_pdCache2 ) || IsDeadFork( nIndex, m_pdCache2, m_pdCache3 ) ) )
  641. { // 高位死叉
  642. if( pnCode ) *pnCode = ITSC_DEADFORK;
  643. return m_itsDeadFork;
  644. }
  645. return ITS_NOTHING;
  646. }
  647. BOOL CMOBV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  648. {
  649. return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
  650. }
  651. /***
  652. *pValue1  = 当日OBV
  653. *pValue2  = m_nDays1日OBV平均值
  654. *pValue3  = m_nDays2日OBV平均值
  655. */
  656. BOOL CMOBV::Calculate( double * pValue1, double * pValue2, double * pValue3, int nIndex, BOOL bUseLast )
  657. {
  658. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  659. int nMaxDays = max(m_nDays1,m_nDays2);
  660. if( nMaxDays > nIndex+1 )
  661. return FALSE;
  662. if( LoadFromCache( nIndex, pValue1, pValue2, pValue3 ) )
  663. return TRUE;
  664. double dOBV = 0, dMOBV1 = 0, dMOBV2 = 0;
  665. int nCount = 0;
  666. BOOL bHasLast = bUseLast;
  667. for( int k=nIndex; k>=0; k-- )
  668. {
  669. double dTemp = 0;
  670. if( bUseLast && nIndex == k && pValue1 )
  671. dTemp = *pValue1;
  672. if( COBV::Calculate( &dTemp, k, bUseLast && nIndex == k && pValue1 ) )
  673. {
  674. if( nIndex == k )
  675. dOBV = dTemp;
  676. if( nCount < m_nDays1 )
  677. dMOBV1 += dTemp;
  678. if( nCount < m_nDays2 )
  679. dMOBV2 += dTemp;
  680. nCount ++;
  681. if( nCount >= m_nDays1 && nCount >= m_nDays2 )
  682. {
  683. if( pValue1 ) *pValue1 = dOBV;
  684. if( pValue2 ) *pValue2 = dMOBV1 / m_nDays1;
  685. if( pValue3 ) *pValue3 = dMOBV2 / m_nDays2;
  686. StoreToCache( nIndex, pValue1, pValue2, pValue3 );
  687. return TRUE;
  688. }
  689. }
  690. }
  691. return FALSE;
  692. }
  693. //////////////////////////////////////////////////////////////////////
  694. // CMFI
  695. CMFI::CMFI( )
  696. {
  697. SetDefaultParameters( );
  698. }
  699. CMFI::CMFI( CKData * pKData )
  700. : CTechnique( pKData )
  701. {
  702. SetDefaultParameters( );
  703. }
  704. CMFI::~CMFI()
  705. {
  706. Clear( );
  707. }
  708. void CMFI::SetDefaultParameters( )
  709. {
  710. m_nDays = 10;
  711. m_itsLong = ITS_BUY;
  712. m_itsShort = ITS_SELL;
  713. }
  714. void CMFI::AttachParameters( CMFI & src )
  715. {
  716. m_nDays = src.m_nDays;
  717. m_itsLong = src.m_itsLong;
  718. m_itsShort = src.m_itsShort;
  719. }
  720. BOOL CMFI::IsValidParameters( )
  721. {
  722. return ( VALID_DAYS(m_nDays) && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  723. }
  724. void CMFI::Clear( )
  725. {
  726. CTechnique::Clear( );
  727. }
  728. int CMFI::GetSignal( int nIndex, UINT * pnCode )
  729. {
  730. if( pnCode ) *pnCode = ITSC_NOTHING;
  731. double dValue = 0;
  732. if( !Calculate( &dValue, nIndex, FALSE ) )
  733. return ITS_NOTHING;
  734. if( dValue <= 20 )
  735. { // 低位
  736. if( pnCode ) *pnCode = ITSC_LONG;
  737. return m_itsLong;
  738. }
  739. if( dValue >= 80 )
  740. { // 高位
  741. if( pnCode ) *pnCode = ITSC_SHORT;
  742. return m_itsShort;
  743. }
  744. return ITS_NOTHING;
  745. }
  746. BOOL CMFI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  747. {
  748. if( pdMin ) *pdMin = 0;
  749. if( pdMax ) *pdMax = 100;
  750. return TRUE;
  751. }
  752. /***
  753. PMF 和 NMF 如下计算:
  754. TP = (High+Low+Close)/3   当日的中间价
  755. PMF = n日内,TP上涨日的 (TP*成交量) 之和。
  756. NMF = n日内,TP下降日的 (TP*成交量) 之和。
  757. MFI = 100 * PMF / (PMF + NMF)
  758. 备注:MR = PMF/NMF
  759. */
  760. BOOL CMFI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  761. {
  762. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  763. if( m_nDays > nIndex )
  764. return FALSE;
  765. if( LoadFromCache( nIndex, pValue ) )
  766. return TRUE;
  767. double dPMF = 0, dNMF = 0;
  768. int nCount = 0;
  769. for( int k=nIndex; k>=1; k-- )
  770. {
  771. KDATA kd = m_pKData->ElementAt(k);
  772. KDATA kdLast = m_pKData->ElementAt(k-1);
  773. double dTP = (kd.m_fHigh+kd.m_fLow+kd.m_fClose)/3.;
  774. double dTPLast = (kdLast.m_fHigh+kdLast.m_fLow+kdLast.m_fClose)/3.;
  775. if( dTP > dTPLast )
  776. dPMF += dTP * kd.m_fVolume;
  777. if( dTPLast > dTP )
  778. dNMF += dTP * kd.m_fVolume;
  779. nCount ++;
  780. if( nCount == m_nDays )
  781. {
  782. if( fabs(dPMF+dNMF) < 1e-4 )
  783. return FALSE;
  784. if( pValue ) *pValue = 100 * dPMF / (dPMF + dNMF);
  785. StoreToCache( nIndex, pValue );
  786. return TRUE;
  787. }
  788. }
  789. return FALSE;
  790. }
  791. //////////////////////////////////////////////////////////////////////
  792. // CVMACD
  793. CVMACD::CVMACD( )
  794. {
  795. SetDefaultParameters( );
  796. }
  797. CVMACD::CVMACD( CKData * pKData )
  798. : CMACD( pKData )
  799. {
  800. SetDefaultParameters( );
  801. }
  802. CVMACD::~CVMACD()
  803. {
  804. Clear( );
  805. }
  806. /***
  807. 成交量的MACD
  808. EMA  = 短期移动均值
  809. EMA2 = 长期移动均值
  810. DIF  = 短期移动均值 - 长期移动均值
  811. DEA  = DIF的移动平滑值
  812. 柱状线值 = DIF - DEA
  813. */
  814. BOOL CVMACD::Calculate( double *pdEMA1, double *pdEMA2, double *pdDIF, double *pdDEA,
  815. int nIndex, BOOL bUseLast )
  816. {
  817. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  818. if( m_nEMA1Days > nIndex+1 || m_nEMA2Days > nIndex+1 || m_nDIFDays > nIndex+1 )
  819. return FALSE;
  820. if( LoadFromCache( nIndex, pdEMA1, pdEMA2, pdDIF, pdDEA ) )
  821. return TRUE;
  822. // Calculate EMA1, EMA2, DIF, DEA
  823. double dEMA1New = 0, dEMA2New = 0, dDIFNew = 0, dDEANew = 0;
  824. if( bUseLast && pdEMA1 && pdEMA2 && pdDEA )
  825. {
  826. dEMA1New = (*pdEMA1)*(m_nEMA1Days-1)/(m_nEMA1Days+1) + 2 * m_pKData->ElementAt(nIndex).m_fVolume/(m_nEMA1Days+1);
  827. dEMA2New = (*pdEMA2)*(m_nEMA2Days-1)/(m_nEMA2Days+1) + 2 * m_pKData->ElementAt(nIndex).m_fVolume/(m_nEMA2Days+1);
  828. dDIFNew = dEMA1New-dEMA2New;
  829. dDEANew = (*pdDEA)*(m_nDIFDays-1)/(m_nDIFDays+1) + 2 * dDIFNew/(m_nDIFDays+1);
  830. }
  831. else
  832. {
  833. double factor1 = 1, factor2 = 1;
  834. for( int k=nIndex; k > 0; k-- )
  835. {
  836. factor1 *= ((double)(m_nEMA1Days-1))/(m_nEMA1Days+1);
  837. factor2 *= ((double)(m_nEMA2Days-1))/(m_nEMA2Days+1);
  838. if( factor1 < 0.001 && factor2 < 0.001 ) // 太久以前的数据影响很小,忽略不计
  839. break;
  840. }
  841. dEMA1New = m_pKData->ElementAt(k).m_fVolume;
  842. dEMA2New = m_pKData->ElementAt(k).m_fVolume;
  843. dDIFNew = dEMA1New - dEMA2New;
  844. dDEANew = dDIFNew;
  845. for( ; k<=nIndex; k++ )
  846. {
  847. dEMA1New = dEMA1New * (m_nEMA1Days-1)/(m_nEMA1Days+1) + 2 * m_pKData->ElementAt(k).m_fVolume/(m_nEMA1Days+1);
  848. dEMA2New = dEMA2New * (m_nEMA2Days-1)/(m_nEMA2Days+1) + 2 * m_pKData->ElementAt(k).m_fVolume/(m_nEMA2Days+1);
  849. dDIFNew = dEMA1New - dEMA2New;
  850. dDEANew = dDEANew * (m_nDIFDays-1)/(m_nDIFDays+1) + 2 * dDIFNew / (m_nDIFDays+1);
  851. }
  852. }
  853. if( pdEMA1 ) *pdEMA1 = dEMA1New;
  854. if( pdEMA2 ) *pdEMA2 = dEMA2New;
  855. if( pdDIF ) *pdDIF = dDIFNew;
  856. if( pdDEA ) *pdDEA = dDEANew;
  857. StoreToCache( nIndex, pdEMA1, pdEMA2, pdDIF, pdDEA );
  858. return TRUE;
  859. }
  860. //////////////////////////////////////////////////////////////////////
  861. // CWVAD
  862. CWVAD::CWVAD( )
  863. {
  864. SetDefaultParameters( );
  865. }
  866. CWVAD::CWVAD( CKData * pKData )
  867. : CTechnique( pKData )
  868. {
  869. SetDefaultParameters( );
  870. }
  871. CWVAD::~CWVAD()
  872. {
  873. Clear( );
  874. }
  875. void CWVAD::SetDefaultParameters( )
  876. {
  877. m_nDays = 24;
  878. m_itsLong = ITS_BUY;
  879. m_itsShort = ITS_SELL;
  880. }
  881. void CWVAD::AttachParameters( CWVAD & src )
  882. {
  883. m_nDays = src.m_nDays;
  884. m_itsLong = src.m_itsLong;
  885. m_itsShort = src.m_itsShort;
  886. }
  887. BOOL CWVAD::IsValidParameters( )
  888. {
  889. return ( VALID_DAYS( m_nDays )
  890. && VALID_ITS(m_itsLong) && VALID_ITS(m_itsShort) );
  891. }
  892. void CWVAD::Clear( )
  893. {
  894. CTechnique::Clear( );
  895. }
  896. int CWVAD::GetSignal( int nIndex, UINT * pnCode )
  897. {
  898. if( pnCode ) *pnCode = ITSC_NOTHING;
  899. int nMaxDays = m_nDays;
  900. double dLiminalLow = 0, dLiminalHigh = 0;
  901. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
  902. return ITS_NOTHING;
  903. if( nIndex <= 0 )
  904. return ITS_NOTHING;
  905. double dLast, dNow;
  906. if( !Calculate( &dLast, nIndex-1, FALSE )
  907. || !Calculate( &dNow, nIndex, FALSE ) )
  908. return ITS_NOTHING;
  909. if( dNow < dLiminalLow )
  910. { // 低位
  911. if( pnCode ) *pnCode = ITSC_LONG;
  912. return m_itsLong;
  913. }
  914. if( dNow > dLiminalHigh  )
  915. { // 高位
  916. if( pnCode ) *pnCode = ITSC_SHORT;
  917. return m_itsShort;
  918. }
  919. return ITS_NOTHING;
  920. }
  921. BOOL CWVAD::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  922. {
  923. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  924. }
  925. /***
  926. A = 当天收盘价 - 当天开盘价
  927. B = 当天最高价 - 当天最低价
  928. C = A÷B×V(成交量)
  929. WVAD = 累计n天的C值
  930. */
  931. BOOL CWVAD::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  932. {
  933. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  934. if( m_nDays > nIndex+1 )
  935. return FALSE;
  936. if( LoadFromCache( nIndex, pValue ) )
  937. return TRUE;
  938. int nCount = 0;
  939. double dResult = 0;
  940. for( int k=nIndex; k>=0; k-- )
  941. {
  942. KDATA kd = m_pKData->ElementAt(k);
  943. if( kd.m_fHigh > kd.m_fLow )
  944. dResult += (((double)kd.m_fClose) - kd.m_fOpen)*kd.m_fVolume/(((double)kd.m_fHigh)-kd.m_fLow);
  945. nCount ++;
  946. if( nCount == m_nDays )
  947. {
  948. if( pValue ) *pValue = dResult;
  949. StoreToCache( nIndex, pValue );
  950. return TRUE;
  951. }
  952. }
  953. return FALSE;
  954. }
  955. //////////////////////////////////////////////////////////////////////
  956. // CEMV
  957. CEMV::CEMV( )
  958. {
  959. SetDefaultParameters( );
  960. }
  961. CEMV::CEMV( CKData * pKData )
  962. : CTechnique( pKData )
  963. {
  964. SetDefaultParameters( );
  965. }
  966. CEMV::~CEMV()
  967. {
  968. Clear( );
  969. }
  970. void CEMV::SetDefaultParameters( )
  971. {
  972. m_nDays = 14;
  973. m_nMADays = 9;
  974. m_itsGoldenFork = ITS_BUY;
  975. m_itsGoldenFork = ITS_SELL;
  976. }
  977. void CEMV::AttachParameters( CEMV & src )
  978. {
  979. m_nDays = src.m_nDays;
  980. m_nMADays = src.m_nMADays;
  981. m_itsGoldenFork = src.m_itsGoldenFork;
  982. m_itsDeadFork = src.m_itsDeadFork;
  983. }
  984. BOOL CEMV::IsValidParameters( )
  985. {
  986. return ( VALID_DAYS(m_nDays) && VALID_DAYS(m_nMADays)
  987. && VALID_ITS(m_itsGoldenFork) && VALID_ITS(m_itsDeadFork) );
  988. }
  989. void CEMV::Clear( )
  990. {
  991. CTechnique::Clear( );
  992. }
  993. int CEMV::GetSignal( int nIndex, UINT * pnCode )
  994. {
  995. if( pnCode ) *pnCode = ITSC_NOTHING;
  996. int nMaxDays = m_nDays+m_nMADays;
  997. double dLiminalLow = 0, dLiminalHigh = 0;
  998. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.5, 0.5 ) )
  999. return ITS_NOTHING;
  1000. double dEMV;
  1001. if( !Calculate( &dEMV, nIndex, FALSE ) )
  1002. return ITS_NOTHING;
  1003. int nSignal = GetForkSignal( nIndex, m_itsGoldenFork, m_itsDeadFork, pnCode );
  1004. if( dEMV < dLiminalLow && nSignal == m_itsGoldenFork )
  1005. { // 低位金叉
  1006. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  1007. return m_itsGoldenFork;
  1008. }
  1009. if( dEMV > dLiminalHigh && nSignal == m_itsDeadFork )
  1010. { // 高位死叉
  1011. if( pnCode ) *pnCode = ITSC_DEADFORK;
  1012. return m_itsDeadFork;
  1013. }
  1014. return ITS_NOTHING;
  1015. /*  FROM BOOK */
  1016. /* if( pnCode ) *pnCode = ITSC_NOTHING;
  1017. double dValue;
  1018. if( !Calculate( &dValue, nIndex, FALSE ) )
  1019. return ITS_NOTHING;
  1020. if( dValue > 0 )
  1021. {
  1022. if( pnCode ) *pnCode = ITSC_LONG;
  1023. return m_itsLong;
  1024. }
  1025. if( dValue < 0 )
  1026. {
  1027. if( pnCode ) *pnCode = ITSC_SHORT;
  1028. return m_itsShort;
  1029. }
  1030. return ITS_NOTHING;
  1031. */
  1032. }
  1033. BOOL CEMV::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1034. {
  1035. return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
  1036. }
  1037. /***
  1038. A = (今天最高 + 今天最低)÷ 2
  1039. B = (前一天最高 + 前一天最低)÷2
  1040. C = 今天最高 - 今天最低
  1041. EM = (A-B)×C÷今天成交额
  1042. EMV = 累计n天的EM值
  1043. */
  1044. BOOL CEMV::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1045. {
  1046. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1047. if( m_nDays > nIndex )
  1048. return FALSE;
  1049. if( LoadFromCache( nIndex, pValue ) )
  1050. return TRUE;
  1051. double dEMV = 0;
  1052. int nCount = 0;
  1053. for( int k=nIndex; k>=1; k-- )
  1054. {
  1055. KDATA kd = m_pKData->ElementAt(k);
  1056. KDATA kdLast = m_pKData->ElementAt(k-1);
  1057. if( 0 == kd.m_fVolume )
  1058. return FALSE;
  1059. double dDIF = 0;
  1060. dDIF = (kd.m_fHigh+kd.m_fLow)/2 - (((double)kdLast.m_fHigh)+kdLast.m_fLow)/2;
  1061. dEMV += dDIF * (kd.m_fHigh-kd.m_fLow) / kd.m_fVolume;
  1062. nCount ++;
  1063. if( nCount == m_nDays )
  1064. {
  1065. if( pValue )
  1066. *pValue = dEMV / m_nDays;
  1067. StoreToCache( nIndex, pValue );
  1068. return TRUE;
  1069. }
  1070. }
  1071. return FALSE;
  1072. }
  1073. BOOL CEMV::Calculate( double * pValue, double * pMA, int nIndex, BOOL bUseLast )
  1074. {
  1075. return CalculateMA( pValue, pMA, nIndex, bUseLast, m_nMADays );
  1076. }
  1077. //////////////////////////////////////////////////////////////////////
  1078. // CVRSI
  1079. CVRSI::CVRSI( )
  1080. {
  1081. SetDefaultParameters( );
  1082. }
  1083. CVRSI::CVRSI( CKData * pKData )
  1084. : CTechnique( pKData )
  1085. {
  1086. SetDefaultParameters( );
  1087. }
  1088. CVRSI::~CVRSI()
  1089. {
  1090. Clear( );
  1091. }
  1092. void CVRSI::SetDefaultParameters( )
  1093. {
  1094. m_nDays = 10;
  1095. m_itsDeviateOnBottom = ITS_BUYINTENSE;
  1096. m_itsDeviateOnTop = ITS_SELLINTENSE;
  1097. m_itsSold = ITS_BUY;
  1098. m_itsBought = ITS_SELL;
  1099. }
  1100. void CVRSI::AttachParameters( CVRSI & src )
  1101. {
  1102. m_nDays = src.m_nDays;
  1103. m_itsDeviateOnBottom = src.m_itsDeviateOnBottom;
  1104. m_itsDeviateOnTop = src.m_itsDeviateOnTop;
  1105. m_itsSold = src.m_itsSold;
  1106. m_itsBought = src.m_itsBought;
  1107. }
  1108. BOOL CVRSI::IsValidParameters( )
  1109. {
  1110. return ( VALID_DAYS( m_nDays )
  1111. && VALID_ITS(m_itsDeviateOnBottom) && VALID_ITS(m_itsDeviateOnTop)
  1112. && VALID_ITS(m_itsSold) && VALID_ITS(m_itsBought) );
  1113. }
  1114. void CVRSI::Clear( )
  1115. {
  1116. CTechnique::Clear( );
  1117. }
  1118. int CVRSI::GetSignal( int nIndex, UINT * pnCode )
  1119. {
  1120. if( pnCode ) *pnCode = ITSC_NOTHING;
  1121. int nMaxDays = m_nDays;
  1122. double dLiminalLow = 0, dLiminalHigh = 0;
  1123. if( !IntensityPrepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh ) )
  1124. return ITS_NOTHING;
  1125. double dNow;
  1126. if( !Calculate( &dNow, nIndex, FALSE ) )
  1127. return ITS_NOTHING;
  1128. if( IsDeviateOnBottom( nIndex, m_pdCache1, m_pdCache2 ) )
  1129. { // 底背离
  1130. if( pnCode ) *pnCode = ITSC_DEVIATEONBOTTOM;
  1131. return m_itsDeviateOnBottom;
  1132. }
  1133. if( IsDeviateOnTop( nIndex, m_pdCache1, m_pdCache2 ) )
  1134. { // 顶背离
  1135. if( pnCode ) *pnCode = ITSC_DEVIATEONTOP;
  1136. return m_itsDeviateOnTop;
  1137. }
  1138. if( dNow < dLiminalLow )
  1139. { // 超卖
  1140. if( pnCode ) *pnCode = ITSC_OVERSOLD;
  1141. return m_itsSold;
  1142. }
  1143. if( dNow > dLiminalHigh )
  1144. { // 超买
  1145. if( pnCode ) *pnCode = ITSC_OVERBOUGHT;
  1146. return m_itsBought;
  1147. }
  1148. return ITS_NOTHING;
  1149. }
  1150. BOOL CVRSI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1151. {
  1152. if( pdMin ) *pdMin = 0;
  1153. if( pdMax ) *pdMax = 100;
  1154. return TRUE;
  1155. }
  1156. /***
  1157. VP = N日内成交量增加日的平均成交量
  1158. VQ = N日内成交量减少日的平均成交量
  1159. VRSI = 100 * VP / (VP+VQ)
  1160. */
  1161. BOOL CVRSI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1162. {
  1163. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1164. if( m_nDays > nIndex )
  1165. return FALSE;
  1166. if( LoadFromCache( nIndex, pValue ) )
  1167. return TRUE;
  1168. double dVP = 0, dVQ = 0, dResult = 0;
  1169. int nCount = 0, p = 0, q = 0;
  1170. for( int k=nIndex; k>=1; k-- )
  1171. {
  1172. if( m_pKData->MaindataAt(k) >= m_pKData->MaindataAt(k-1) )
  1173. {
  1174. dVP += m_pKData->ElementAt(k).m_fVolume;
  1175. p ++;
  1176. }
  1177. else
  1178. {
  1179. dVQ += m_pKData->ElementAt(k).m_fVolume;
  1180. q ++;
  1181. }
  1182. nCount ++;
  1183. if( nCount == m_nDays )
  1184. {
  1185. if( p > 0 ) dVP = dVP / p;
  1186. if( q > 0 ) dVQ = dVQ / q;
  1187. if( dVQ < 1e-4 )
  1188. dResult = 100;
  1189. else
  1190. dResult = 100 - 100. / (1 + dVP / dVQ);
  1191. if( pValue ) *pValue = dResult;
  1192. StoreToCache( nIndex, pValue );
  1193. return TRUE;
  1194. }
  1195. }
  1196. return FALSE;
  1197. }
  1198. //////////////////////////////////////////////////////////////////////
  1199. // CNVRSI
  1200. CNVRSI::CNVRSI( )
  1201. {
  1202. SetDefaultParameters( );
  1203. }
  1204. CNVRSI::CNVRSI( CKData * pKData )
  1205. : CVRSI( pKData )
  1206. {
  1207. SetDefaultParameters( );
  1208. }
  1209. CNVRSI::~CNVRSI()
  1210. {
  1211. Clear( );
  1212. }
  1213. /***
  1214. VP = N日内成交量增加日的总成交量
  1215. VQ = N日内成交量减少日的总成交量
  1216. VRSI = 100 * VP / (VP+VQ)
  1217. */
  1218. BOOL CNVRSI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1219. {
  1220. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1221. if( m_nDays > nIndex )
  1222. return FALSE;
  1223. if( LoadFromCache( nIndex, pValue ) )
  1224. return TRUE;
  1225. double dUV = 0, dV = 0, dResult = 0;
  1226. int nCount = 0;
  1227. for( int k=nIndex; k>=1; k-- )
  1228. {
  1229. if( m_pKData->ElementAt(k).m_fVolume > m_pKData->ElementAt(k-1).m_fVolume )
  1230. dUV += m_pKData->ElementAt(k).m_fVolume;
  1231. dV += m_pKData->ElementAt(k).m_fVolume;
  1232. nCount ++;
  1233. if( nCount == m_nDays )
  1234. {
  1235. if( dV < 1e-4 )
  1236. dResult = 50;
  1237. else
  1238. dResult = 100. * dUV / dV;
  1239. if( pValue ) *pValue = dResult;
  1240. StoreToCache( nIndex, pValue );
  1241. return TRUE;
  1242. }
  1243. }
  1244. return FALSE;
  1245. }
  1246. //////////////////////////////////////////////////////////////////////
  1247. // CAD
  1248. CAD::CAD( )
  1249. {
  1250. SetDefaultParameters( );
  1251. }
  1252. CAD::CAD( CKData * pKData )
  1253. : CTechnique( pKData )
  1254. {
  1255. SetDefaultParameters( );
  1256. }
  1257. CAD::~CAD()
  1258. {
  1259. Clear( );
  1260. }
  1261. void CAD::SetDefaultParameters( )
  1262. {
  1263. m_nDays = 8;
  1264. }
  1265. void CAD::AttachParameters( CAD & src )
  1266. {
  1267. m_nDays = src.m_nDays;
  1268. }
  1269. BOOL CAD::IsValidParameters( )
  1270. {
  1271. return ( VALID_DAYS(m_nDays) );
  1272. }
  1273. void CAD::Clear( )
  1274. {
  1275. CTechnique::Clear( );
  1276. }
  1277. int CAD::GetSignal( int nIndex, UINT * pnCode )
  1278. {
  1279. if( pnCode ) *pnCode = ITSC_NOTHING;
  1280. // 无买卖信号
  1281. return ITS_NOTHING;
  1282. }
  1283. BOOL CAD::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1284. {
  1285. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  1286. }
  1287. /***
  1288. A = 当日最高价 - 当日最低价
  1289. B = 2 * 当日收盘价 - 当日最高价 - 当日最低价
  1290. C = 当日成交量 * B / A
  1291. AD = N日内C的总和
  1292. */
  1293. BOOL CAD::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1294. {
  1295. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1296. if( m_nDays > nIndex+1 )
  1297. return FALSE;
  1298. if( LoadFromCache( nIndex, pValue ) )
  1299. return TRUE;
  1300. double dAD = 0;
  1301. int nCount = 0;
  1302. for( int k=nIndex; k>=0; k-- )
  1303. {
  1304. KDATA kd = m_pKData->ElementAt(k);
  1305. if( kd.m_fHigh-kd.m_fLow > 1e-4 )
  1306. dAD += kd.m_fVolume * (((double)kd.m_fClose)-kd.m_fLow-kd.m_fHigh+kd.m_fClose)/(((double)kd.m_fHigh)-kd.m_fLow);
  1307. nCount ++;
  1308. if( nCount == m_nDays )
  1309. {
  1310. if( pValue ) *pValue = dAD;
  1311. StoreToCache( nIndex, pValue );
  1312. return TRUE;
  1313. }
  1314. }
  1315. return FALSE;
  1316. }
  1317. //////////////////////////////////////////////////////////////////////
  1318. // CCI
  1319. CCI::CCI( )
  1320. {
  1321. SetDefaultParameters( );
  1322. }
  1323. CCI::CCI( CKData * pKData )
  1324. : CTechnique( pKData )
  1325. {
  1326. SetDefaultParameters( );
  1327. }
  1328. CCI::~CCI()
  1329. {
  1330. Clear( );
  1331. }
  1332. void CCI::SetDefaultParameters( )
  1333. {
  1334. }
  1335. void CCI::AttachParameters( CCI & src )
  1336. {
  1337. }
  1338. BOOL CCI::IsValidParameters( )
  1339. {
  1340. return TRUE;
  1341. }
  1342. void CCI::Clear( )
  1343. {
  1344. CTechnique::Clear( );
  1345. }
  1346. int CCI::GetSignal( int nIndex, UINT * pnCode )
  1347. {
  1348. if( pnCode ) *pnCode = ITSC_NOTHING;
  1349. // 无买卖信号
  1350. return ITS_NOTHING;
  1351. }
  1352. BOOL CCI::GetMinMaxInfo(int nStart, int nEnd, double *pdMin, double *pdMax )
  1353. {
  1354. return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
  1355. }
  1356. /***
  1357. CI = (当日收盘价 - 当日开盘价)/(当日最高价 - 当日最低价)
  1358. */
  1359. BOOL CCI::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  1360. {
  1361. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  1362. if( LoadFromCache( nIndex, pValue ) )
  1363. return TRUE;
  1364. KDATA kd = m_pKData->ElementAt(nIndex);
  1365. if( kd.m_fHigh-kd.m_fLow < 1e-4)
  1366. return FALSE;
  1367. double dCI = (((double)kd.m_fClose)-kd.m_fOpen)/(((double)kd.m_fHigh)-kd.m_fLow);
  1368. /*
  1369. if( nIndex > 0 )
  1370. {
  1371. KDATA kdLast = m_pKData->ElementAt(nIndex-1);
  1372. if( max(kd.m_fOpen,kd.m_fClose) > kdLast.m_fClose*1.08 && kd.m_fHigh>kdLast.m_fClose)
  1373. dCI += (2.*kd.m_fClose-kd.m_fLow-kdLast.m_fClose)/(((double)kd.m_fHigh)-kdLast.m_fClose);
  1374. if( kd.m_fOpen < kdLast.m_fClose*0.92 )
  1375. dCI += (2.*kd.m_fLow-kd.m_fHigh-kdLast.m_fClose)/(((double)kd.m_fClose)-kd.m_fLow);
  1376. }
  1377. */
  1378. dCI = kd.m_fVolume * dCI;
  1379. if( pValue )
  1380. *pValue = dCI;
  1381. StoreToCache( nIndex, pValue );
  1382. return TRUE;
  1383. }