Pastebin: OmegaChart Fibonacciトレースメント ChartDrawing.cs 追加修正ポイントには//☆Fibonacci ※差し替え その1

Format
Plain text
Post date
2018-08-19 18:01
Publication Period
Unlimited
  1. using System;
  2. using System.Collections;
  3. using System.Drawing;
  4. using System.Text;
  5. using System.Diagnostics;
  6. using System.Windows.Forms;
  7. using Travis.Util;
  8. using Zanetti;
  9. using Zanetti.Data;
  10. using Zanetti.Indicators;
  11. using Zanetti.Arithmetic;
  12. using Zanetti.Arithmetic.Series;
  13. #if DOJIMA
  14. using DojimaChart = Zanetti.Dojima.DojimaChart;
  15. #endif
  16. namespace Zanetti.UI
  17. {
  18. internal class RedrawValue
  19. {
  20. public int _lastDrawn;
  21. public int _nextToBeDrawn;
  22. }
  23. /// <summary>
  24. /// ChartDrawing の概要の説明です。
  25. /// </summary>
  26. internal class ChartDrawing
  27. {
  28. private ChartCanvas _owner;
  29. private Preference _pref; //描画のいろいろな過程で参照するのでメンバとして保持
  30. private LayoutInfo _layout;
  31. private int _maximumValueWindowItemCount;
  32. private AbstractBrand _brand;
  33. private int _firstDateIndex;
  34. private int _firstDate;
  35. private int _lastDate;
  36. private double[] _relativisedMultipliers;
  37. private RedrawValue _dateLine;
  38. private RedrawValue _priceLine;
  39. private bool _scaleIsInvalidated;
  40. private Trans _priceTrans; //price->y座標変換
  41. private double _highPrice; //表示している値段の範囲
  42. private double _lowPrice;
  43. private int _priceScaleStep; //値段を示す横線の幅 これの整数倍ごとに線を引く
  44. private Trans _volumeTrans; //volume->y座標変換
  45. private double _volumeScaleStep;
  46. private Win32.POINT _dummyPoint;
  47. //キャプションが長すぎて見えないやつを拾うためのデータ
  48. private ArrayList _tipEntries;
  49. private bool _tipBuilding;
  50. //価格帯出来高
  51. private AccumulativeVolume _accumulativeVolume;
  52. //FreeLine
  53. private ArrayList _freeLines;
  54. //☆Fibonacci
  55. private ArrayList _fibonaccies;
  56. public ChartDrawing(ChartCanvas owner)
  57. {
  58. _owner = owner;
  59. _dateLine = new RedrawValue();
  60. _dateLine._lastDrawn = -1;
  61. _dateLine._nextToBeDrawn = -1;
  62. _priceLine = new RedrawValue();
  63. _freeLines = new ArrayList();
  64. _fibonaccies = new ArrayList();//☆Fibonacci
  65. _scaleIsInvalidated = true;
  66. _accumulativeVolume = new AccumulativeVolume();
  67. }
  68. public void SetBrand(AbstractBrand br)
  69. {
  70. _brand = br;
  71. #if DOJIMA
  72. _halfDailyDataFarm = null;
  73. #endif
  74. //銘柄がかわるごとにクリア
  75. ClearScale();
  76. _relativisedMultipliers = new double[Env.CurrentIndicators.IndicatorCount];
  77. }
  78. public void ClearScale()
  79. {
  80. if (!Env.Preference.ScaleLock)
  81. {
  82. _priceTrans = null;
  83. _freeLines.Clear();
  84. _fibonaccies.Clear();//☆Fibonacci
  85. }
  86. _scaleIsInvalidated = true;
  87. _tipEntries = null;
  88. }
  89. public ArrayList TipEntries
  90. {
  91. get
  92. {
  93. return _tipEntries;
  94. }
  95. }
  96. public int FirstDateIndex
  97. {
  98. get
  99. {
  100. return _firstDateIndex;
  101. }
  102. set
  103. {
  104. _firstDateIndex = value;
  105. }
  106. }
  107. public RedrawValue DateLine
  108. {
  109. get
  110. {
  111. return _dateLine;
  112. }
  113. }
  114. public RedrawValue PriceLine
  115. {
  116. get
  117. {
  118. return _priceLine;
  119. }
  120. set
  121. {
  122. _priceLine = value;
  123. }
  124. }
  125. public Trans PriceTrans//☆Fibonacci
  126. {
  127. get
  128. {
  129. return _priceTrans;
  130. }
  131. set
  132. {
  133. _priceTrans = value;
  134. }
  135. }
  136. //次に描画するものを決める
  137. public void UpdateDateLineIndex(int index)
  138. {
  139. if (_dateLine._nextToBeDrawn != index)
  140. {
  141. if (index != -1)
  142. {
  143. DataFarm farm = _owner.GetBrand().ReserveFarm();
  144. if (farm.IsEmpty || _scaleIsInvalidated)
  145. _accumulativeVolume.Available = false;
  146. else
  147. {
  148. int price_pitch = Math.Max(1, _priceScaleStep / AccumulativeVolume.DATA_PER_SCALELINE);
  149. _accumulativeVolume.Fill(farm, index, _accumulativeVolume.StartPrice, price_pitch, _accumulativeVolume.EndPrice);
  150. }
  151. }
  152. }
  153. _dateLine._nextToBeDrawn = index;
  154. }
  155. //現在の設定で表示できる日付範囲
  156. public int FirstDate
  157. {
  158. get
  159. {
  160. DataFarm farm = _owner.GetBrand().ReserveFarm();
  161. return farm.GetByIndex(_firstDateIndex).Date;
  162. }
  163. }
  164. public int LastDate
  165. {
  166. get
  167. {
  168. DataFarm farm = _owner.GetBrand().ReserveFarm();
  169. return farm.GetByIndex(Math.Min(farm.FilledLength, _firstDateIndex + Env.Layout.DisplayColumnCount) - 1).Date;
  170. }
  171. }
  172. public int MaximumValueWindowItemCount
  173. {
  174. get
  175. {
  176. return _maximumValueWindowItemCount;
  177. }
  178. }
  179. public int FreeLineCount
  180. {
  181. get
  182. {
  183. return _freeLines.Count;
  184. }
  185. }
  186. public IEnumerable FreeLines
  187. {
  188. get
  189. {
  190. return _freeLines;
  191. }
  192. }
  193. //☆Fibonacci
  194. public int FibonacciesCount
  195. {
  196. get
  197. {
  198. return _fibonaccies.Count;
  199. }
  200. }
  201. public IEnumerable Fibonaccies
  202. {
  203. get
  204. {
  205. return _fibonaccies;
  206. }
  207. }
  208. //☆Fibonacci 追加ここまで
  209. public void PaintMain(Graphics g, Rectangle clip)
  210. {
  211. if (_brand == null) return;
  212. if (!Env.CurrentIndicators.Valid) return;
  213. _pref = Env.Preference;
  214. _layout = Env.Layout;
  215. IntPtr hdc = g.GetHdc();
  216. Win32.SetBkColor(hdc, Util.ToCOLORREF(_pref.BackBrush.Color));
  217. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  218. Win32.SelectObject(hdc, _pref.DefaultHFont);
  219. if (_tipEntries == null)
  220. {
  221. _tipEntries = new ArrayList();
  222. _tipBuilding = true;
  223. }
  224. else
  225. _tipBuilding = false;
  226. try
  227. {
  228. if (clip.IntersectsWith(_layout.ChartBodyRect))
  229. DrawChartBody(hdc, clip);
  230. if (_pref.ShowPrice)
  231. {
  232. if (clip.IntersectsWith(_layout.CurrentValueRect))
  233. DrawCurrentValue(hdc);
  234. if (clip.IntersectsWith(_layout.ExplanationRect))
  235. DrawExplanation(hdc);
  236. }
  237. if (_pref.ShowAccumulativeVolume && clip.IntersectsWith(_layout.AccumulativeVolumeRect))
  238. DrawAccumulativeVolume(hdc);
  239. foreach (FreeLine fl in _freeLines)
  240. {
  241. if (fl.GetInclusion(_owner.ClientRectangle).IntersectsWith(clip))
  242. fl.Draw(_layout.ChartBodyRect, hdc);
  243. }
  244. foreach (Fibonacci fl in _fibonaccies)//☆Fibonacci
  245. {
  246. //クリックして選んだ2点の内側の最高値と最安値を取得
  247. fl.SetHighPriceAndLowPrice(_brand.ReserveFarm(), PriceTrans, fl.Pivot.X, fl.Destination.X, FirstDateIndex);
  248. if (fl.GetInclusion(_owner.ClientRectangle).IntersectsWith(clip))
  249. fl.Draw(_priceTrans, _layout.ChartBodyRect, hdc);
  250. }
  251. if (clip.IntersectsWith(_layout.BrandInformationRect))
  252. DrawBrandInformation(hdc);
  253. }
  254. catch (Exception ex)
  255. {
  256. Util.SilentReportCriticalError(ex);
  257. Util.Warning(Env.Frame, ex.Message + "\n拡張キットを読み込みなおすまでチャートの描画を停止します。");
  258. Env.CurrentIndicators.Valid = false;
  259. }
  260. finally
  261. {
  262. g.ReleaseHdc(hdc);
  263. }
  264. }
  265. //各パーツの描画 けっこう大変だよ
  266. private void DrawChartBody(IntPtr hdc, Rectangle clip)
  267. {
  268. Indicator[] indicators = Env.CurrentIndicators.GetIndicatorsForChart();
  269. DataFarm farm = _brand.ReserveFarm();
  270. if (farm.IsEmpty)
  271. {
  272. RecalcValueWindowFormat();
  273. DrawBrandInformation(hdc);
  274. return;
  275. }
  276. if (_scaleIsInvalidated)
  277. {
  278. RecalcFormat();
  279. RecalcValueWindowFormat();
  280. _scaleIsInvalidated = false;
  281. }
  282. DrawScaleLines(hdc);
  283. DrawMouseTrackingLine(hdc); //これはロウソクの前に描いたほうがヒゲなどが見えやすい
  284. Win32.SelectObject(hdc, _pref.DefaultHFont);
  285. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.FushiColor));
  286. int index = _firstDateIndex;
  287. int end = Math.Min(farm.TotalLength, _firstDateIndex + _layout.DisplayColumnCount);
  288. _firstDate = this.FirstDate; //farm.GetByIndex(index).Date;
  289. _lastDate = this.LastDate; //farm.GetByIndex(Math.Min(farm.FilledLength, _firstDateIndex+_layout.DisplayColumnCount)-1).Date;
  290. if (_firstDate == 0) return; //ケンミレの一部のデータが壊れている件の暫定対応
  291. //特殊処理:一目の雲
  292. if (IchimokuKumoIsAvailable())
  293. DrawIchimokuKumo(hdc, farm, index, end, clip);
  294. int prev_date_part = 0;
  295. string caption = "";
  296. while (index < end)
  297. {
  298. int x = (index - _firstDateIndex) * _layout.DatePitch;
  299. TradeData td = farm.GetByIndex(index);
  300. //if(!td.IsFuture) {
  301. int mid = x + _layout.CandleMiddleOffset;
  302. if (clip.Left <= x + _layout.DatePitch && x - _layout.DatePitch < clip.Right)
  303. {
  304. #if DOJIMA
  305. ChartFormat fmt = Env.CurrentIndicators.Format;
  306. if(DojimaChart.IsMusousenAvailable(fmt))
  307. DojimaChart.DrawMusousen(hdc, _pref.CandlePen, mid, -_priceScaleStep*3, td, clip, _priceTrans);
  308. if(!td.IsFuture) {
  309. if(fmt==ChartFormat.HalfDaily)
  310. DrawHalfDailyChart(hdc, farm as DailyDataFarm, x, td, clip);
  311. else
  312. DrawBasicChart(hdc, mid, td, clip);
  313. #else
  314. if (!td.IsFuture)
  315. {
  316. DrawBasicChart(hdc, mid, td, clip);
  317. #endif
  318. foreach (Indicator ind in indicators)
  319. DrawIndicator(hdc, mid, td, null, ind, clip);
  320. for (int i = 0; i < OscillatorPreference.LENGTH; i++)
  321. {
  322. OscillatorPreference op = _pref.OscillatorPreferences[i];
  323. if (op.Config != HeightConfig.None)
  324. {
  325. foreach (Indicator ind in op.OscillatorGroup)
  326. DrawIndicator(hdc, mid, td, op, ind, clip);
  327. }
  328. }
  329. }
  330. }
  331. //月/4半期の切り替わり
  332. if (!td.IsFuture)
  333. {
  334. int date_part = td.Date % 100;
  335. if (CheckMonthDiv(prev_date_part, date_part, td, ref caption))
  336. {
  337. Win32.SelectObject(hdc, _pref.MonthDivPen.Handle);
  338. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  339. Win32.MoveToEx(hdc, x, _layout.HeaderHeight, out _dummyPoint);
  340. Win32.LineTo(hdc, x, _layout.ChartAreaBottom);
  341. if (ChartUtil.HasIntersectionY(clip, _layout.ChartAreaBottom, _layout.ChartAreaBottom + _layout.FooterHeight))
  342. ChartUtil.DrawText(hdc, x + 2, _layout.ChartAreaBottom, caption);
  343. }
  344. prev_date_part = date_part;
  345. DrawFushiOrSplit(hdc, mid, td, clip); //節は最後の描画でないと隠れてしまうことがある
  346. }
  347. //}
  348. index++;
  349. }
  350. }
  351. private bool CheckMonthDiv(int prev_date_part, int date_part, TradeData td, ref string caption)
  352. {
  353. if (Util.IsDailyBased(Env.CurrentIndicators.Format))
  354. {
  355. if (prev_date_part > date_part)
  356. { //月の値が減少したら
  357. caption = String.Format("{0}年{1}月", td.Date / 10000, (td.Date % 10000) / 100);
  358. return true;
  359. }
  360. }
  361. else if (Env.CurrentIndicators.Format == ChartFormat.Weekly)
  362. {
  363. int t = td.Date;
  364. DateTime d = new DateTime(t / 10000, (t % 10000) / 100, (t % 100));
  365. d = d.AddDays(5); //金曜日の位置で決めるのが自然
  366. int m = d.Month;
  367. if (d.Day <= 7 && (m == 1 || m == 4 || m == 7 || m == 10))
  368. {
  369. caption = String.Format("{0}年{1}Q", d.Year, (m - 1) / 3 + 1);
  370. return true;
  371. }
  372. }
  373. else if (Env.CurrentIndicators.Format == ChartFormat.Yearly)
  374. {
  375. int t = td.Date;
  376. int y = t / 10000;
  377. if (y % 5 == 0)
  378. {
  379. caption = String.Format("{0}年", y);
  380. return true;
  381. }
  382. }
  383. else
  384. { // Monthly
  385. int t = td.Date;
  386. int y = t / 10000;
  387. int m = (t % 10000) / 100;
  388. if (m == 1)
  389. {
  390. caption = String.Format("{0}年", y);
  391. return true;
  392. }
  393. }
  394. return false;
  395. }
  396. private void DrawBasicChart(IntPtr hdc, int mid, TradeData td, Rectangle clip)
  397. {
  398. DrawCandle(hdc, mid, td, clip);
  399. //volume
  400. if (_pref.ShowVolume != HeightConfig.None && _brand.IsVolumeAvailable)
  401. DrawVolume(hdc, mid, td, clip);
  402. }
  403. private void DrawCurrentValue(IntPtr hdc)
  404. {
  405. DataFarm farm = _brand.ReserveFarm();
  406. int ni = _dateLine._nextToBeDrawn;
  407. if (farm.IsEmpty || farm.FilledLength <= ni) ni = -1;
  408. TradeData td = ni == -1 ? null : farm.GetByIndex(ni);
  409. DrawValueWindow(hdc, td);
  410. }
  411. private void DrawScaleLines(IntPtr hdc)
  412. {
  413. int right = _layout.ChartBodyRect.Right;
  414. //price
  415. Win32.SelectObject(hdc, _pref.PriceScalePen.Handle);
  416. double y;
  417. double top = _highPrice;
  418. int price = (int)(Math.Floor(top / _priceScaleStep) * _priceScaleStep);
  419. while (price >= _lowPrice)
  420. {
  421. y = _priceTrans.TransValue((double)price);
  422. Win32.MoveToEx(hdc, 0, (int)y, out _dummyPoint);
  423. Win32.LineTo(hdc, right, (int)y);
  424. ChartUtil.DrawText(hdc, right, (int)y - 5, price.ToString());
  425. price -= _priceScaleStep;
  426. }
  427. //volume
  428. if (_pref.ShowVolume != HeightConfig.None && _brand.IsVolumeAvailable)
  429. {
  430. Win32.SelectObject(hdc, _pref.VolumeScalePen.Handle);
  431. top = _volumeTrans.Inverse(GetPricePaneBottom());
  432. double volume = (Math.Floor(top / _volumeScaleStep) * _volumeScaleStep);
  433. y = _volumeTrans.TransValue(volume);
  434. while (volume >= 0)
  435. {
  436. Win32.MoveToEx(hdc, 0, (int)y, out _dummyPoint);
  437. Win32.LineTo(hdc, right, (int)y);
  438. ChartUtil.DrawText(hdc, right, (int)y - 6, volume.ToString());
  439. volume -= _volumeScaleStep;
  440. y = _volumeTrans.TransValue((double)volume);
  441. }
  442. }
  443. //oscillator
  444. Win32.SelectObject(hdc, _pref.OscillatorScalePen.Handle);
  445. for (int i = 0; i < OscillatorPreference.LENGTH; i++)
  446. {
  447. OscillatorPreference op = _pref.OscillatorPreferences[i];
  448. if (op.Config != HeightConfig.None)
  449. {
  450. foreach (double osc in op.ScaleValues)
  451. {
  452. y = op.Trans.TransValue(osc);
  453. Win32.MoveToEx(hdc, 0, (int)y, out _dummyPoint);
  454. Win32.LineTo(hdc, right, (int)y);
  455. ChartUtil.DrawText(hdc, right, (int)y - 6, FormatOscillatorValue(op, osc));
  456. }
  457. }
  458. }
  459. }
  460. private string FormatOscillatorValue(OscillatorPreference op, double v)
  461. {
  462. switch (op.OscillatorGroup.Type)
  463. {
  464. case ValueRange.Percent0_1:
  465. case ValueRange.Percent1_1:
  466. return (v * 100).ToString();
  467. case ValueRange.Origin0:
  468. return (v * 100).ToString("F2");
  469. default:
  470. return v.ToString();
  471. }
  472. }
  473. private void DrawCandle(IntPtr hdc, int x, TradeData td, Rectangle clip)
  474. {
  475. DrawCandle(hdc, x, td.Open, td.High, td.Low, td.Close, clip);
  476. }
  477. private void DrawCandle(IntPtr hdc, int x, double open, double high, double low, double close, Rectangle clip)
  478. {
  479. if (!ChartUtil.HasIntersectionY(clip, (int)_priceTrans.TransValue(high), (int)_priceTrans.TransValue(low))) return;
  480. Win32.SelectObject(hdc, _pref.CandlePen.Handle);
  481. int halfcw = _pref.HalfCandleWidth;
  482. //正規の枠は[x-HALF_CW, x+HALF_CW+1)
  483. if (open <= close)
  484. { //陽線
  485. int top = (int)_priceTrans.TransValue(close);
  486. int bottom = (int)_priceTrans.TransValue(open);
  487. if (_pref.InverseChart) Util.Swap(ref top, ref bottom);
  488. Win32.SelectObject(hdc, _pref.BackBrush.Handle);
  489. if (_pref.UseCandleEffect)
  490. {
  491. Win32.Rectangle(hdc, x - halfcw, top, x + halfcw + 1, bottom + 1);
  492. //上と左
  493. Win32.SelectObject(hdc, _pref.CandlePen.DarkDarkPen);
  494. Win32.MoveToEx(hdc, x + halfcw, top - 1, out _dummyPoint);
  495. Win32.LineTo(hdc, x - halfcw - 1, top - 1);
  496. Win32.LineTo(hdc, x - halfcw - 1, bottom + 1);
  497. //下と右
  498. Win32.SelectObject(hdc, _pref.CandlePen.DarkPen);
  499. Win32.MoveToEx(hdc, x + halfcw - 1, top + 1, out _dummyPoint);
  500. Win32.LineTo(hdc, x + halfcw - 1, bottom - 1);
  501. Win32.LineTo(hdc, x - halfcw, bottom - 1);
  502. }
  503. else
  504. Win32.Rectangle(hdc, x - halfcw, top, x + halfcw + 1, bottom + 1);
  505. }
  506. else
  507. { //陰線
  508. int top = (int)_priceTrans.TransValue(open);
  509. int bottom = (int)_priceTrans.TransValue(close);
  510. if (_pref.InverseChart) Util.Swap(ref top, ref bottom);
  511. Win32.SelectObject(hdc, _pref.InsenBrush.Handle);
  512. if (_pref.UseCandleEffect)
  513. {
  514. Win32.Rectangle(hdc, x - halfcw + 1, top + 1, x + halfcw, bottom);
  515. //上と左
  516. Win32.SelectObject(hdc, _pref.CandlePen.LightPen);
  517. Win32.MoveToEx(hdc, x + halfcw, top, out _dummyPoint);
  518. Win32.LineTo(hdc, x - halfcw, top);
  519. Win32.LineTo(hdc, x - halfcw, bottom + 1);
  520. //下と右
  521. Win32.SelectObject(hdc, _pref.CandlePen.DarkPen);
  522. Win32.MoveToEx(hdc, x + halfcw, top + 1, out _dummyPoint);
  523. Win32.LineTo(hdc, x + halfcw, bottom);
  524. Win32.LineTo(hdc, x - halfcw, bottom);
  525. }
  526. else
  527. Win32.Rectangle(hdc, x - halfcw, top, x + halfcw + 1, bottom + 1);
  528. }
  529. Win32.SelectObject(hdc, _pref.CandlePen.Handle);
  530. //ひげ
  531. if (high > Math.Max(open, close))
  532. {
  533. Win32.MoveToEx(hdc, x, (int)_priceTrans.TransValue(high), out _dummyPoint);
  534. Win32.LineTo(hdc, x, (int)_priceTrans.TransValue(Math.Max(open, close)));
  535. }
  536. if (low < Math.Min(open, close))
  537. {
  538. Win32.MoveToEx(hdc, x, (int)_priceTrans.TransValue(Math.Min(open, close)), out _dummyPoint);
  539. Win32.LineTo(hdc, x, (int)_priceTrans.TransValue(low));
  540. }
  541. }
  542. private void DrawFushiOrSplit(IntPtr hdc, int x, TradeData td, Rectangle clip)
  543. {
  544. bool low = false;
  545. //節
  546. int upmargin = _pref.InverseChart ? 5 : -5 - _layout.DefaultTextHeight;
  547. int downmargin = _pref.InverseChart ? -5 - _layout.DefaultTextHeight : 5;
  548. if (td.Fushi == Fushi.High)
  549. {
  550. int y = (int)_priceTrans.TransValue(td.High) + upmargin;
  551. if (ChartUtil.HasIntersectionY(clip, y, y + _layout.DefaultTextHeight))
  552. {
  553. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.FushiColor));
  554. var bp = _brand.IsBuiltIn || td.High <= 5000 ? _brand.PriceFormatString : "F0";
  555. string t = td.High.ToString(bp);
  556. ChartUtil.DrawText(hdc, x - t.Length * _layout.DefaultTextWidth / 2, y, t);
  557. }
  558. }
  559. else if (td.Fushi == Fushi.Low)
  560. {
  561. int y = (int)_priceTrans.TransValue(td.Low) + downmargin;
  562. if (ChartUtil.HasIntersectionY(clip, y, y + _layout.DefaultTextHeight))
  563. {
  564. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.FushiColor));
  565. var bp = _brand.IsBuiltIn || td.High <= 5000 ? _brand.PriceFormatString : "F0";
  566. string t = td.Low.ToString(bp);
  567. ChartUtil.DrawText(hdc, x - t.Length * _layout.DefaultTextWidth / 2, y, t);
  568. }
  569. low = true;
  570. }
  571. //分割
  572. if (_brand.SplitInfo != null)
  573. {
  574. foreach (SplitInfo si in _brand.SplitInfo)
  575. {
  576. if (td.CoversDate(si.Date))
  577. {
  578. int y = (int)_priceTrans.TransValue(td.Low) + 5 + (low ? _layout.DefaultTextHeight : 0);
  579. if (ChartUtil.HasIntersectionY(clip, y, y + _layout.DefaultTextHeight))
  580. {
  581. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.FushiColor));
  582. string t = "▲分" + si.Ratio.ToString();
  583. ChartUtil.DrawText(hdc, x - _layout.DefaultTextWidth / 2 - 2, y, t);
  584. }
  585. break;
  586. }
  587. }
  588. }
  589. }
  590. private void DrawVolume(IntPtr hdc, int x, TradeData td, Rectangle clip)
  591. {
  592. DrawVolume(hdc, x, td.Volume, clip);
  593. }
  594. private void DrawVolume(IntPtr hdc, int x, double volume, Rectangle clip)
  595. {
  596. Win32.RECT r = new Win32.RECT();
  597. r.left = x - _pref.HalfCandleWidth;
  598. r.top = (int)_volumeTrans.TransValue(volume);
  599. r.right = x + _pref.HalfCandleWidth;
  600. r.bottom = (int)_volumeTrans.TransValue(0) + 1;
  601. if (ChartUtil.HasIntersectionY(clip, r.top, r.bottom))
  602. {
  603. Win32.FillRect(hdc, ref r, _pref.VolumeBrush.Handle);
  604. Win32.POINT pt;
  605. Win32.SelectObject(hdc, _pref.VolumeBrush.LightPen);
  606. Win32.MoveToEx(hdc, r.left, r.top, out pt);
  607. Win32.LineTo(hdc, r.right + 1, r.top);
  608. Win32.MoveToEx(hdc, r.left, r.top, out pt);
  609. Win32.LineTo(hdc, r.left, r.bottom);
  610. Win32.SelectObject(hdc, _pref.VolumeBrush.DarkPen);
  611. Win32.MoveToEx(hdc, r.right, r.top + 1, out pt);
  612. Win32.LineTo(hdc, r.right, r.bottom);
  613. }
  614. }
  615. //indicatorの描画:opはオシレータ以外ではnull
  616. private void DrawIndicator(IntPtr hdc, int x, TradeData td, OscillatorPreference op, Indicator ind, Rectangle clip)
  617. {
  618. if (ind == null) return; //!!_currentOscillatorGroupがおかしいのか、nullが入っているケースがあった。原因究明したい
  619. if (ind.Target == IndicatorTarget.Volume && _pref.ShowVolume == HeightConfig.None) return;
  620. TradeData pr = td.Prev;
  621. if (pr == null) return;
  622. if (ind.TargetBrand != null && !ind.TargetBrand.Applicable(_brand.Code)) return; //適用不可
  623. double v1 = pr.GetValue(ind);
  624. double v2 = td.GetValue(ind);
  625. if (!Double.IsNaN(v1) && !Double.IsNaN(v2))
  626. {
  627. if (ind.Target == IndicatorTarget.Volume && (v1 == 0 || v2 == 0)) return; //存在しない信用残を回避
  628. //相対化表示パラメータがついていれば調整
  629. if (ind.RelativiseParam != null)
  630. {
  631. double m = _relativisedMultipliers[ind.LaneID];
  632. if (m == 0)
  633. {
  634. m = ind.RelativiseParam.CalcMultiplier(ind, td.Farm);
  635. _relativisedMultipliers[ind.LaneID] = m;
  636. }
  637. v1 *= m;
  638. v2 *= m;
  639. //基準日だったらさらに■を書く
  640. if (td.Date == ind.RelativiseParam.Date)
  641. {
  642. Win32.RECT rect = new Win32.RECT();
  643. rect.left = x - 2; rect.right = x + 2;
  644. rect.top = ConvertToY(ind.Target, null, v2) - 2; rect.bottom = rect.top + 4;
  645. Win32.FillRect(hdc, ref rect, new ZBrush(ind.Appearance.Pen.Color).Handle);
  646. }
  647. }
  648. int y1 = ConvertToY(ind.Target, op, v1);
  649. int y2 = ConvertToY(ind.Target, op, v2);
  650. if (ChartUtil.HasIntersectionY(clip, y1, y2))
  651. {
  652. Win32.SelectObject(hdc, ind.Appearance.Pen.Handle);
  653. Win32.MoveToEx(hdc, x - _layout.DatePitch, y1, out _dummyPoint);
  654. Win32.LineTo(hdc, x, y2);
  655. }
  656. }
  657. }
  658. private void DrawMouseTrackingLine(IntPtr hdc)
  659. {
  660. if (Env.Preference.MouseTrackingLineMode != MouseTrackingLineMode.None)
  661. {
  662. if (_dateLine._nextToBeDrawn != -1)
  663. {
  664. int x = (_dateLine._nextToBeDrawn - _firstDateIndex) * _layout.DatePitch + _layout.DatePitch / 2;
  665. Win32.SelectObject(hdc, _pref.MouseTrackingLinePen.Handle);
  666. Win32.MoveToEx(hdc, x, _layout.HeaderHeight, out _dummyPoint);
  667. Win32.LineTo(hdc, x, _owner.Height - _layout.FooterHeight);
  668. _dateLine._lastDrawn = _dateLine._nextToBeDrawn;
  669. }
  670. }
  671. if (Env.Preference.MouseTrackingLineMode == MouseTrackingLineMode.Full)
  672. { //!!Flagにしたほうがいいか
  673. int y = _priceLine._nextToBeDrawn;
  674. if (y >= _layout.HeaderHeight && y < GetPricePaneBottom())
  675. {
  676. Win32.SelectObject(hdc, _pref.MouseTrackingLinePen.Handle);
  677. Win32.MoveToEx(hdc, 0, y, out _dummyPoint);
  678. Win32.LineTo(hdc, _layout.ChartAreaWidth, y);
  679. double price = _priceTrans.Inverse((double)y);
  680. double yobine = Util.Yobine(_brand.Market, price);
  681. price = Math.Floor(price / yobine + 0.5) * yobine; //呼値の整数倍に修正
  682. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.MouseTrackingLinePen.Color));
  683. ChartUtil.DrawText(hdc, _layout.ChartAreaWidth, y - _layout.DefaultTextHeight / 2, price.ToString("F0"));
  684. _priceLine._lastDrawn = y;
  685. }
  686. }
  687. }
  688. private void DrawBrandInformation(IntPtr hdc)
  689. {
  690. Win32.SelectObject(hdc, _pref.HeaderHFont);
  691. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  692. AbstractBrand br = _brand;
  693. StringBuilder bld = new StringBuilder();
  694. bld.Append(EnumDescAttribute.For(typeof(MarketType)).GetDescription(br.Market));
  695. bld.Append(" コード:");
  696. bld.Append(br.CodeAsString);
  697. BasicBrand bb = br as BasicBrand;
  698. if (bb != null)
  699. {
  700. if (bb.Nikkei225) bld.Append(" 日経225採用");
  701. if (bb.Unit != 0)
  702. {
  703. bld.Append(" 単元株数:");
  704. bld.Append(bb.Unit);
  705. }
  706. }
  707. if (_brand.ReserveFarm().IsEmpty)
  708. {
  709. bld.Append(" (データが取得できません)");
  710. }
  711. else
  712. {
  713. ChartFormat format = Env.CurrentIndicators.Format;
  714. int fd = Env.Frame.ChartCanvas.DrawingEngine.FirstDate;
  715. int ld = Env.Frame.ChartCanvas.DrawingEngine.LastDate;
  716. string h = String.Format(" 表示期間:{0} - {1}", Util.FormatFullDate(fd, format), Util.FormatFullDate(ld, format));
  717. bld.Append(h);
  718. }
  719. int offset = 7; //少し右へ描画
  720. ChartUtil.DrawTextLimitedWidth(hdc, bld.ToString(), offset, _layout.HeaderHeight + 1, _layout.ChartAreaWidth - offset, _layout.DefaultTextHeight);
  721. Win32.SelectObject(hdc, _pref.DefaultHFont);
  722. }
  723. private void DrawValueWindow(IntPtr hdc, TradeData td)
  724. {
  725. Win32.SelectObject(hdc, _pref.DefaultHFont);
  726. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  727. int ix = _layout.CurrentValueRect.Left + 5;
  728. int vx = ix + _layout.DefaultTextWidth * 11;
  729. Indicator[] inds = Env.CurrentIndicators.GetIndicatorsForValueWindow();
  730. int y = _layout.HeaderHeight;
  731. if (td != null) ChartUtil.DrawText(hdc, ix, y, Util.FormatFullDate(td.Date, Env.CurrentIndicators.Format));
  732. y += _layout.DefaultTextHeight;
  733. foreach (Indicator ind in inds)
  734. {
  735. if (ind.Target == IndicatorTarget.Oscillator && !IsVisibleOscillator(ind)) continue;
  736. if (ind.TargetBrand != null && !ind.TargetBrand.Applicable(_brand.Code)) continue; //適用不可
  737. if (ind.Appearance != null)
  738. Win32.SetTextColor(hdc, Util.ToCOLORREF(ind.Appearance.Color));
  739. else
  740. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  741. ChartUtil.DrawText(hdc, ix, y, ind.Name);
  742. if (_tipBuilding)
  743. {
  744. int w = MeasureString(ind.Name);
  745. if (w > vx - ix)
  746. _tipEntries.Add(new ComplementaryTextEntry(new Rectangle(ix, y, w, _layout.DefaultTextHeight), ind.Name));
  747. }
  748. double val = Double.NaN;
  749. if (td != null)
  750. {
  751. val = td.GetValue(ind);
  752. }
  753. ChartUtil.DrawText(hdc, vx, y, Util.FormatFixedLenValue(val, 9, RetFormatString(_brand, ind, val), ind.FormatModifier));
  754. y += _layout.DefaultTextHeight;
  755. }
  756. }
  757. private string RetFormatString(AbstractBrand br, Indicator ind, double val)
  758. {
  759. switch ((PrimitiveIndicator)ind.LaneID)
  760. {
  761. case PrimitiveIndicator.Open:
  762. case PrimitiveIndicator.High:
  763. case PrimitiveIndicator.Low:
  764. case PrimitiveIndicator.Close:
  765. if (!br.IsBuiltIn && val > 5000)
  766. return "F0";
  767. break;
  768. }
  769. return ind.GetFormatString(br);
  770. }
  771. private void DrawExplanation(IntPtr hdc)
  772. {
  773. Win32.SelectObject(hdc, _pref.DefaultHFont);
  774. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  775. int ix = _layout.CurrentValueRect.Left + 5;
  776. int lx = ix + _layout.DefaultTextWidth * 14;
  777. Indicator[] inds = Env.CurrentIndicators.GetIndicatorsForExplanationWindow();
  778. int y = _layout.HeaderHeight + _layout.DefaultTextHeight * _maximumValueWindowItemCount + 30;
  779. Point pt = _owner.PointToClient(Control.MousePosition);
  780. foreach (Indicator ind in inds)
  781. {
  782. if (ind.Target == IndicatorTarget.Oscillator && !IsVisibleOscillator(ind)) continue;
  783. IndicatorAppearance ia = ind.Appearance;
  784. ZPen pen = ia == null ? _pref.DefaultPen : ia.Pen;
  785. ChartUtil.DrawText(hdc, ix, y, ind.Name);
  786. if (_tipBuilding)
  787. {
  788. int w = MeasureString(ind.Name);
  789. if (w > lx - ix)
  790. _tipEntries.Add(new ComplementaryTextEntry(new Rectangle(ix, y, w, _layout.DefaultTextHeight), ind.Name));
  791. }
  792. Win32.MoveToEx(hdc, lx, y + _layout.DefaultTextHeight / 2 - 1, out _dummyPoint);
  793. Win32.SelectObject(hdc, pen.Handle);
  794. Win32.LineTo(hdc, lx + 30, y + _layout.DefaultTextHeight / 2 - 1);
  795. y += _layout.DefaultTextHeight;
  796. }
  797. }
  798. private void DrawAccumulativeVolume(IntPtr hdc)
  799. {
  800. if (!_brand.IsVolumeAvailable || !_accumulativeVolume.Available || _priceTrans == null) return;
  801. double price = _accumulativeVolume.StartPrice;
  802. Rectangle acc_rect = _layout.AccumulativeVolumeRect;
  803. Win32.SelectObject(hdc, _pref.DefaultHFont);
  804. Win32.SetTextColor(hdc, Util.ToCOLORREF(_pref.TextColor));
  805. int char_height = (int)_pref.DefaultCharPitch.Height;
  806. //棒の半分の幅。EndPrice付近を使うのは対数グラフでも困らないようにするため
  807. int half_height = (int)Math.Abs(_priceTrans.TransValue(_accumulativeVolume.EndPrice) - _priceTrans.TransValue(_accumulativeVolume.EndPrice - _accumulativeVolume.Pitch)) / 2 - 2;
  808. if (half_height < 2) half_height = 2;
  809. ChartUtil.DrawText(hdc, acc_rect.Left, acc_rect.Top, String.Format("価格帯別出来高"));
  810. ChartUtil.DrawText(hdc, acc_rect.Left, acc_rect.Top + char_height, String.Format("{0}~", Util.FormatShortDate(_accumulativeVolume.BeginDate)));
  811. ChartUtil.DrawText(hdc, acc_rect.Left, acc_rect.Top + char_height * 2, String.Format("   {0}", Util.FormatShortDate(_accumulativeVolume.EndDate)));
  812. double scale = ChartUtil.SelectGoodValue(_accumulativeVolume.MaxVolume);
  813. if (scale < _accumulativeVolume.MaxVolume) scale = ChartUtil.SelectGoodValue(_accumulativeVolume.MaxVolume * 2); //はみ出ることがないように
  814. Trans volume_trans = Trans.Solve(0, acc_rect.Left, scale, acc_rect.Right, false, false);
  815. for (int index = 0; index < _accumulativeVolume.DataLength; index++)
  816. {
  817. int y = (int)_priceTrans.TransValue(price + _accumulativeVolume.Pitch / 2);
  818. double value = _accumulativeVolume[index];
  819. if (value != 0)
  820. {
  821. Win32.RECT r = new Win32.RECT();
  822. r.left = acc_rect.Left;
  823. r.top = y - half_height;
  824. r.right = (int)volume_trans.TransValue(value);
  825. r.bottom = y + half_height;
  826. Win32.FillRect(hdc, ref r, _pref.VolumeBrush.Handle);
  827. Win32.POINT pt;
  828. Win32.SelectObject(hdc, _pref.VolumeBrush.LightPen);
  829. Win32.MoveToEx(hdc, r.left, r.top, out pt);
  830. Win32.LineTo(hdc, r.right + 1, r.top);
  831. Win32.MoveToEx(hdc, r.right, r.top, out pt);
  832. Win32.LineTo(hdc, r.right, r.bottom);
  833. Win32.SelectObject(hdc, _pref.VolumeBrush.DarkPen);
  834. Win32.MoveToEx(hdc, r.left, r.bottom + 1, out pt);
  835. Win32.LineTo(hdc, r.right, r.bottom + 1);
  836. }
  837. price += _accumulativeVolume.Pitch;
  838. }
  839. //縦線
  840. Win32.SelectObject(hdc, _pref.VolumeScalePen.Handle);
  841. const int SCALE_COUNT = 4;
  842. for (int i = 0; i < SCALE_COUNT; i++)
  843. {
  844. int x = acc_rect.Left + acc_rect.Width / SCALE_COUNT * i;
  845. Win32.MoveToEx(hdc, x, acc_rect.Top + char_height * 3, out _dummyPoint);
  846. int y = acc_rect.Bottom - char_height * (i % 2 == 0 ? 1 : 2); //数字が大きくなりがちなので互い違いにする
  847. Win32.LineTo(hdc, x, y);
  848. string scale_string = (scale / SCALE_COUNT * i).ToString();
  849. ChartUtil.DrawText(hdc, x - (int)_pref.DefaultCharPitch.Width * scale_string.Length / 2, y, scale_string);
  850. }
  851. }
  852. //Conversions
  853. private int ConvertToY(IndicatorTarget target, OscillatorPreference op, double value)
  854. {
  855. switch (target)
  856. {
  857. case IndicatorTarget.Price:
  858. return (int)_priceTrans.TransValue(value);
  859. case IndicatorTarget.Volume:
  860. return (int)_volumeTrans.TransValue(value);
  861. case IndicatorTarget.Oscillator:
  862. return (int)op.Trans.TransValue(value);
  863. }
  864. return 0;
  865. }
  866. private int DateOffsetToX(int offset)
  867. {
  868. return offset * _layout.DatePitch + _layout.CandleMiddleOffset;
  869. }
  870. //Formats
  871. private void RecalcFormat()
  872. {
  873. int width = _owner.Width;
  874. _pref = Env.Preference;
  875. DataFarm farm = _brand.ReserveFarm();
  876. int half_height = _layout.DefaultTextHeight / 2;
  877. int end = Math.Min(farm.FilledLength, _firstDateIndex + _layout.DisplayColumnCount);
  878. double chart_bottom = (double)GetPricePaneBottom();
  879. if (chart_bottom < 0) chart_bottom = 0;
  880. //値段ゾーン
  881. if (!_pref.ScaleLock)
  882. { //Brandをリセットするとロックが外れるのでこれでよい
  883. double range_min = new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.Low), _firstDateIndex, end).Min;
  884. double range_max = new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.High), _firstDateIndex, end).Max;
  885. //ボリンジャーバンドなど、上下に広がるチャートのことを考えてちょっと広めにとる
  886. //double t = (range_max - range_min) * 0.1;
  887. //_lowPrice = range_min - t;
  888. //_highPrice = range_max + t;
  889. if (_pref.LogScale)
  890. {
  891. double t = (Math.Log10(range_max) - Math.Log10(range_min)) * 0.1;
  892. _highPrice = Math.Pow(10, Math.Log10(range_max) + t);
  893. _lowPrice = Math.Pow(10, Math.Log10(range_min) - t);
  894. }
  895. else
  896. {
  897. double t = (range_max - range_min) * 0.1;
  898. _lowPrice = range_min - t;
  899. _highPrice = range_max + t;
  900. }
  901. #if DOJIMA
  902. _priceScaleStep = ChartUtil.CalcScaleStep((_highPrice - _lowPrice)*1.2, chart_bottom - (double)_layout.HeaderHeight, 60);
  903. if(Dojima.DojimaChart.IsMusousenAvailable(Env.CurrentIndicators.Format))
  904. _lowPrice -= _priceScaleStep * 3; //下の値段に3段分余裕を作る
  905. #else
  906. _priceScaleStep = (int)ChartUtil.CalcScaleStep(_highPrice - _lowPrice, chart_bottom - (double)_layout.HeaderHeight, 60);
  907. #endif
  908. _priceTrans = Trans.Solve(_highPrice, (double)_layout.HeaderHeight, _lowPrice, chart_bottom, _pref.LogScale, _pref.InverseChart);
  909. if (_pref.ShowAccumulativeVolume)
  910. {
  911. int first_index = _dateLine._nextToBeDrawn == -1 ? farm.FilledLength - 1 : Math.Min(_dateLine._nextToBeDrawn, farm.FilledLength - 1);
  912. int price_pitch = Math.Max(1, _priceScaleStep / AccumulativeVolume.DATA_PER_SCALELINE);
  913. _accumulativeVolume.Fill(farm, first_index, range_min, price_pitch, range_max);
  914. }
  915. }
  916. //出来高ゾーン
  917. if (_pref.ShowVolume != HeightConfig.None)
  918. {
  919. double max_volume = new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.Volume), _firstDateIndex, end).Max;
  920. max_volume = Math.Max(max_volume, new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.CreditShort), _firstDateIndex, end).Max);
  921. max_volume = Math.Max(max_volume, new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.CreditLong), _firstDateIndex, end).Max);
  922. double volume_bottom = (double)GetVolumePaneBottom() - half_height;
  923. if (volume_bottom < 0) volume_bottom = 0;
  924. _volumeTrans = LinearTrans.Solve(max_volume, chart_bottom, 0, volume_bottom);
  925. _volumeScaleStep = ChartUtil.CalcScaleStep(max_volume, volume_bottom - chart_bottom, 30);
  926. }
  927. //オシレータゾーン
  928. int top = this.GetVolumePaneBottom();
  929. for (int i = 0; i < OscillatorPreference.LENGTH; i++)
  930. {
  931. OscillatorPreference op = _pref.OscillatorPreferences[i];
  932. if (op.Config != HeightConfig.None)
  933. {
  934. if (op.OscillatorGroup.Type == ValueRange.Percent0_1)
  935. {
  936. op.SetScaleValues(1, 0.5, 0);
  937. }
  938. else if (op.OscillatorGroup.Type == ValueRange.Percent1_1)
  939. {
  940. op.SetScaleValues(1, 0, -1);
  941. }
  942. else if (op.OscillatorGroup.Type == ValueRange.Origin0)
  943. {
  944. double m = 0;
  945. foreach (Indicator ind in op.OscillatorGroup)
  946. {
  947. TimeSeries ts = new IndicatorTimeSeries(farm, ind, _firstDateIndex, end);
  948. m = Math.Max(m, Math.Max(Math.Abs(ts.Max), Math.Abs(ts.Min)));
  949. }
  950. m = ChartUtil.SelectGoodValue(m);
  951. op.SetScaleValues(m, 0, -m);
  952. }
  953. else
  954. {
  955. double min = Double.MaxValue;
  956. double max = Double.MinValue;
  957. foreach (Indicator ind in op.OscillatorGroup)
  958. {
  959. TimeSeries ts = new IndicatorTimeSeries(farm, ind, _firstDateIndex, end);
  960. max = Math.Max(max, ts.Max);
  961. min = Math.Min(min, ts.Min);
  962. }
  963. double mid = (max + min) / 2;
  964. double pitch = ChartUtil.SelectGoodValue((max - min) / 2);
  965. mid = pitch * (int)(mid / pitch); //四捨五入しての整数倍
  966. op.SetScaleValues(mid + pitch, mid, mid - pitch);
  967. }
  968. op.Trans = LinearTrans.Solve(op.ScaleValues[0], top + half_height, op.ScaleValues[2], top + _layout.OscillatorPaneHeights[i] - half_height);
  969. }
  970. top += _layout.OscillatorPaneHeights[i];
  971. }
  972. //FreeLine
  973. SolidFreeLine[] sls = Env.FreeLines.Find(_brand, Env.CurrentIndicators.Format, _pref.LogScale);
  974. _freeLines.Clear();
  975. foreach (SolidFreeLine sl in sls)
  976. _freeLines.Add(new FreeLine(farm, _firstDateIndex, sl, _priceTrans));
  977. //☆Fibonacci
  978. SolidFibonacci[] sfn = Env.Fibonacci.Find(_brand, Env.CurrentIndicators.Format, _pref.LogScale);
  979. _fibonaccies.Clear();
  980. foreach (SolidFibonacci sf in sfn)
  981. _fibonaccies.Add(new Fibonacci(farm, _firstDateIndex, sf, _priceTrans));
  982. //☆Fibonacci 追加ここまで
  983. }
  984. private void RecalcValueWindowFormat()
  985. {
  986. Indicator[] inds = Env.CurrentIndicators.GetIndicatorsForValueWindow();
  987. _maximumValueWindowItemCount = 0;
  988. foreach (Indicator ind in inds)
  989. if (ind.Target != IndicatorTarget.Oscillator) _maximumValueWindowItemCount++;
  990. //これにOscillatorGroupを考慮
  991. int im = 0;
  992. foreach (OscillatorPreference op in _pref.OscillatorPreferences)
  993. {
  994. if (op.OscillatorGroup != null)
  995. im += op.OscillatorGroup.Count;
  996. }
  997. _maximumValueWindowItemCount += im;
  998. }
  999. private int GetPricePaneBottom()
  1000. {
  1001. return _layout.ChartAreaBottom - _layout.OscillatorPaneHeightTotal - _layout.VolumePaneHeight;
  1002. }
  1003. private int GetVolumePaneBottom()
  1004. {
  1005. return _layout.ChartAreaBottom - _layout.OscillatorPaneHeightTotal;
  1006. }
  1007. private bool IsVisibleOscillator(Indicator ind)
  1008. {
  1009. for (int i = 0; i < OscillatorPreference.LENGTH; i++)
  1010. {
  1011. OscillatorPreference op = _pref.OscillatorPreferences[i];
  1012. if (op.Config != HeightConfig.None)
  1013. {
  1014. OscillatorGroup g = op.OscillatorGroup;
  1015. if (g.Contains(ind)) return true;
  1016. }
  1017. }
  1018. return false;
  1019. }
  1020. //FreeLineの追加
  1021. public void FixFreeLine(FreeLine fl)
  1022. {
  1023. Env.FreeLines.Add(_brand, Env.CurrentIndicators.Format, _pref.LogScale, fl.ToSolid(_brand.ReserveFarm(), _firstDateIndex, _priceTrans));
  1024. _freeLines.Add(fl);
  1025. }
  1026. public bool RemoveHighlitedFreeLines()
  1027. {
  1028. ArrayList remain = new ArrayList();
  1029. bool f = false;
  1030. foreach (FreeLine line in _freeLines)
  1031. {
  1032. if (line.DrawMode == FreeLine.LineDrawMode.Normal)
  1033. {
  1034. remain.Add(line);
  1035. }
  1036. else
  1037. {
  1038. if (line.ID != -1) Env.FreeLines.Remove(line.ID);
  1039. f = true;
  1040. }
  1041. }
  1042. _freeLines = remain;
  1043. return f; //1つでも消去したらtrueを返す
  1044. }
  1045. //追加ここまで
  1046. //☆Fibonacci Fibonacciの追加
  1047. public void FixFibonacci(Fibonacci fl)
  1048. {
  1049. Env.Fibonacci.Add(_brand, Env.CurrentIndicators.Format, _pref.LogScale, fl.ToSolid(_brand.ReserveFarm(), _firstDateIndex, _priceTrans));
  1050. _fibonaccies.Add(fl);
  1051. }
  1052. public bool RemoveHighlitedFibonacci()
  1053. {
  1054. ArrayList remain = new ArrayList();
  1055. bool f = false;
  1056. foreach (Fibonacci line in _fibonaccies)
  1057. {
  1058. if (line.DrawMode == Fibonacci.LineDrawMode.Normal)
  1059. {
  1060. remain.Add(line);
  1061. }
  1062. //☆Fibonacci 20180816 追加ここから
  1063. else if (line.DrawMode == Fibonacci.LineDrawMode.Move)
  1064. {
  1065. remain.Add(line);
  1066. }//ここまで
  1067. else
  1068. {
  1069. if (line.ID != -1) Env.Fibonacci.Remove(line.ID);
  1070. f = true;
  1071. }
  1072. }
  1073. _fibonaccies = remain;
  1074. return f; //1つでも消去したらtrueを返す
  1075. }
  1076. //特殊なやつの描画
  1077. //一目均衡表の雲
  1078. private bool IchimokuKumoIsAvailable()
  1079. {
  1080. IList l = Env.CurrentIndicators.IchimokuKumo;
  1081. if (l.Count < 2) return false;
  1082. Indicator indA = (Indicator)l[0];
  1083. Indicator indB = (Indicator)l[1];
  1084. //両方が描画されるときのみ雲を描く
  1085. return ((indA.Display & IndicatorDisplay.Chart) != IndicatorDisplay.None && indA.Appearance.Style != IndicatorStyle.None) &&
  1086. ((indB.Display & IndicatorDisplay.Chart) != IndicatorDisplay.None && indB.Appearance.Style != IndicatorStyle.None);
  1087. }
  1088. private void DrawIchimokuKumo(IntPtr hdc, DataFarm farm, int index, int end, Rectangle clip)
  1089. {
  1090. while (index < end)
  1091. {
  1092. int x = (index - _firstDateIndex) * _layout.DatePitch;
  1093. int mid = x + _layout.CandleMiddleOffset;
  1094. TradeData td = farm.GetByIndex(index);
  1095. if (clip.Left <= x + _pref.DatePitch && x - _layout.DatePitch < clip.Right)
  1096. {
  1097. DrawIchimokuKumoParts(hdc, mid, td);
  1098. }
  1099. index++;
  1100. }
  1101. }
  1102. private void DrawIchimokuKumoParts(IntPtr hdc, int x, TradeData td)
  1103. {
  1104. IList l = Env.CurrentIndicators.IchimokuKumo;
  1105. Indicator indA = (Indicator)l[0];
  1106. Indicator indB = (Indicator)l[1];
  1107. double vA = td.GetValue(indA);
  1108. double vB = td.GetValue(indB);
  1109. if (Double.IsNaN(vA) || Double.IsNaN(vB)) return;
  1110. int y1A = (int)_priceTrans.TransValue(vA);
  1111. int y1B = (int)_priceTrans.TransValue(vB);
  1112. TradeData pr = td.Prev;
  1113. if (pr == null) return;
  1114. double pA = pr.GetValue(indA);
  1115. double pB = pr.GetValue(indB);
  1116. if (Double.IsNaN(pA) || Double.IsNaN(pB)) return;
  1117. int y0A = (int)_priceTrans.TransValue(pA);
  1118. int y0B = (int)_priceTrans.TransValue(pB);
  1119. //ここまでで値が出揃った
  1120. int x0 = x - _layout.DatePitch;
  1121. if (pA >= pB && vA >= vB)
  1122. PaintKumo(hdc, indA.Appearance.Color, x0, y0A, x, y1A, x, y1B, x0, y0B);
  1123. else if (pA <= pB && vA <= vB)
  1124. PaintKumo(hdc, indB.Appearance.Color, x0, y0B, x, y1B, x, y1A, x0, y0A);
  1125. else
  1126. { //交差。めんどうくさいなあ
  1127. double r = (double)(Math.Abs(y0A - y0B)) / (double)(Math.Abs(y0A - y0B) + Math.Abs(y1A - y1B));
  1128. int cx = x - (int)((double)_layout.DatePitch * (1 - r));
  1129. int cy = (int)(y1A * r + y0A * (1 - r));
  1130. if (pA >= pB)
  1131. {
  1132. PaintKumo(hdc, indA.Appearance.Color, cx, cy, x0, y0A, x0, y0B);
  1133. PaintKumo(hdc, indB.Appearance.Color, cx, cy, x, y1A, x, y1B);
  1134. }
  1135. else
  1136. {
  1137. PaintKumo(hdc, indB.Appearance.Color, cx, cy, x0, y0A, x0, y0B);
  1138. PaintKumo(hdc, indA.Appearance.Color, cx, cy, x, y1A, x, y1B);
  1139. }
  1140. }
  1141. }
  1142. private void PaintKumo(IntPtr hdc, Color col, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
  1143. {
  1144. Win32.POINT[] points = new Win32.POINT[4];
  1145. points[0].x = x0;
  1146. points[0].y = y0;
  1147. points[1].x = x1;
  1148. points[1].y = y1;
  1149. points[2].x = x2;
  1150. points[2].y = y2;
  1151. points[3].x = x3;
  1152. points[3].y = y3;
  1153. IntPtr rgn = Win32.CreatePolygonRgn(points, 4, 2); //2はWINDING
  1154. IntPtr brush = Win32.CreateSolidBrush(Util.ToCOLORREF(col));
  1155. Win32.FillRgn(hdc, rgn, brush);
  1156. Win32.DeleteObject(brush);
  1157. Win32.DeleteObject(rgn);
  1158. }
  1159. private void PaintKumo(IntPtr hdc, Color col, int x0, int y0, int x1, int y1, int x2, int y2)
  1160. {
  1161. Win32.POINT[] points = new Win32.POINT[3];
  1162. points[0].x = x0;
  1163. points[0].y = y0;
  1164. points[1].x = x1;
  1165. points[1].y = y1;
  1166. points[2].x = x2;
  1167. points[2].y = y2;
  1168. IntPtr rgn = Win32.CreatePolygonRgn(points, 3, 2); //2はWINDING
  1169. IntPtr brush = Win32.CreateSolidBrush(Util.ToCOLORREF(col));
  1170. Win32.FillRgn(hdc, rgn, brush);
  1171. Win32.DeleteObject(brush);
  1172. Win32.DeleteObject(rgn);
  1173. }
  1174. //y座標から、そこに最も近い呼値に対応したy座標に変換する
  1175. public int NormalizeByYobine(int y)
  1176. {
  1177. if (_priceTrans == null || _brand == null) return y;
  1178. double price = _priceTrans.Inverse(y);
  1179. double yobine = Util.Yobine(_brand.Market, price);
  1180. return (int)_priceTrans.TransValue(yobine * Math.Round(price / yobine));
  1181. }
  1182. //utils
  1183. private int MeasureString(string text)
  1184. {
  1185. int n = 0;
  1186. for (int i = 0; i < text.Length; i++)
  1187. {
  1188. char ch = text[i];
  1189. if (ch <= 0xFF)
  1190. n++;
  1191. else
  1192. n += 2;
  1193. }
  1194. return n * _layout.DefaultTextWidth;
  1195. }
  1196. #if DOJIMA
  1197. private HalfDailyDataFarm _halfDailyDataFarm;
  1198. private void DrawHalfDailyChart(IntPtr hdc, DailyDataFarm farm, int x, TradeData td, Rectangle clip) {
  1199. if(_halfDailyDataFarm==null)
  1200. _halfDailyDataFarm = Dojima.DojimaUtil.HalfDailyDataFarmCache.Get(farm);
  1201. int width = _layout.CandleMiddleOffset / 2;
  1202. bool vol = _pref.ShowVolume!=HeightConfig.None && _brand.IsVolumeAvailable;
  1203. HalfDailyDataUnit unit = _halfDailyDataFarm.GetData(td.Index, HalfDay.Zenba);
  1204. DrawCandle(hdc, x + width, unit.open, unit.high, unit.low, unit.close, clip);
  1205. if(vol) DrawVolume(hdc, x + width, unit.volume, clip);
  1206. unit = _halfDailyDataFarm.GetData(td.Index, HalfDay.Goba);
  1207. DrawCandle(hdc, x + width*3, unit.open, unit.high, unit.low, unit.close, clip);
  1208. if(vol) DrawVolume(hdc, x + width*3, unit.volume, clip);
  1209. //さらに週末の後場にマーク
  1210. bool flag = true;
  1211. DateTime mark = Util.IntToDate(td.Date);
  1212. mark = mark.AddDays(1);
  1213. while(mark.DayOfWeek!=DayOfWeek.Saturday) {
  1214. if(Util.IsMarketOpenDate(mark)) {
  1215. flag = false; //翌日以降土曜日以前に市場の開いている日を見つけたら描画しない
  1216. break;
  1217. }
  1218. mark = mark.AddDays(1);
  1219. }
  1220. if(flag) {
  1221. double p = td.Low + _priceScaleStep / 5 * (_pref.InverseChart? 1 : -1);
  1222. ZBrush cb = new ZBrush(Color.Red);
  1223. ZPen cp = new ZPen(Color.Red, ZPen.PenStyle.Normal);
  1224. IntPtr ob = Win32.SelectObject(hdc, cb.Handle);
  1225. IntPtr op = Win32.SelectObject(hdc, cp.Handle);
  1226. int t = _layout.CandleMiddleOffset / 3; //半径
  1227. int y = (int)_priceTrans.TransValue(p);
  1228. Win32.Ellipse(hdc, x+width*3-t, y-t, x+width*3+t, y+t);
  1229. Win32.SelectObject(hdc, ob);
  1230. Win32.SelectObject(hdc, op);
  1231. cb.Dispose();
  1232. cp.Dispose();
  1233. }
  1234. }
  1235. #endif
  1236. }
  1237. internal class ChartUtil
  1238. {
  1239. public static double CalcScaleStep(double range, double pane_height, double standard_pitch_in_pixel)
  1240. {
  1241. if (pane_height <= 0) return 1;
  1242. double t = range / (pane_height / standard_pitch_in_pixel);
  1243. return SelectGoodValue(t);
  1244. }
  1245. //srcに最も近い、切りの良い数を返す。切りがよいとは、(1 or 2.5 or 5) * 10^n
  1246. public static double SelectGoodValue(double src)
  1247. {
  1248. if (src < 0)
  1249. return -SelectGoodValue(-src);
  1250. double log = Math.Log10(src);
  1251. int n = (int)Math.Floor(log);
  1252. double a = log - n;
  1253. double b;
  1254. if (a < 0.16)
  1255. b = 1;
  1256. else if (a < 0.5)
  1257. b = 2.5;
  1258. else if (a < 0.83)
  1259. b = 5;
  1260. else
  1261. {
  1262. b = 1;
  1263. n++;
  1264. }
  1265. if (n > 0)
  1266. for (int i = 0; i < n; i++) b *= 10;
  1267. else
  1268. for (int i = 0; i < -n; i++) b /= 10;
  1269. return b;
  1270. }
  1271. public static void DrawText(IntPtr hdc, int x, int y, string text)
  1272. {
  1273. unsafe
  1274. {
  1275. int len = text.Length;
  1276. fixed (char* p = text)
  1277. {
  1278. Win32.TextOut(hdc, x, y, p, len);
  1279. }
  1280. }
  1281. }
  1282. private static Win32.RECT _tempRect = new Win32.RECT();
  1283. public static void DrawTextLimitedWidth(IntPtr hdc, string text, int x, int y, int width, int height)
  1284. {
  1285. _tempRect.left = x;
  1286. _tempRect.top = y;
  1287. _tempRect.right = x + width;
  1288. _tempRect.bottom = y + height;
  1289. Win32.DrawText(hdc, text, text.Length, ref _tempRect, 0);
  1290. }
  1291. public static bool HasIntersectionY(Rectangle clip, int y1, int y2)
  1292. {
  1293. if (y1 > y2)
  1294. {
  1295. int t = y1;
  1296. y1 = y2;
  1297. y2 = t;
  1298. }
  1299. return !(y1 > clip.Bottom || y2 < clip.Top);
  1300. }
  1301. }
  1302. internal class ComplementaryTextEntry
  1303. {
  1304. public Rectangle rect;
  1305. public string text;
  1306. public ComplementaryTextEntry(Rectangle r, string t)
  1307. {
  1308. rect = r;
  1309. text = t;
  1310. }
  1311. }
  1312. }
Download Printable view

URL of this paste

Embed with JavaScript

Embed with iframe

Raw text