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

金融证券系统

开发平台:

Visual C++

  1. /*
  2. Cross Platform Core Code.
  3. Copyright(R) 2001-2002 Balang Software.
  4. All rights reserved.
  5. Using:
  6. class CTechnique;
  7. */
  8. #include "StdAfx.h"
  9. #include "../Include/Stock.h"
  10. #include "../Include/Technique.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #endif
  18. //////////////////////////////////////////////////////////////////
  19. // GetMinMaxInfo
  20. // 一些反复使用的代码,用函数代替,得到技术指标在指定范围内的最大最小值
  21. // 技术指标有不同日期作为参数
  22. BOOL AfxGetMinMaxInfo( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech, CSPDWordArray & adwDays )
  23. {
  24. SP_ASSERT( pTech );
  25. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  26. return FALSE;
  27. double dMin = 0, dMax = 0;
  28. double dValue = 0;
  29. BOOL bFirst = TRUE;
  30. for( int i=0; i<adwDays.GetSize(); i++ )
  31. {
  32. for( int k=nStart; k<=nEnd; k++ )
  33. {
  34. if( pTech->Calculate( &dValue, k, adwDays[i], !bFirst ) )
  35. {
  36. if( bFirst || dValue < dMin ) dMin = dValue;
  37. if( bFirst || dValue > dMax ) dMax = dValue;
  38. bFirst = FALSE;
  39. }
  40. }
  41. }
  42. dMin -= fabs(dMin)*0.02;
  43. dMax += fabs(dMax)*0.02;
  44. if( dMax - dMin < 0.03 )
  45. dMax = dMin + 0.05;
  46. if( pdMin ) *pdMin = dMin;
  47. if( pdMax ) *pdMax = dMax;
  48. return !bFirst;
  49. }
  50. // 技术指标有1个最终值
  51. BOOL AfxGetMinMaxInfo1( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech )
  52. {
  53. SP_ASSERT( pTech );
  54. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  55. return FALSE;
  56. double dMin = 0, dMax = 0;
  57. double dValue = 0;
  58. BOOL bFirst = TRUE;
  59. for( int k=nStart; k<=nEnd; k++ )
  60. {
  61. if( pTech->Calculate( &dValue, k, !bFirst ) ) // 技术指标有1个最终值
  62. {
  63. if( bFirst || dValue < dMin ) dMin = dValue;
  64. if( bFirst || dValue > dMax ) dMax = dValue;
  65. bFirst = FALSE;
  66. }
  67. }
  68. dMin -= fabs(dMin)*0.02;
  69. dMax += fabs(dMax)*0.02;
  70. if( dMax - dMin < 0.03 )
  71. dMax = dMin + 0.05;
  72. if( pdMin ) *pdMin = dMin;
  73. if( pdMax ) *pdMax = dMax;
  74. return !bFirst;
  75. }
  76. // 技术指标有2个最终值
  77. BOOL AfxGetMinMaxInfo2( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech )
  78. {
  79. SP_ASSERT( pTech );
  80. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  81. return FALSE;
  82. double dMin = 0, dMax = 0;
  83. double dValue1 = 0, dValue2 = 0;
  84. BOOL bFirst = TRUE;
  85. for( int k=nStart; k<=nEnd; k++ )
  86. {
  87. if( pTech->Calculate( &dValue1, &dValue2, k, !bFirst ) ) // 技术指标有2个最终值
  88. {
  89. if( bFirst || dValue1 < dMin ) dMin = dValue1;
  90. if( bFirst || dValue1 > dMax ) dMax = dValue1;
  91. if( dValue2 < dMin ) dMin = dValue2;
  92. if( dValue2 > dMax ) dMax = dValue2;
  93. bFirst = FALSE;
  94. }
  95. }
  96. dMin -= fabs(dMin)*0.02;
  97. dMax += fabs(dMax)*0.02;
  98. if( dMax - dMin < 0.03 )
  99. dMax = dMin + 0.05;
  100. if( pdMin ) *pdMin = dMin;
  101. if( pdMax ) *pdMax = dMax;
  102. return !bFirst;
  103. }
  104. // 技术指标有3个最终值
  105. BOOL AfxGetMinMaxInfo3( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech )
  106. {
  107. SP_ASSERT( pTech );
  108. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  109. return FALSE;
  110. double dMin = 0, dMax = 0;
  111. double dValue1 = 0, dValue2 = 0, dValue3 = 0;
  112. BOOL bFirst = TRUE;
  113. for( int k=nStart; k<=nEnd; k++ )
  114. {
  115. if( pTech->Calculate( &dValue1, &dValue2, &dValue3, k, !bFirst ) ) // 技术指标有3个最终值
  116. {
  117. if( bFirst || dValue1 < dMin ) dMin = dValue1;
  118. if( bFirst || dValue1 > dMax ) dMax = dValue1;
  119. if( dValue2 < dMin ) dMin = dValue2;
  120. if( dValue2 > dMax ) dMax = dValue2;
  121. if( dValue3 < dMin ) dMin = dValue3;
  122. if( dValue3 > dMax ) dMax = dValue3;
  123. bFirst = FALSE;
  124. }
  125. }
  126. dMin -= fabs(dMin)*0.02;
  127. dMax += fabs(dMax)*0.02;
  128. if( dMax - dMin < 0.03 )
  129. dMax = dMin + 0.05;
  130. if( pdMin ) *pdMin = dMin;
  131. if( pdMax ) *pdMax = dMax;
  132. return !bFirst;
  133. }
  134. // 技术指标有4个最终值
  135. BOOL AfxGetMinMaxInfo4( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech )
  136. {
  137. SP_ASSERT( pTech );
  138. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  139. return FALSE;
  140. double dMin = 0, dMax = 0;
  141. double dValue1 = 0, dValue2 = 0, dValue3 = 0, dValue4 = 0;
  142. BOOL bFirst = TRUE;
  143. for( int k=nStart; k<=nEnd; k++ )
  144. {
  145. if( pTech->Calculate( &dValue1, &dValue2, &dValue3, &dValue4, k, !bFirst ) ) // 技术指标有4个最终值
  146. {
  147. if( bFirst || dValue1 < dMin ) dMin = dValue1;
  148. if( bFirst || dValue1 > dMax ) dMax = dValue1;
  149. if( dValue2 < dMin ) dMin = dValue2;
  150. if( dValue2 > dMax ) dMax = dValue2;
  151. if( dValue3 < dMin ) dMin = dValue3;
  152. if( dValue3 > dMax ) dMax = dValue3;
  153. if( dValue4 < dMin ) dMin = dValue4;
  154. if( dValue4 > dMax ) dMax = dValue4;
  155. bFirst = FALSE;
  156. }
  157. }
  158. dMin -= fabs(dMin)*0.02;
  159. dMax += fabs(dMax)*0.02;
  160. if( dMax - dMin < 0.03 )
  161. dMax = dMin + 0.05;
  162. if( pdMin ) *pdMin = dMin;
  163. if( pdMax ) *pdMax = dMax;
  164. return !bFirst;
  165. }
  166. // 技术指标有5个最终值
  167. BOOL AfxGetMinMaxInfo5( int nStart, int nEnd, double *pdMin, double *pdMax, CTechnique * pTech )
  168. {
  169. SP_ASSERT( pTech );
  170. if( nStart < 0 || nEnd < 0 || nStart > nEnd || !pTech )
  171. return FALSE;
  172. double dMin = 0, dMax = 0;
  173. double dValue1 = 0, dValue2 = 0, dValue3 = 0, dValue4 = 0, dValue5 = 0;
  174. BOOL bFirst = TRUE;
  175. for( int k=nStart; k<=nEnd; k++ )
  176. {
  177. if( pTech->Calculate( &dValue1, &dValue2, &dValue3, &dValue4, &dValue5, k, !bFirst ) ) // 技术指标有5个最终值
  178. {
  179. if( bFirst || dValue1 < dMin ) dMin = dValue1;
  180. if( bFirst || dValue1 > dMax ) dMax = dValue1;
  181. if( dValue2 < dMin ) dMin = dValue2;
  182. if( dValue2 > dMax ) dMax = dValue2;
  183. if( dValue3 < dMin ) dMin = dValue3;
  184. if( dValue3 > dMax ) dMax = dValue3;
  185. if( dValue4 < dMin ) dMin = dValue4;
  186. if( dValue4 > dMax ) dMax = dValue4;
  187. if( dValue5 < dMin ) dMin = dValue5;
  188. if( dValue5 > dMax ) dMax = dValue5;
  189. bFirst = FALSE;
  190. }
  191. }
  192. dMin -= fabs(dMin)*0.02;
  193. dMax += fabs(dMax)*0.02;
  194. if( dMax - dMin < 0.03 )
  195. dMax = dMin + 0.05;
  196. if( pdMin ) *pdMin = dMin;
  197. if( pdMax ) *pdMax = dMax;
  198. return !bFirst;
  199. }
  200. DWORD AfxGetMaxDays( CSPDWordArray & adw )
  201. {
  202. DWORD dwMax = 0;
  203. for( int i=0; i<adw.GetSize(); i++ )
  204. {
  205. if( adw.ElementAt(i) > dwMax )
  206. dwMax = adw.ElementAt(i);
  207. }
  208. return dwMax;
  209. }
  210. //////////////////////////////////////////////////////////////////////
  211. // CTechnique
  212. CTechnique::CTechnique( )
  213. {
  214. m_pKData = NULL;
  215. m_pdCache1 = NULL;
  216. m_pdCache2 = NULL;
  217. m_pdCache3 = NULL;
  218. m_pdCache4 = NULL;
  219. m_pdCache5 = NULL;
  220. m_pbHasCache1 = NULL;
  221. m_pbHasCache2 = NULL;
  222. m_pbHasCache3 = NULL;
  223. m_pbHasCache4 = NULL;
  224. m_pbHasCache5 = NULL;
  225. m_nLength = 0;
  226. m_nIndexStart = -1;
  227. m_nLastIntensity = ITS_NOTHING;
  228. m_nLastIntensityCode = ITSC_NOTHING;
  229. }
  230. CTechnique::CTechnique( CKData * pKData )
  231. {
  232. m_pKData = pKData;
  233. m_pdCache1 = NULL;
  234. m_pdCache2 = NULL;
  235. m_pdCache3 = NULL;
  236. m_pdCache4 = NULL;
  237. m_pdCache5 = NULL;
  238. m_pbHasCache1 = NULL;
  239. m_pbHasCache2 = NULL;
  240. m_pbHasCache3 = NULL;
  241. m_pbHasCache4 = NULL;
  242. m_pbHasCache5 = NULL;
  243. m_nLength = 0;
  244. m_nIndexStart = -1;
  245. m_nLastIntensity = ITS_NOTHING;
  246. m_nLastIntensityCode = ITSC_NOTHING;
  247. }
  248. CTechnique::~CTechnique()
  249. {
  250. CTechnique::Clear( );
  251. }
  252. void CTechnique::SetKData( CKData * pKData )
  253. {
  254. m_pKData = pKData;
  255. CTechnique::Clear( );
  256. }
  257. CKData * CTechnique::GetKData( )
  258. {
  259. return m_pKData;
  260. }
  261. void CTechnique::Clear( )
  262. {
  263. if( m_pdCache1 )
  264. delete [] m_pdCache1;
  265. if( m_pdCache2 )
  266. delete [] m_pdCache2;
  267. if( m_pdCache3 )
  268. delete [] m_pdCache3;
  269. if( m_pdCache4 )
  270. delete [] m_pdCache4;
  271. if( m_pdCache5 )
  272. delete [] m_pdCache5;
  273. if( m_pbHasCache1 )
  274. delete [] m_pbHasCache1;
  275. if( m_pbHasCache2 )
  276. delete [] m_pbHasCache2;
  277. if( m_pbHasCache3 )
  278. delete [] m_pbHasCache3;
  279. if( m_pbHasCache4 )
  280. delete [] m_pbHasCache4;
  281. if( m_pbHasCache5 )
  282. delete [] m_pbHasCache5;
  283. m_pdCache1 = NULL;
  284. m_pdCache2 = NULL;
  285. m_pdCache3 = NULL;
  286. m_pdCache4 = NULL;
  287. m_pdCache5 = NULL;
  288. m_pbHasCache1 = NULL;
  289. m_pbHasCache2 = NULL;
  290. m_pbHasCache3 = NULL;
  291. m_pbHasCache4 = NULL;
  292. m_pbHasCache5 = NULL;
  293. m_nLength = 0;
  294. m_nIndexStart = -1;
  295. m_nLastIntensity = ITS_NOTHING;
  296. m_nLastIntensityCode = ITSC_NOTHING;
  297. }
  298. void CTechnique::ClearLastIntensity( )
  299. {
  300. m_nLastIntensity = ITS_NOTHING;
  301. m_nLastIntensityCode = ITSC_NOTHING;
  302. }
  303. // 准备缓冲区
  304. BOOL CTechnique::PrepareCache( int nStart, int nEnd, BOOL bForceRecalculate )
  305. {
  306. SP_ASSERT( m_pKData );
  307. if( NULL == m_pKData )
  308. return FALSE;
  309. if( -1 == nEnd )
  310. nEnd = m_pKData->GetSize()-1;
  311. if( nStart < 0 || nEnd < nStart || nEnd >= m_pKData->GetSize() )
  312. return FALSE;
  313. if( bForceRecalculate )
  314. Clear( );
  315. return GetMinMaxInfo( nStart, nEnd, NULL, NULL );
  316. }
  317. // 从缓冲区中读取计算好的数据
  318. BOOL CTechnique::LoadFromCache( int nIndex, double * pValue1, double * pValue2, double * pValue3, double * pValue4, double * pValue5 )
  319. {
  320. if( m_nLength <= 0 || m_nIndexStart < 0
  321. || nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength )
  322. return FALSE;
  323. BOOL bOK = TRUE;
  324. if( pValue1 && !( m_pdCache1 && m_pbHasCache1 && m_pbHasCache1[nIndex-m_nIndexStart] ) )
  325. bOK = FALSE;
  326. if( pValue2 && !( m_pdCache2 && m_pbHasCache2 && m_pbHasCache2[nIndex-m_nIndexStart] ) )
  327. bOK = FALSE;
  328. if( pValue3 && !( m_pdCache3 && m_pbHasCache3 && m_pbHasCache3[nIndex-m_nIndexStart] ) )
  329. bOK = FALSE;
  330. if( pValue4 && !( m_pdCache4 && m_pbHasCache4 && m_pbHasCache4[nIndex-m_nIndexStart] ) )
  331. bOK = FALSE;
  332. if( pValue5 && !( m_pdCache5 && m_pbHasCache5 && m_pbHasCache5[nIndex-m_nIndexStart] ) )
  333. bOK = FALSE;
  334. if( !bOK )
  335. return FALSE;
  336. if( pValue1 )
  337. *pValue1 = m_pdCache1[nIndex-m_nIndexStart];
  338. if( pValue2 )
  339. *pValue2 = m_pdCache2[nIndex-m_nIndexStart];
  340. if( pValue3 )
  341. *pValue3 = m_pdCache3[nIndex-m_nIndexStart];
  342. if( pValue4 )
  343. *pValue4 = m_pdCache4[nIndex-m_nIndexStart];
  344. if( pValue5 )
  345. *pValue5 = m_pdCache5[nIndex-m_nIndexStart];
  346. return TRUE;
  347. }
  348. // 将计算好的数据保存至缓冲区
  349. BOOL CTechnique::StoreToCache( int nIndex, double * pValue1, double *pValue2, double *pValue3, double * pValue4, double * pValue5 )
  350. {
  351. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  352. if( m_nLength <= 0 || m_nIndexStart < 0 )
  353. {
  354. m_nLength = ( NULL!=m_pKData ? m_pKData->GetSize() : 0 );
  355. if( m_nLength > 0 )
  356. m_nIndexStart = 0;
  357. }
  358. if( m_nLength <= 0 || m_nIndexStart <  0 )
  359. return FALSE;
  360. // Realocate
  361. if( pValue1 )
  362. {
  363. if( !m_pdCache1 )
  364. m_pdCache1 = new double[m_nLength];
  365. if( !m_pbHasCache1 )
  366. {
  367. m_pbHasCache1 = new BOOL[m_nLength];
  368. if( !m_pbHasCache1 ) return FALSE;
  369. for( int i=0; i<m_nLength; i++ )
  370. m_pbHasCache1[i] = FALSE;
  371. }
  372. if( NULL == m_pbHasCache1 || NULL == m_pdCache1 )
  373. return FALSE;
  374. }
  375. if( pValue2 )
  376. {
  377. if( !m_pdCache2 )
  378. m_pdCache2 = new double[m_nLength];
  379. if( !m_pbHasCache2 )
  380. {
  381. m_pbHasCache2 = new BOOL[m_nLength];
  382. if( !m_pbHasCache2 ) return FALSE;
  383. for( int i=0; i<m_nLength; i++ )
  384. m_pbHasCache2[i] = FALSE;
  385. }
  386. if( NULL == m_pbHasCache2 || NULL == m_pdCache2 )
  387. return FALSE;
  388. }
  389. if( pValue3 )
  390. {
  391. if( !m_pdCache3 )
  392. m_pdCache3 = new double[m_nLength];
  393. if( !m_pbHasCache3 )
  394. {
  395. m_pbHasCache3 = new BOOL[m_nLength];
  396. if( !m_pbHasCache3 ) return FALSE;
  397. for( int i=0; i<m_nLength; i++ )
  398. m_pbHasCache3[i] = FALSE;
  399. }
  400. if( NULL == m_pbHasCache3 || NULL == m_pdCache3 )
  401. return FALSE;
  402. }
  403. if( pValue4 )
  404. {
  405. if( !m_pdCache4 )
  406. m_pdCache4 = new double[m_nLength];
  407. if( !m_pbHasCache4 )
  408. {
  409. m_pbHasCache4 = new BOOL[m_nLength];
  410. if( !m_pbHasCache4 ) return FALSE;
  411. for( int i=0; i<m_nLength; i++ )
  412. m_pbHasCache4[i] = FALSE;
  413. }
  414. if( NULL == m_pbHasCache4 || NULL == m_pdCache4 )
  415. return FALSE;
  416. }
  417. if( pValue5 )
  418. {
  419. if( !m_pdCache5 )
  420. m_pdCache5 = new double[m_nLength];
  421. if( !m_pbHasCache5 )
  422. {
  423. m_pbHasCache5 = new BOOL[m_nLength];
  424. if( !m_pbHasCache5 ) return FALSE;
  425. for( int i=0; i<m_nLength; i++ )
  426. m_pbHasCache5[i] = FALSE;
  427. }
  428. if( NULL == m_pbHasCache5 || NULL == m_pdCache5 )
  429. return FALSE;
  430. }
  431. if( nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength )
  432. return FALSE;
  433. // Store
  434. if( pValue1 && m_pdCache1 && m_pbHasCache1 )
  435. {
  436. m_pdCache1[nIndex-m_nIndexStart] = *pValue1;
  437. m_pbHasCache1[nIndex-m_nIndexStart] = TRUE;
  438. }
  439. if( pValue2 && m_pdCache2 && m_pbHasCache2 )
  440. {
  441. m_pdCache2[nIndex-m_nIndexStart] = *pValue2;
  442. m_pbHasCache2[nIndex-m_nIndexStart] = TRUE;
  443. }
  444. if( pValue3 && m_pdCache3 && m_pbHasCache3 )
  445. {
  446. m_pdCache3[nIndex-m_nIndexStart] = *pValue3;
  447. m_pbHasCache3[nIndex-m_nIndexStart] = TRUE;
  448. }
  449. if( pValue4 && m_pdCache4 && m_pbHasCache4 )
  450. {
  451. m_pdCache4[nIndex-m_nIndexStart] = *pValue4;
  452. m_pbHasCache4[nIndex-m_nIndexStart] = TRUE;
  453. }
  454. if( pValue5 && m_pdCache5 && m_pbHasCache5 )
  455. {
  456. m_pdCache5[nIndex-m_nIndexStart] = *pValue5;
  457. m_pbHasCache5[nIndex-m_nIndexStart] = TRUE;
  458. }
  459. return TRUE;
  460. }
  461. // 准备数据,得到较大值和较小值
  462. BOOL CTechnique::IntensityPrepare( int nIndex, UINT * pnCode, int nMaxDays, int nMinMaxDays, double *pdLiminalLow, double *pdLiminalHigh, double dGateLow, double dGateHigh )
  463. {
  464. if( pnCode ) *pnCode = ITSC_NOTHING;
  465. if( nIndex < nMaxDays + nMinMaxDays )
  466. return FALSE;
  467. int nStart = nIndex - nMinMaxDays + 1;
  468. if( nStart < 0 )
  469. return FALSE;
  470. double dMin = 0, dMax = 0;
  471. if( !GetMinMaxInfo( nStart, nIndex, &dMin, &dMax ) )
  472. return FALSE;
  473. if( pdLiminalLow ) *pdLiminalLow = dMin + (dMax-dMin)*dGateLow;
  474. if( pdLiminalHigh ) *pdLiminalHigh = dMin + (dMax-dMin)*dGateHigh;
  475. return TRUE;
  476. }
  477. // 准备数据,得到价格较大值和较小值
  478. BOOL CTechnique::IntensityPreparePrice( int nIndex, UINT * pnCode, int nMaxDays, int nMinMaxDays, double *pdLiminalLow, double *pdLiminalHigh, double dGateLow, double dGateHigh )
  479. {
  480. if( pnCode ) *pnCode = ITSC_NOTHING;
  481. if( nIndex < nMaxDays + nMinMaxDays )
  482. return FALSE;
  483. int nStart = nIndex - nMinMaxDays + 1;
  484. if( nStart < 0 )
  485. return FALSE;
  486. float fMin = 0, fMax = 0;
  487. if( !m_pKData || !m_pKData->GetMinMaxInfo( nStart, nIndex, &fMin, &fMax ) )
  488. return FALSE;
  489. if( pdLiminalLow ) *pdLiminalLow = (fMin + (fMax-fMin)*dGateLow);
  490. if( pdLiminalHigh ) *pdLiminalHigh = (fMin + (fMax-fMin)*dGateHigh);
  491. return TRUE;
  492. }
  493. // 是否创新高或者创新低
  494. BOOL CTechnique::IsNewValue( int nIndex, BOOL bTopOrBottom, int nDays, double * pdValue1, double * pdValue2 )
  495. {
  496. SP_ASSERT( nDays > 3 );
  497. if( nDays < 3 )
  498. return FALSE;
  499. SP_ASSERT( NULL != pdValue1 || NULL != pdValue2 );
  500. if( NULL == pdValue1 && NULL == pdValue2 )
  501. return FALSE;
  502. if( m_nLength <= 0 || m_nIndexStart < 0
  503. || nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength
  504. || nIndex-m_nIndexStart < nDays-1 )
  505. return FALSE;
  506. BOOL bFirst = TRUE;
  507. double dLast1 = 0, dLast2 = 0;
  508. int nLast1 = 0, nLast2 = 0;
  509. double dNow1 = 0, dNow2 = 0;
  510. if( NULL != pdValue1 )
  511. dNow1 = pdValue1[nIndex-m_nIndexStart];
  512. if( NULL != pdValue2 )
  513. dNow2 = pdValue2[nIndex-m_nIndexStart];
  514. for( int k=nIndex-m_nIndexStart-1; k>=0 && k>nIndex-m_nIndexStart-nDays; k-- )
  515. {
  516. if( bFirst )
  517. {
  518. if( pdValue1 ) dLast1 = pdValue1[k];
  519. if( pdValue2 ) dLast2 = pdValue2[k];
  520. nLast1 = nLast2 = k;
  521. bFirst = FALSE;
  522. }
  523. if( bTopOrBottom )
  524. {
  525. if( pdValue1 && pdValue1[k] > dNow1 )
  526. return FALSE;
  527. if( pdValue2 && pdValue2[k] > dNow2 )
  528. return FALSE;
  529. if( pdValue1 && pdValue1[k] > dLast1 )
  530. {
  531. dLast1 = pdValue1[k];
  532. nLast1 = k;
  533. }
  534. if( pdValue2 && pdValue2[k] > dLast2 )
  535. {
  536. dLast2 = pdValue2[k];
  537. nLast2 = k;
  538. }
  539. }
  540. else
  541. {
  542. if( pdValue1 && pdValue1[k] < dNow1 )
  543. return FALSE;
  544. if( pdValue2 && pdValue2[k] < dNow2 )
  545. return FALSE;
  546. if( pdValue1 && pdValue1[k] < dLast1 )
  547. {
  548. dLast1 = pdValue1[k];
  549. nLast1 = k;
  550. }
  551. if( pdValue2 && pdValue2[k] < dLast2 )
  552. {
  553. dLast2 = pdValue2[k];
  554. nLast2 = k;
  555. }
  556. }
  557. }
  558. if( bFirst )
  559. return FALSE;
  560. if( ( !pdValue1 || (nLast1 >= nIndex-30 && nLast1 <= nIndex-5) )
  561. && ( !pdValue2 || (nLast2 >= nIndex-30 && nLast2 <= nIndex-5) ) )
  562. return TRUE;
  563. return FALSE;
  564. }
  565. // 是否底背离
  566. BOOL CTechnique::IsDeviateOnBottom( int nIndex, double * pdValue1, double * pdValue2 )
  567. {
  568. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  569. if( !m_pKData->IsNewValue( nIndex, FALSE, ITS_DAYS_DEVIATE ) )
  570. return FALSE;
  571. if( IsNewValue( nIndex, FALSE, ITS_DAYS_DEVIATE, pdValue1, pdValue2 ) )
  572. return FALSE;
  573. return TRUE;
  574. }
  575. // 是否顶背离
  576. BOOL CTechnique::IsDeviateOnTop( int nIndex, double * pdValue1, double * pdValue2 )
  577. {
  578. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  579. if( !m_pKData->IsNewValue( nIndex, TRUE, ITS_DAYS_DEVIATE ) )
  580. return FALSE;
  581. if( IsNewValue( nIndex, TRUE, ITS_DAYS_DEVIATE, pdValue1, pdValue2 ) )
  582. return FALSE;
  583. return TRUE;
  584. }
  585. // 是否金叉
  586. BOOL CTechnique::IsGoldenFork( int nIndex, double * pdValue1, double * pdValue2 )
  587. {
  588. SP_ASSERT( NULL != pdValue1 && NULL != pdValue2 );
  589. if( NULL == pdValue1 || NULL == pdValue2 )
  590. return FALSE;
  591. if( m_nLength <= 0 || m_nIndexStart < 0
  592. || nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength
  593. || nIndex-m_nIndexStart < 1 )
  594. return FALSE;
  595. int k = nIndex-m_nIndexStart;
  596. if( pdValue1[k-1] <= pdValue2[k-1] && pdValue1[k] > pdValue2[k]
  597. && pdValue1[k] >= pdValue1[k-1] && pdValue2[k] >= pdValue2[k-1] )
  598. return TRUE;
  599. return FALSE;
  600. }
  601. // 是否死叉
  602. BOOL CTechnique::IsDeadFork( int nIndex, double * pdValue1, double * pdValue2 )
  603. {
  604. SP_ASSERT( NULL != pdValue1 && NULL != pdValue2 );
  605. if( NULL == pdValue1 || NULL == pdValue2 )
  606. return FALSE;
  607. if( m_nLength <= 0 || m_nIndexStart < 0
  608. || nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength
  609. || nIndex-m_nIndexStart < 1 )
  610. return FALSE;
  611. int k = nIndex-m_nIndexStart;
  612. if( pdValue1[k-1] >= pdValue2[k-1] && pdValue1[k] < pdValue2[k]
  613. && pdValue1[k] <= pdValue1[k-1] && pdValue2[k] <= pdValue2[k-1] )
  614. return TRUE;
  615. return FALSE;
  616. }
  617. // 得到金叉或者死叉信号
  618. int CTechnique::GetForkSignal(int nIndex, CSPDWordArray & adwDays,
  619.  UINT itsGoldenFork, UINT itsDeadFork, UINT * pnCode )
  620. {
  621. if( pnCode ) *pnCode = ITSC_NOTHING;
  622. if( nIndex <= 0 )
  623. return ITS_NOTHING;
  624. for( int k=1; k<adwDays.GetSize(); k++ )
  625. {
  626. double dMANow1, dMANow2, dMALast1, dMALast2;
  627. if( !Calculate( &dMANow1, nIndex, min(adwDays[k-1],adwDays[k]), FALSE )
  628. || !Calculate( &dMANow2, nIndex, max(adwDays[k-1],adwDays[k]), FALSE )
  629. || !Calculate( &dMALast1, nIndex-1, min(adwDays[k-1],adwDays[k]), FALSE )
  630. || !Calculate( &dMALast2, nIndex-1, max(adwDays[k-1],adwDays[k]), FALSE ) )
  631. return ITS_NOTHING;
  632. if( dMALast1 <= dMALast2 && dMANow1 > dMANow2
  633. && dMANow1 >= dMALast1 && dMANow2 >= dMALast2 )
  634. {
  635. if( adwDays.GetSize()-1 == k )
  636. {
  637. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  638. return itsGoldenFork;
  639. }
  640. for( int l=k+1; l<adwDays.GetSize(); l++ )
  641. {
  642. double dMANow3, dMALast3;
  643. if( !Calculate( &dMANow3, nIndex, adwDays[l], FALSE )
  644. || !Calculate( &dMALast3, nIndex-1, adwDays[l], FALSE ) )
  645. return ITS_NOTHING;
  646. if( dMANow3 >= dMALast3 )
  647. {
  648. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  649. return itsGoldenFork;
  650. }
  651. }
  652. }
  653. if( dMALast1 >= dMALast2 && dMANow1 < dMANow2
  654. && dMANow1 <= dMALast1 && dMANow2 <= dMALast2 )
  655. {
  656. if( adwDays.GetSize()-1 == k )
  657. {
  658. if( pnCode ) *pnCode = ITSC_DEADFORK;
  659. return itsDeadFork;
  660. }
  661. for( int l=k+1; l<adwDays.GetSize(); l++ )
  662. {
  663. double dMANow3, dMALast3;
  664. if( !Calculate( &dMANow3, nIndex, adwDays[l], FALSE )
  665. || !Calculate( &dMALast3, nIndex-1, adwDays[l], FALSE ) )
  666. return ITS_NOTHING;
  667. if( dMANow3 <= dMALast3 )
  668. {
  669. if( pnCode ) *pnCode = ITSC_DEADFORK;
  670. return itsDeadFork;
  671. }
  672. }
  673. }
  674. }
  675. return ITS_NOTHING;
  676. }
  677. // 得到金叉或者死叉信号
  678. int CTechnique::GetForkSignal( int nIndex, UINT itsGoldenFork, UINT itsDeadFork, UINT *pnCode )
  679. {
  680. if( pnCode ) *pnCode = ITSC_NOTHING;
  681. if( nIndex <= 0 )
  682. return ITS_NOTHING;
  683. double dLast1 = 0, dLast2 = 0, dNow1 = 0, dNow2 = 0;
  684. if( !Calculate( &dLast1, &dLast2, nIndex-1, FALSE )
  685. || !Calculate( &dNow1, &dNow2, nIndex, FALSE ) )
  686. return ITS_NOTHING;
  687. if( dLast1 <= dLast2 && dNow1 > dNow2
  688. && dNow1 >= dLast1 && dNow2 >= dLast2 )
  689. {
  690. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  691. return itsGoldenFork;
  692. }
  693. if( dLast1 >= dLast2 && dNow1 < dNow2
  694. && dNow1 <= dLast1 && dNow2 <= dLast2 )
  695. {
  696. if( pnCode ) *pnCode = ITSC_DEADFORK;
  697. return itsDeadFork;
  698. }
  699. return ITS_NOTHING;
  700. }
  701. // 得到金叉或者死叉信号
  702. int CTechnique::GetForkSignal(int nIndex, double * pdValue1, double * pdValue2,
  703.   UINT itsGoldenFork, UINT itsDeadFork, UINT *pnCode )
  704. {
  705. if( pnCode ) *pnCode = ITSC_NOTHING;
  706. if( IsGoldenFork( nIndex, pdValue1, pdValue2 ) )
  707. {
  708. if( pnCode ) *pnCode = ITSC_GOLDENFORK;
  709. return itsGoldenFork;
  710. }
  711. if( IsDeadFork( nIndex, pdValue1, pdValue2 ) )
  712. {
  713. if( pnCode ) *pnCode = ITSC_DEADFORK;
  714. return itsDeadFork;
  715. }
  716. return ITS_NOTHING;
  717. }
  718. // 得到趋势信号
  719. int CTechnique::GetTrendIntensity(int nIndex, CSPDWordArray & adwDays,
  720.  UINT itsLong, UINT itsShort, UINT * pnCode )
  721. {
  722. if( pnCode ) *pnCode = ITSC_NOTHING;
  723. if( nIndex <= 0 )
  724. return ITS_NOTHING;
  725. int nRet = ITS_NOTHING;
  726. for( int k=1; k<adwDays.GetSize(); k++ )
  727. {
  728. double dMALast1, dMALast2, dMANow1, dMANow2;
  729. if( !Calculate( &dMALast1, nIndex-1, min(adwDays[k-1],adwDays[k]), FALSE )
  730. || !Calculate( &dMALast2, nIndex-1, max(adwDays[k-1],adwDays[k]), FALSE )
  731. || !Calculate( &dMANow1, nIndex, min(adwDays[k-1],adwDays[k]), FALSE )
  732. || !Calculate( &dMANow2, nIndex, max(adwDays[k-1],adwDays[k]), FALSE ) )
  733. return ITS_NOTHING;
  734. if( dMANow1 >= dMALast1 && dMANow2 >= dMALast2
  735. && dMANow1 > dMANow2 && (dMANow1-dMANow2)>=(dMALast1-dMALast2)
  736. && (ITS_ISBUY(nRet) || 1==k) )
  737. {
  738. if( pnCode ) *pnCode = ITSC_LONG;
  739. nRet = itsLong;
  740. }
  741. else if( dMANow1 <= dMALast1 && dMANow2 <= dMALast2
  742. && dMANow1 < dMANow2 && (dMANow1-dMANow2)<=(dMALast1-dMALast2)
  743. && (ITS_ISSELL(nRet) || 1==k) )
  744. {
  745. if( pnCode ) *pnCode = ITSC_SHORT;
  746. nRet = itsShort;
  747. }
  748. else
  749. {
  750. if( pnCode ) *pnCode = ITSC_NOTHING;
  751. return ITS_NOTHING;
  752. }
  753. }
  754. return nRet;
  755. }
  756. // 得到趋势信号
  757. int CTechnique::GetTrendIntensity1( int nIndex, UINT itsLong, UINT itsShort, UINT *pnCode )
  758. {
  759. if( pnCode ) *pnCode = ITSC_NOTHING;
  760. if( nIndex <= 0 )
  761. return ITS_NOTHING;
  762. double dLast = 0, dNow = 0;
  763. if( !Calculate( &dLast, nIndex-1, FALSE )
  764. || !Calculate( &dNow, nIndex, FALSE ) )
  765. return ITS_NOTHING;
  766. if( dNow > dLast )
  767. {
  768. if( pnCode ) *pnCode = ITSC_LONG;
  769. return itsLong;
  770. }
  771. if( dNow < dLast )
  772. {
  773. if( pnCode ) *pnCode = ITSC_SHORT;
  774. return itsShort;
  775. }
  776. return ITS_NOTHING;
  777. }
  778. // 得到趋势信号
  779. int CTechnique::GetTrendIntensity2( int nIndex, UINT itsLong, UINT itsShort, UINT *pnCode )
  780. {
  781. if( pnCode ) *pnCode = ITSC_NOTHING;
  782. if( nIndex <= 0 )
  783. return ITS_NOTHING;
  784. double dLast1 = 0, dLast2 = 0, dNow1 = 0, dNow2 = 0;
  785. if( Calculate( &dLast1, &dLast2, nIndex-1, FALSE )
  786. && Calculate( &dNow1, &dNow2, nIndex, FALSE ) )
  787. {
  788. if( dNow1 >= dLast1 && dNow2 >= dLast2
  789. && dNow1 > dNow2 && (dNow1-dNow2)>=(dLast1-dLast2) )
  790. {
  791. if( pnCode ) *pnCode = ITSC_LONG;
  792. return itsLong;
  793. }
  794. if( dNow1 <= dLast1 && dNow2 <= dLast2
  795. && dNow1 < dNow2 && (dNow1-dNow2)<=(dLast1-dLast2) )
  796. {
  797. if( pnCode ) *pnCode = ITSC_SHORT;
  798. return itsShort;
  799. }
  800. }
  801. return ITS_NOTHING;
  802. }
  803. // 得到趋势信号
  804. int CTechnique::GetTrendIntensity(int nIndex, double * pdValue1, double * pdValue2,
  805.   UINT itsLong, UINT itsShort, UINT *pnCode )
  806. {
  807. if( pnCode ) *pnCode = ITSC_NOTHING;
  808. SP_ASSERT( NULL != pdValue1 && NULL != pdValue2 );
  809. if( NULL == pdValue1 || NULL == pdValue2 )
  810. return FALSE;
  811. if( m_nLength <= 0 || m_nIndexStart < 0
  812. || nIndex < m_nIndexStart || nIndex-m_nIndexStart>=m_nLength
  813. || nIndex-m_nIndexStart < 1 )
  814. return FALSE;
  815. int k = nIndex-m_nIndexStart;
  816. if( pdValue1[k] >= pdValue1[k-1] && pdValue2[k] >= pdValue2[k-1]
  817. && pdValue1[k] > pdValue2[k] && (pdValue1[k]-pdValue2[k])>=(pdValue1[k-1]-pdValue2[k-1]) )
  818. {
  819. if( pnCode ) *pnCode = ITSC_LONG;
  820. return itsLong;
  821. }
  822. if( pdValue1[k] <= pdValue1[k-1] && pdValue2[k] <= pdValue2[k-1]
  823. && pdValue1[k] < pdValue2[k] && (pdValue1[k]-pdValue2[k])<=(pdValue1[k-1]-pdValue2[k-1]) )
  824. {
  825. if( pnCode ) *pnCode = ITSC_SHORT;
  826. return itsShort;
  827. }
  828. return ITS_NOTHING;
  829. }
  830. void CTechnique::SetDefaultParameters( )
  831. {
  832. SP_ASSERT( FALSE );
  833. }
  834. void CTechnique::AttachParameters( CTechnique & src )
  835. {
  836. SP_ASSERT( FALSE );
  837. }
  838. BOOL CTechnique::IsValidParameters( )
  839. {
  840. SP_ASSERT( FALSE );
  841. return FALSE;
  842. }
  843. // 创建新的技术指标对象
  844. CTechnique * CTechnique::CreateTechnique( UINT nTech, CKData * pKData )
  845. {
  846. CTechnique * pTech = NULL;
  847. switch( nTech )
  848. {
  849. case STT_MA: pTech = new CMA( pKData ); break;
  850. case STT_BBI: pTech = new CBBI( pKData ); break;
  851. case STT_BOLL: pTech = new CBOLL( pKData ); break;
  852. case STT_PV: pTech = new CPV( pKData ); break;
  853. case STT_SAR: pTech = new CSAR( pKData ); break;
  854. case STT_DJ: pTech = new CDJ( pKData ); break;
  855. case STT_CW: pTech = new CCW( pKData ); break;
  856. case STT_MACD: pTech = new CMACD( pKData ); break;
  857. case STT_MIKE: pTech = new CMIKE( pKData ); break;
  858. case STT_PSY: pTech = new CPSY( pKData ); break;
  859. case STT_VOLUME: pTech = new CVOLUME( pKData ); break;
  860. case STT_NVI: pTech = new CNVI( pKData ); break;
  861. case STT_PVI: pTech = new CPVI( pKData ); break;
  862. case STT_VR: pTech = new CVR( pKData ); break;
  863. case STT_VROC: pTech = new CVROC( pKData ); break;
  864. case STT_OBV: pTech = new COBV( pKData ); break;
  865. case STT_MOBV: pTech = new CMOBV( pKData ); break;
  866. case STT_MFI: pTech = new CMFI( pKData ); break;
  867. case STT_VMACD: pTech = new CVMACD( pKData ); break;
  868. case STT_WVAD: pTech = new CWVAD( pKData ); break;
  869. case STT_EMV: pTech = new CEMV( pKData ); break;
  870. case STT_VRSI: pTech = new CVRSI( pKData ); break;
  871. case STT_NVRSI: pTech = new CNVRSI( pKData ); break;
  872. case STT_AD: pTech = new CAD( pKData ); break;
  873. case STT_CI: pTech = new CCI( pKData ); break;
  874. case STT_KDJ: pTech = new CKDJ( pKData ); break;
  875. case STT_R: pTech = new CR( pKData ); break;
  876. case STT_RSI: pTech = new CRSI( pKData ); break;
  877. case STT_BIAS: pTech = new CBIAS( pKData ); break;
  878. case STT_MTM: pTech = new CMTM( pKData ); break;
  879. case STT_DMI: pTech = new CDMI( pKData ); break;
  880. case STT_ROC: pTech = new CROC( pKData ); break;
  881. case STT_CCI: pTech = new CCCI( pKData ); break;
  882. case STT_CV: pTech = new CCV( pKData ); break;
  883. case STT_ARBR: pTech = new CARBR( pKData ); break;
  884. case STT_CR: pTech = new CCR( pKData ); break;
  885. case STT_OSC: pTech = new COSC( pKData ); break;
  886. case STT_UOS: pTech = new CUOS( pKData ); break;
  887. case STT_MAOSC: pTech = new CMAOSC( pKData ); break;
  888. case STT_36BIAS: pTech = new C36BIAS( pKData ); break;
  889. case STT_DPO: pTech = new CDPO( pKData ); break;
  890. case STT_KST: pTech = new CKST( pKData ); break;
  891. case STT_REI: pTech = new CREI( pKData ); break;
  892. case STT_DMKI: pTech = new CDMKI( pKData ); break;
  893. case STT_PCNT: pTech = new CPCNT( pKData ); break;
  894. case STT_HLC: pTech = new CHLC( pKData ); break;
  895. case STT_CDP: pTech = new CCDP( pKData ); break;
  896. case STT_ASI: pTech = new CASI( pKData ); break;
  897. case STT_ATR: pTech = new CATR( pKData ); break;
  898. case STT_CYO: pTech = new CCYO( pKData ); break;
  899. case STT_DCYO: pTech = new CDCYO( pKData ); break;
  900. case STT_HSL: pTech = new CHSL( pKData ); break;
  901. case STT_DPER: pTech = new CDPER( pKData ); break;
  902. default:
  903. SP_ASSERT( FALSE );
  904. }
  905. return pTech;
  906. }
  907. // 得到买卖信号
  908. int CTechnique::GetSignal( int nIndex, UINT * pnCode )
  909. {
  910. if( pnCode ) *pnCode = ITSC_NOTHING;
  911. return ITS_NOTHING;
  912. }
  913. // 得到趋势信号
  914. int CTechnique::GetIntensity( int nIndex, UINT * pnCode, BOOL bTraceBack )
  915. {
  916. UINT nCode = ITSC_NOTHING;
  917. int nSignal = GetSignal( nIndex, &nCode );
  918. if( ITS_NOTHING != nSignal )
  919. {
  920. m_nLastIntensity = nSignal;
  921. m_nLastIntensityCode = nCode;
  922. if( pnCode ) *pnCode = nCode;
  923. return nSignal;
  924. }
  925. if( m_nLastIntensity > 1 )
  926. m_nLastIntensity --;
  927. if( m_nLastIntensity < -1  )
  928. m_nLastIntensity ++;
  929. if( bTraceBack && ITS_NOTHING == m_nLastIntensity )
  930. m_nLastIntensity = GetIntensityTraceback( nIndex, &m_nLastIntensityCode );
  931. if( pnCode ) *pnCode = m_nLastIntensityCode;
  932. return m_nLastIntensity;
  933. }
  934. int CTechnique::GetIntensityTraceback( int nIndex, UINT * pnCode )
  935. {
  936. if( pnCode ) *pnCode = ITSC_NOTHING;
  937. int nIntensity = ITS_NOTHING;
  938. UINT nCode = ITSC_NOTHING;
  939. for( int k=nIndex; k>=0; k -- )
  940. {
  941. nIntensity = GetSignal(k,&nCode);
  942. if( ITS_NOTHING != nIntensity )
  943. break;
  944. }
  945. if( k < 0 )
  946. return ITS_NOTHING;
  947. for( k=k+1; k<=nIndex; k++ )
  948. {
  949. if( nIntensity > 1 )
  950. nIntensity --;
  951. else if( nIntensity < -1  )
  952. nIntensity ++;
  953. else
  954. break;
  955. }
  956. if( pnCode ) *pnCode = nCode;
  957. return nIntensity;
  958. }
  959. BOOL CTechnique::GetMinMaxInfo( int nStart, int nEnd, double *pdMin, double *pdMax )
  960. {
  961. SP_ASSERT( FALSE );
  962. return FALSE;
  963. }
  964. BOOL CTechnique::Calculate( double * pValue, int nIndex, int nDays, BOOL bUseLast )
  965. {
  966. SP_ASSERT( FALSE );
  967. return FALSE;
  968. }
  969. BOOL CTechnique::Calculate( double * pValue, int nIndex, BOOL bUseLast )
  970. {
  971. SP_ASSERT( FALSE );
  972. return FALSE;
  973. }
  974. BOOL CTechnique::Calculate( double * pValue1, double * pValue2, int nIndex, BOOL bUseLast )
  975. {
  976. SP_ASSERT( FALSE );
  977. return FALSE;
  978. }
  979. BOOL CTechnique::Calculate( double * pValue1, double * pValue2, double * pValue3, int nIndex, BOOL bUseLast )
  980. {
  981. SP_ASSERT( FALSE );
  982. return FALSE;
  983. }
  984. BOOL CTechnique::Calculate( double * pValue1, double * pValue2, double * pValue3, double *pValue4, int nIndex, BOOL bUseLast )
  985. {
  986. SP_ASSERT( FALSE );
  987. return FALSE;
  988. }
  989. BOOL CTechnique::Calculate( double * pValue1, double * pValue2, double * pValue3, double *pValue4, double *pValue5, int nIndex, BOOL bUseLast )
  990. {
  991. SP_ASSERT( FALSE );
  992. return FALSE;
  993. }
  994. // 计算指标值和均值
  995. BOOL CTechnique::CalculateMA( double * pValue, double * pMA, int nIndex, BOOL bUseLast, int nMADays )
  996. {
  997. STT_ASSERT_CALCULATE1( m_pKData, nIndex );
  998. if( nMADays > nIndex+1 )
  999. return FALSE;
  1000. if( LoadFromCache( nIndex, pValue, pMA ) )
  1001. return TRUE;
  1002. double dValue = 0, dMA = 0;
  1003. int nCount = 0;
  1004. for( int k=nIndex; k>=0; k-- )
  1005. {
  1006. double dTemp = 0;
  1007. if( Calculate( &dTemp, k, FALSE ) )
  1008. {
  1009. if( nIndex == k )
  1010. dValue = dTemp;
  1011. dMA += dTemp;
  1012. nCount ++;
  1013. if( nCount == nMADays )
  1014. {
  1015. dMA = dMA / nMADays;
  1016. if( pValue ) *pValue = dValue;
  1017. if( pMA ) *pMA = dMA;
  1018. StoreToCache( nIndex, pValue, pMA );
  1019. return TRUE;
  1020. }
  1021. }
  1022. }
  1023. return FALSE;
  1024. }