Pastebin: OmegaChart Fibonacciトレースメント ChartDrawing.cs 追加修正ポイントには//☆Fibonacci

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

URL of this paste

Embed with JavaScript

Embed with iframe

Raw text