PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Sources/Indicators/Indicators/Trend/JurikMovingAverage.cs

#
C# | 686 lines | 541 code | 109 blank | 36 comment | 82 complexity | 8b06c3dc419b9e63bb913c74be066feb MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. namespace StockSharp.Algo.Indicators.Trend
  3. {
  4. using System.ComponentModel;
  5. /// <summary>
  6. /// Юриковская (Jurik's) скользящая средняя.
  7. /// </summary>
  8. [DisplayName("JMA")]
  9. [Description("Юриковская (Jurik's) скользящая средняя.")]
  10. public class JurikMovingAverage : LengthIndicator<decimal>
  11. {
  12. private int _phase;
  13. #region Описание переменных
  14. int _jj;
  15. int _ii;
  16. double _series;
  17. double _vv;
  18. double _v1;
  19. double _v2;
  20. double _v3;
  21. double _v4;
  22. double _s8;
  23. double _s10;
  24. double _s18;
  25. double _s20;
  26. int _v5;
  27. int _v6;
  28. double _s28;
  29. double _s30;
  30. int _s38;
  31. int _s40;
  32. int _s48;
  33. int _s50;
  34. int _s58;
  35. int _s60;
  36. double _s68;
  37. double _s70;
  38. double _f8;
  39. double _f10;
  40. double _f18;
  41. double _f20;
  42. double _f28;
  43. double _f30;
  44. double _f38;
  45. double _f40;
  46. double _f48;
  47. double _f50;
  48. double _f58;
  49. double _f60;
  50. double _f68;
  51. double _f70;
  52. double _f78;
  53. double _f80;
  54. double _f88;
  55. double _f90;
  56. double _f98;
  57. double _fA0;
  58. double _fA8;
  59. double _fB0;
  60. double _fB8;
  61. double _fC0;
  62. double _fC8;
  63. double _fD0;
  64. int _f0;
  65. int _fD8;
  66. int _fE0;
  67. int _fE8;
  68. int _fF0;
  69. int _fF8;
  70. int _value2;
  71. double[] _list = new double[128];
  72. double[] _ring1 = new double[128];
  73. double[] _ring2 = new double[11];
  74. double[] _buffer = new double[62];
  75. #endregion
  76. #region Свойства
  77. /// <summary>
  78. /// Фаза
  79. /// </summary>
  80. public int Phase
  81. {
  82. get
  83. {
  84. return _phase;
  85. }
  86. set
  87. {
  88. _phase = value;
  89. if (_phase > 100)
  90. _phase = 100;
  91. else if (_phase < -100)
  92. _phase = -100;
  93. Reset();
  94. }
  95. }
  96. /// <summary>
  97. /// Текущее направление тренда
  98. /// </summary>
  99. public int LastDirection { get; private set; }
  100. #endregion
  101. /// <summary>
  102. /// Создать <see cref="JurikMovingAverage"/>.
  103. /// </summary>
  104. public JurikMovingAverage()
  105. : base(typeof(decimal))
  106. {
  107. Initialize();
  108. }
  109. /// <summary>
  110. /// Начальная инициализация переменных
  111. /// </summary>
  112. public void Initialize()
  113. {
  114. _jj = 0;
  115. _ii = 0;
  116. _series = 0;
  117. _vv = 0;
  118. _v1 = 0;
  119. _v2 = 0;
  120. _v3 = 0;
  121. _v4 = 0;
  122. _s8 = 0;
  123. _s10 = 0;
  124. _s18 = 0;
  125. _s20 = 0;
  126. _v5 = 0;
  127. _v6 = 0;
  128. _s28 = 0;
  129. _s30 = 0;
  130. _s38 = 0;
  131. _s40 = 0;
  132. _s48 = 0;
  133. _s50 = 0;
  134. _s58 = 0;
  135. _s60 = 0;
  136. _s68 = 0;
  137. _s70 = 0;
  138. _f8 = 0;
  139. _f10 = 0;
  140. _f18 = 0;
  141. _f20 = 0;
  142. _f28 = 0;
  143. _f30 = 0;
  144. _f38 = 0;
  145. _f40 = 0;
  146. _f48 = 0;
  147. _f50 = 0;
  148. _f58 = 0;
  149. _f60 = 0;
  150. _f68 = 0;
  151. _f70 = 0;
  152. _f78 = 0;
  153. _f80 = 0;
  154. _f88 = 0;
  155. _f90 = 0;
  156. _f98 = 0;
  157. _fA0 = 0;
  158. _fA8 = 0;
  159. _fB0 = 0;
  160. _fB8 = 0;
  161. _fC0 = 0;
  162. _fC8 = 0;
  163. _fD0 = 0;
  164. _f0 = 0;
  165. _fD8 = 0;
  166. _fE0 = 0;
  167. _fE8 = 0;
  168. _fF0 = 0;
  169. _fF8 = 0;
  170. _value2 = 0;
  171. _list = new double[128];
  172. _ring1 = new double[128];
  173. _ring2 = new double[11];
  174. _buffer = new double[62];
  175. _s28 = 63;
  176. _s30 = 64;
  177. for (var i = 1; i <= (int)_s28; i++)
  178. _list[i] = -1000000;
  179. for (var i = (int)_s30; i <= 127; i++)
  180. _list[i] = 1000000;
  181. _f0 = 1;
  182. }
  183. /// <summary>
  184. /// Обработать входное значение.
  185. /// </summary>
  186. /// <param name="input">Входное значение.</param>
  187. /// <returns>Результирующее значение.</returns>
  188. protected override decimal OnProcess(IIndicatorValue input)
  189. {
  190. var originalLastValue = this.GetCurrentValue();
  191. var lastValue = originalLastValue;
  192. var newValue = input.GetValue<decimal>();
  193. #region Расчет JMA
  194. _series = (double)newValue;
  195. if (_fF0 < 61)
  196. {
  197. _fF0 = _fF0 + 1;
  198. _buffer[_fF0] = _series;
  199. }
  200. //{ main cycle }
  201. if (_fF0 > 30)
  202. {
  203. if (Length < 1.0000000002)
  204. {
  205. _f80 = 0.0000000001; //{1.0e-10}
  206. }
  207. else
  208. {
  209. _f80 = (Length - 1) / 2.0;
  210. }
  211. if (_phase < -100)
  212. {
  213. _f10 = 0.5;
  214. }
  215. else
  216. {
  217. if (_phase > 100)
  218. {
  219. _f10 = 2.5;
  220. }
  221. else
  222. {
  223. _f10 = (double)_phase / 100 + 1.5;
  224. }
  225. }
  226. _v1 = Math.Log(Math.Sqrt(_f80));
  227. _v2 = _v1;
  228. if (_v1 / Math.Log(2.0) + 2.0 < 0.0)
  229. {
  230. _v3 = 0;
  231. }
  232. else
  233. {
  234. _v3 = _v2 / Math.Log(2.0) + 2.0;
  235. }
  236. _f98 = _v3;
  237. //----
  238. if (0.5 <= _f98 - 2.0)
  239. {
  240. _f88 = _f98 - 2.0;
  241. }
  242. else
  243. {
  244. _f88 = 0.5;
  245. }
  246. _f78 = Math.Sqrt(_f80) * _f98;
  247. _f90 = _f78 / (_f78 + 1.0);
  248. _f80 = _f80 * 0.9;
  249. _f50 = _f80 / (_f80 + 2.0);
  250. //----
  251. if (_f0 != 0)
  252. {
  253. _f0 = 0;
  254. _v5 = 0;
  255. for (_ii = 1; _ii <= 29; _ii++)
  256. {
  257. if (_buffer[_ii + 1] != _buffer[_ii])
  258. {
  259. _v5 = 1;
  260. }
  261. }
  262. _fD8 = _v5 * 30;
  263. _f38 = _fD8 == 0 ? _series : _buffer[1];
  264. _f18 = _f38;
  265. if (_fD8 > 29)
  266. _fD8 = 29;
  267. }
  268. else
  269. _fD8 = 0;
  270. //----
  271. for (_ii = _fD8; _ii >= 0; _ii--)
  272. {
  273. //{ another bigcycle...}
  274. _value2 = 31 - _ii;
  275. _f8 = _ii == 0 ? _series : _buffer[_value2];
  276. _f28 = _f8 - _f18;
  277. _f48 = _f8 - _f38;
  278. _v2 = Math.Max(Math.Abs(_f28), Math.Abs(_f48));
  279. _fA0 = _v2;
  280. _vv = _fA0 + 0.0000000001; //{1.0e-10;}
  281. //----
  282. if (_s48 <= 1)
  283. {
  284. _s48 = 127;
  285. }
  286. else
  287. {
  288. _s48 = _s48 - 1;
  289. }
  290. if (_s50 <= 1)
  291. {
  292. _s50 = 10;
  293. }
  294. else
  295. {
  296. _s50 = _s50 - 1;
  297. }
  298. if (_s70 < 128)
  299. _s70 = _s70 + 1;
  300. _s8 = _s8 + _vv - _ring2[_s50];
  301. _ring2[_s50] = _vv;
  302. if (_s70 > 10)
  303. {
  304. _s20 = _s8 / 10;
  305. }
  306. else
  307. _s20 = _s8 / _s70;
  308. //----
  309. if (_s70 > 127)
  310. {
  311. _s10 = _ring1[_s48];
  312. _ring1[_s48] = _s20;
  313. _s68 = 64;
  314. _s58 = Convert.ToInt32(_s68);
  315. while (_s68 > 1)
  316. {
  317. if (_list[_s58] < _s10)
  318. {
  319. _s68 = _s68 * 0.5;
  320. _s58 = _s58 + Convert.ToInt32(_s68);
  321. }
  322. else
  323. if (_list[_s58] <= _s10)
  324. {
  325. _s68 = 1;
  326. }
  327. else
  328. {
  329. _s68 = _s68 * 0.5;
  330. _s58 = _s58 - Convert.ToInt32(_s68);
  331. }
  332. }
  333. }
  334. else
  335. {
  336. _ring1[_s48] = _s20;
  337. if (_s28 + _s30 > 127)
  338. {
  339. _s30 = _s30 - 1;
  340. _s58 = Convert.ToInt32(_s30);
  341. }
  342. else
  343. {
  344. _s28 = _s28 + 1;
  345. _s58 = Convert.ToInt32(_s28);
  346. }
  347. _s38 = _s28 > 96 ? 96 : Convert.ToInt32(_s28);
  348. _s40 = _s30 < 32 ? 32 : Convert.ToInt32(_s30);
  349. }
  350. //----
  351. _s68 = 64;
  352. _s60 = Convert.ToInt32(_s68);
  353. while (_s68 > 1)
  354. {
  355. if (_list[_s60] >= _s20)
  356. {
  357. if (_list[_s60 - 1] <= _s20)
  358. {
  359. _s68 = 1;
  360. }
  361. else
  362. {
  363. _s68 = _s68 * 0.5;
  364. _s60 = _s60 - Convert.ToInt32(_s68);
  365. }
  366. }
  367. else
  368. {
  369. _s68 = _s68 * 0.5;
  370. _s60 = _s60 + Convert.ToInt32(_s68);
  371. }
  372. if ((_s60 == 127) && (_s20 > _list[127]))
  373. _s60 = 128;
  374. }
  375. if (_s70 > 127)
  376. {
  377. if (_s58 >= _s60)
  378. {
  379. if ((_s38 + 1 > _s60) && (_s40 - 1 < _s60))
  380. {
  381. _s18 = _s18 + _s20;
  382. }
  383. else
  384. if ((_s40 > _s60) && (_s40 - 1 < _s58))
  385. _s18 = _s18 + _list[_s40 - 1];
  386. }
  387. else
  388. if (_s40 >= _s60)
  389. {
  390. if ((_s38 + 1 < _s60) && (_s38 + 1 > _s58))
  391. _s18 = _s18 + _list[_s38 + 1];
  392. }
  393. else
  394. if (_s38 + 2 > _s60)
  395. {
  396. _s18 = _s18 + _s20;
  397. }
  398. else
  399. if ((_s38 + 1 < _s60) && (_s38 + 1 > _s58))
  400. _s18 = _s18 + _list[_s38 + 1];
  401. if (_s58 > _s60)
  402. {
  403. if ((_s40 - 1 < _s58) && (_s38 + 1 > _s58))
  404. {
  405. _s18 = _s18 - _list[_s58];
  406. }
  407. else
  408. if ((_s38 < _s58) && (_s38 + 1 > _s60))
  409. _s18 = _s18 - _list[_s38];
  410. }
  411. else
  412. {
  413. if ((_s38 + 1 > _s58) && (_s40 - 1 < _s58))
  414. {
  415. _s18 = _s18 - _list[_s58];
  416. }
  417. else
  418. if ((_s40 > _s58) && (_s40 < _s60))
  419. _s18 = _s18 - _list[_s40];
  420. }
  421. }
  422. if (_s58 <= _s60)
  423. {
  424. if (_s58 >= _s60)
  425. {
  426. _list[_s60] = _s20;
  427. }
  428. else
  429. {
  430. for (_jj = _s58 + 1; _jj <= _s60 - 1; _jj++)
  431. {
  432. _list[_jj - 1] = _list[_jj];
  433. }
  434. _list[_s60 - 1] = _s20;
  435. }
  436. }
  437. else
  438. {
  439. for (_jj = _s58 - 1; _jj >= _s60; _jj--)
  440. {
  441. _list[_jj + 1] = _list[_jj];
  442. }
  443. _list[_s60] = _s20;
  444. }
  445. if (_s70 <= 127)
  446. {
  447. _s18 = 0;
  448. for (_jj = _s40; _jj <= _s38; _jj++)
  449. {
  450. _s18 = _s18 + _list[_jj];
  451. }
  452. }
  453. _f60 = _s18 / (_s38 - _s40 + 1);
  454. if (_fF8 + 1 > 31)
  455. {
  456. _fF8 = 31;
  457. }
  458. else
  459. _fF8 = _fF8 + 1;
  460. //----
  461. if (_fF8 <= 30)
  462. {
  463. if (_f28 > 0)
  464. {
  465. _f18 = _f8;
  466. }
  467. else
  468. _f18 = _f8 - _f28 * _f90;
  469. if (_f48 < 0)
  470. {
  471. _f38 = _f8;
  472. }
  473. else
  474. _f38 = _f8 - _f48 * _f90;
  475. _fB8 = _series;
  476. if (_fF8 != 30)
  477. {
  478. continue;
  479. }
  480. if (_fF8 == 30)
  481. {
  482. _fC0 = _series;
  483. _v4 = Math.Max(Math.Ceiling(_f78), 1);
  484. _fE8 = (int)Math.Ceiling(_v4);
  485. _v2 = Math.Max(Math.Floor(_f78), 1);
  486. _fE0 = (int)Math.Ceiling(_v2);
  487. if (_fE8 == _fE0)
  488. {
  489. _f68 = 1;
  490. }
  491. else
  492. {
  493. _v4 = _fE8 - _fE0;
  494. _f68 = (_f78 - _fE0) / _v4;
  495. }
  496. _v5 = _fE0 <= 29 ? Convert.ToInt32(_fE0) : 29;
  497. _v6 = _fE8 <= 29 ? Convert.ToInt32(_fE8) : 29;
  498. _fA8 = (_series - _buffer[_fF0 - _v5]) * (1 - _f68) / _fE0 + (_series - _buffer[_fF0 - _v6]) * _f68 / _fE8;
  499. }
  500. }
  501. else
  502. {
  503. _v1 = Math.Min(_f98, Math.Pow(_fA0 / _f60, _f88));
  504. if (_v1 < 1)
  505. {
  506. _v2 = 1;
  507. }
  508. else
  509. {
  510. _v3 = Math.Min(_f98, Math.Pow(_fA0 / _f60, _f88));
  511. _v2 = _v3;
  512. }
  513. _f58 = _v2;
  514. _f70 = Math.Pow(_f90, Math.Sqrt(_f58));
  515. if (_f28 > 0)
  516. {
  517. _f18 = _f8;
  518. }
  519. else
  520. {
  521. _f18 = _f8 - _f28 * _f70;
  522. }
  523. if (_f48 < 0)
  524. {
  525. _f38 = _f8;
  526. }
  527. else
  528. {
  529. _f38 = _f8 - _f48 * _f70;
  530. }
  531. }
  532. }
  533. if (_fF8 > 30)
  534. {
  535. _f30 = Math.Pow(_f50, _f58);
  536. _fC0 = (1 - _f30) * _series + _f30 * _fC0;
  537. _fC8 = (_series - _fC0) * (1 - _f50) + _f50 * _fC8;
  538. _fD0 = _f10 * _fC8 + _fC0;
  539. _f20 = -_f30 * 2;
  540. _f40 = _f30 * _f30;
  541. _fB0 = _f20 + _f40 + 1;
  542. _fA8 = (_fD0 - _fB8) * _fB0 + _f40 * _fA8;
  543. _fB8 = _fB8 + _fA8;
  544. }
  545. lastValue = (decimal)_fB8;
  546. }
  547. if (_fF0 <= 30)
  548. {
  549. lastValue = newValue;
  550. }
  551. #endregion
  552. // Добавляем направление тренда
  553. LastDirection = 0;
  554. // Сравниваем новое получившееся значение индикатора со старым
  555. if (lastValue > originalLastValue)
  556. LastDirection = 1;
  557. else if (lastValue < originalLastValue)
  558. LastDirection = -1;
  559. // если буффер стал достаточно большим (стал больше длины)
  560. if (IsFormed)
  561. {
  562. // удаляем хвостовое значение
  563. Buffer.RemoveAt(0);
  564. }
  565. Buffer.Add(newValue);
  566. return lastValue;
  567. }
  568. /// <summary>
  569. /// Сбросить состояние индикатора на первоначальное. Метод вызывается каждый раз, когда меняются первоначальные настройки (например, длина периода).
  570. /// </summary>
  571. public override void Reset()
  572. {
  573. Initialize();
  574. base.Reset();
  575. }
  576. }
  577. }