# Pastebin: OmegaChart Fibonacciリトレースメント Fibonacci.cs 新規追加 ※差し替え その２

Format
Plain text
Post date
2018-01-13 16:47
Publication Period
Unlimited
` using System; using System.Collections; using System.Drawing; using System.Text;  using Zanetti.Data; using Travis.Storage;  namespace Zanetti.UI {     /// <summary>     /// Fibonacci の概要の説明です。     /// </summary>     internal class Fibonacci     {         private PointF _pivot;         private PointF _destination;         private int _id; //SolidFibonacciからの作成時のみセット、それ以外は-1         private LineDrawMode _mode;          public enum LineDrawMode         {             Normal,             Hilight         }          public Fibonacci(PointF p)         {             _pivot = p;             _destination = p;             _id = -1;         }         public Fibonacci(PointF p1, PointF p2)         {             _pivot = p1;             _destination = p2;             _id = -1;         }         //リサイズしたときなどの再計算         public Fibonacci(DataFarm farm, int firstdateindex, SolidFibonacci fl, Trans value_to_y)         {             int p = Env.Layout.DatePitch;             _pivot = new PointF((farm.DateToIndex(fl._date1) - firstdateindex) * p + p / 2, (float)value_to_y.TransValue(fl._value1));             _destination = new PointF((farm.DateToIndex(fl._date2) - firstdateindex) * p + p / 2, (float)value_to_y.TransValue(fl._value2));             _id = fl._id;         }          public PointF Pivot         {             get             {                 return _pivot;             }             set             {                 _pivot = value;             }         }         public PointF Destination         {             get             {                 return _destination;             }             set             {                 _destination = value;             }         }         public LineDrawMode DrawMode         {             get             {                 return _mode;             }             set             {                 _mode = value;             }         }         public int ID         {             get             {                 return _id;             }         }          public void SetHighPriceAndLowPrice(DataFarm farm, Trans pricetrans, float x1, float x2, int FirstDateIndex)         {             if (x1 > Env.Layout.ChartAreaWidth || x2 > Env.Layout.ChartAreaWidth)                 return;             int ind1 = FirstDateIndex + (int)Math.Floor((double)Math.Min(x1, x2) / Env.Layout.DatePitch);             int ind2 = FirstDateIndex + (int)Math.Floor((double)Math.Max(x1, x2) / Env.Layout.DatePitch);             if (ind1 < 0) ind1 = 0;             if (ind2 < 0) ind2 = 0;             if (ind1 >= farm.TotalLength) ind1 = farm.FilledLength - 1;             if (ind2 >= farm.TotalLength) ind2 = farm.FilledLength - 1;             //最高値と最安値の株価             //double range_max = new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.High), ind1, ind2).Max;             //double range_min = new IndicatorTimeSeries(farm, Env.CurrentIndicators.GetPrimitive(PrimitiveIndicator.Low), ind1, ind2).Min;             double range_max = Max(farm, ind1, ind2);             double range_min = Min(farm, ind1, ind2);             //最高値と最安値の画面上の位置             double top = pricetrans.TransValue(range_max);             double bot = pricetrans.TransValue(range_min);             _pivot = new PointF(x1, (float)bot);             _destination = new PointF(x2, (float)top);         }         private double Max(DataFarm farm, int ind1, int ind2)         {             var pos = ind1;             var max = double.MinValue;             var last = ind2 > farm.FilledLength ? farm.FilledLength - 1 : ind2;             while (pos <= last)             {                 var a = BitConverter.ToInt32(farm.RawDataImage, pos++ * 32 + 4 * 2)  * farm.Brand.PriceScale;                 if (max < a) max = a;             }             return max;         }         private double Min(DataFarm farm, int ind1, int ind2)         {             var pos = ind1;             var min = double.MaxValue;             var last = ind2 > farm.FilledLength ? farm.FilledLength - 1 : ind2;             while (pos <= last)             {                 var a = BitConverter.ToInt32(farm.RawDataImage, pos++ * 32 + 4 * 3)  * farm.Brand.PriceScale;                 if (min > a) min = a;             }             return min;         }         public Rectangle GetInclusion(Rectangle rect)         {             if (_pivot == _destination)                 return new Rectangle(new Point((int)_pivot.X, (int)_pivot.Y), new Size(0, 0));             Point[] es = GetEdge(rect, new Point((int)_pivot.X, (int)_pivot.Y), new Point((int)_destination.X, (int)_destination.Y));             return new Rectangle(Math.Min(es[0].X, es[1].X), Math.Min(es[0].Y, es[1].Y), Math.Abs(es[0].X - es[1].X), Math.Abs(es[0].Y - es[1].Y));         }          //十分に離した位置でないと線を確定させないようにする         public bool PivotHasEnoughDistanceTo(PointF pt)         {             return Math.Abs(_pivot.X - pt.X) > 10 || Math.Abs(_pivot.Y - pt.Y) > 10;         }          public void Draw(Trans pricetrans, Rectangle rect, IntPtr hdc)         {             Win32.POINT pt = new Win32.POINT();             Win32.SelectObject(hdc, _mode == LineDrawMode.Normal ? Env.Preference.FibonacciPen.Handle : Env.Preference.FibonacciBoldPen.Handle);             PointF p1 = _pivot;             PointF p2 = _destination;             var m = Math.Min(p1.X, p2.X);             var l = Math.Max(p1.X, p2.X);             var y1 = 0F;             var y2 = 0F;             var y3 = 0F;             var y4 = 0F;             var y5 = 0F;             var k1 = .0;             var k2 = .0;             var k3 = .0;             var k4 = .0;             var k5 = .0;              if (Env.Preference.LogScale)             {                 k1 = pricetrans.Inverse(Math.Min(p1.Y, p2.Y));                 k2 = pricetrans.Inverse(Math.Abs(p1.Y - p2.Y) * 0.382 + Math.Min(p1.Y, p2.Y));                 k3 = pricetrans.Inverse(Math.Abs(p1.Y - p2.Y) * 0.500 + Math.Min(p1.Y, p2.Y));                 k4 = pricetrans.Inverse(Math.Abs(p1.Y - p2.Y) * 0.618 + Math.Min(p1.Y, p2.Y));                 k5 = pricetrans.Inverse(Math.Max(p1.Y, p2.Y));                 y1 = Math.Min(p1.Y, p2.Y);                 y2 = (float)(Math.Abs(p1.Y - p2.Y) * 0.382 + Math.Min(p1.Y, p2.Y));                 y3 = (p1.Y + p2.Y) / 2;                 y4 = (float)(Math.Abs(p1.Y - p2.Y) * 0.618 + Math.Min(p1.Y, p2.Y));                 y5 = Math.Max(p1.Y, p2.Y);             }             else             {                 k1 = pricetrans.Inverse(Math.Min(p1.Y, p2.Y));                 k5 = pricetrans.Inverse(Math.Max(p1.Y, p2.Y));                 k2 = Math.Abs(k1 - k5) * 0.618 + k5;                 k3 = (k5 + k1) / 2;                 k4 = Math.Abs(k1 - k5) * 0.382 + k5;                 y1 = Math.Min(p1.Y, p2.Y);                 y2 = (float)pricetrans.TransValue(k2);                 y3 = (float)pricetrans.TransValue(k3);                 y4 = (float)pricetrans.TransValue(k4);                 y5 = Math.Max(p1.Y, p2.Y);             }             DrawTheLine(hdc, m, l, y1, k1, out pt);             DrawTheLine(hdc, m, l, y2, k2, out pt);             DrawTheLine(hdc, m, l, y3, k3, out pt);             DrawTheLine(hdc, m, l, y4, k4, out pt);             DrawTheLine(hdc, m, l, y5, k5, out pt);         }          private void DrawTheLine(IntPtr hdc, float px1, float px2, float py, double kabuka, out Win32.POINT pt)         {             Win32.MoveToEx(hdc, (int)px1, (int)py, out pt);             Win32.LineTo(hdc, (int)px2, (int)py);             DrawText(hdc, (int)px2, (int)py, kabuka);         }         private void DrawText(IntPtr hdc, int x, int y, double d)         {             Win32.SetTextColor(hdc, Util.ToCOLORREF(Color.White));             ChartUtil.DrawText(hdc, x + 3, y - 6, string.Format("{0:N}", d));         }          //p1,p2がrectに入っているとき、p1からp2に伸ばした線とp2からp1に伸ばした線がそれぞれrectと交差するところを返す         private static Point[] GetEdge(Rectangle rect, Point p1, Point p2)         {             Point[] result = new Point[2];             ArrayList ar = GetAllEdges(rect, p1, p2);             if (ar.Count == 2) return (Point[])ar.ToArray(typeof(Point));              result[0] = (Point)(p1.X > p2.X ? ar[1] : ar[2]);             result[1] = (Point)(p1.X > p2.X ? ar[2] : ar[1]);             return result;         }         //p1とp2を結ぶ線がrectを構成する４直線と交差する点を返す。水平・垂直のときは２個になる         private static ArrayList GetAllEdges(Rectangle rect, Point p1, Point p2)         {             ArrayList ar = new ArrayList();             if (p1.X == p2.X)             {                 ar.Add(new Point(p1.X, p1.Y < p2.Y ? rect.Bottom : rect.Top));                 ar.Add(new Point(p1.X, p1.Y > p2.Y ? rect.Bottom : rect.Top));                 return ar;             }             else if (p1.Y == p2.Y)             {                 ar.Add(new Point(p1.X < p2.X ? rect.Right : rect.Left, p1.Y));                 ar.Add(new Point(p1.X > p2.X ? rect.Right : rect.Left, p1.Y));                 return ar;             }              LinearTrans lt = LinearTrans.Solve(p1.X, p1.Y, p2.X, p2.Y);             ar.Add(new Point(rect.Left, (int)lt.TransValue(rect.Left)));             ar.Add(new Point(rect.Right, (int)lt.TransValue(rect.Right)));             ar.Add(new Point((int)lt.Inverse(rect.Top), rect.Top));             ar.Add(new Point((int)lt.Inverse(rect.Bottom), rect.Bottom));             //この４点をX座標の順に並べ、２番目と３番目が答え             ar.Sort(new PointComparer());             return ar;         }         private class PointComparer : IComparer         {              public int Compare(object x, object y)             {                 return ((Point)x).X - ((Point)y).X;             }         }          public SolidFibonacci ToSolid(DataFarm farm, int firstdateindex, Trans value_to_y)         {             SolidFibonacci fl = new SolidFibonacci();             int ind1 = firstdateindex + (int)Math.Floor((double)_pivot.X / Env.Layout.DatePitch);             int ind2 = firstdateindex + (int)Math.Floor((double)_destination.X / Env.Layout.DatePitch);              LinearTrans tr = LinearTrans.Solve(ind1, _pivot.Y, ind2, _destination.Y);             double y1 = _pivot.Y;             if (ind1 >= farm.FilledLength)             {                 ind1 = farm.FilledLength - 1;                 y1 = tr.TransValue(ind1);             }             else if (ind1 < 0)             {                 ind1 = 0;                 y1 = tr.TransValue(ind1);             }             fl._date1 = farm.GetByIndex(ind1).Date;             fl._value1 = value_to_y.Inverse(y1);              double y2 = _destination.Y;             if (ind2 >= farm.FilledLength)             {                 ind2 = farm.FilledLength - 1;                 y2 = tr.TransValue(ind2);             }             else if (ind2 < 0)             {                 ind2 = 0;                 y2 = tr.TransValue(0);             }             fl._date2 = farm.GetByIndex(ind2).Date;             //fl._value2 = value_to_y.Inverse(y2);             fl._value2 = value_to_y.Inverse(_destination.Y);             if (_id == -1)             {                 fl._id = SolidFibonacci.NextID++;                 _id = fl._id;             }             else             {                 fl._id = _id;             }             return fl;         }          //p1,p2を結ぶ直線とpの距離を返す         public double GetDistance(Point p)         {             double[] par = GetNormalizedParam();             return Math.Abs(par[0] * p.X + par[1] * p.Y + par[2]);         }          //両端を通る直線を ax+by+c=0, a^2+b^2=1 となる形式でa,b,cの配列で返す         private double[] GetNormalizedParam()         {             double a, b, c;             if (_pivot.X == _destination.X)             {                 a = 1;                 b = 0;             }             else             {                 double d = -(_pivot.Y - _destination.Y) / (double)(_pivot.X - _destination.X);                 b = Math.Sqrt(1 / (1 + d * d));                 a = b * d;             }             c = -(a * _pivot.X + b * _pivot.Y);             return new double[] { a, b, c };         }     }      internal class SolidFibonacci     {         public int _id;         public int _code;         public ChartFormat _targetFormat;         public bool _logScale;         public int _date1;         public double _value1;         public int _date2;         public double _value2;           private static int _nextID;         public static int NextID         {             get             {                 return _nextID;             }             set             {                 _nextID = value;             }         }     }      internal class FibonacciCollection     {         private ArrayList _data;         public FibonacciCollection()         {             _data = new ArrayList();         }         public int Count         {             get             {                 return _data.Count;             }         }          public void Add(AbstractBrand br, ChartFormat format, bool logScale, SolidFibonacci fl)         {             fl._code = br.Code;             fl._targetFormat = format;             fl._logScale = logScale;             _data.Add(fl);         }          public SolidFibonacci[] Find(AbstractBrand br, ChartFormat format, bool logScale)         {             ArrayList t = new ArrayList();             foreach (SolidFibonacci fl in _data)             {                 if (fl._code == br.Code && fl._targetFormat == format && fl._logScale == logScale)                     t.Add(fl);             }             return (SolidFibonacci[])t.ToArray(typeof(SolidFibonacci));         }          public void ClearAll()         {             _data.Clear();         }         public void Clear(AbstractBrand br, ChartFormat format, bool logScale)         {             ArrayList temp = new ArrayList();             IEnumerator ie = _data.GetEnumerator();             while (ie.MoveNext())             {                 SolidFibonacci fl = (SolidFibonacci)ie.Current;                 if (!(fl._code == br.Code && fl._targetFormat == format && fl._logScale == logScale))                     temp.Add(fl);             }             _data = temp;         }         public void Remove(int id)         {             for (int i = 0; i < _data.Count; i++)             {                 SolidFibonacci l = (SolidFibonacci)_data[i];                 if (l._id == id)                 {                     _data.RemoveAt(i);                     break;                 }             }         }           public void Load(StorageNode parent)         {             string t = parent["fibonacci-lines"];             if (t == null) return;             foreach (string ee in t.Split(','))             {                 if (ee == null) continue;                 if (ee.Trim() == string.Empty) continue;                 SolidFibonacci fl = new SolidFibonacci();                 string[] e = ee.Split(':');                 fl._code = Int32.Parse(e[0]);                 switch (e[1])                 {                     case "D":                         fl._targetFormat = ChartFormat.Daily;                         fl._logScale = false;                         break;                     case "W":                         fl._targetFormat = ChartFormat.Weekly;                         fl._logScale = false;                         break;                     case "M":                         fl._targetFormat = ChartFormat.Monthly;                         fl._logScale = false;                         break;                     case "Y":                         fl._targetFormat = ChartFormat.Yearly;                         fl._logScale = false;                         break;                     case "DL":                         fl._targetFormat = ChartFormat.Daily;                         fl._logScale = true;                         break;                     case "WL":                         fl._targetFormat = ChartFormat.Weekly;                         fl._logScale = true;                         break;                     case "ML":                         fl._targetFormat = ChartFormat.Monthly;                         fl._logScale = true;                         break;                     case "YL":                         fl._targetFormat = ChartFormat.Yearly;                         fl._logScale = true;                         break;                 }                 fl._date1 = Int32.Parse(e[2]);                 fl._value1 = Double.Parse(e[3]);                 fl._date2 = Int32.Parse(e[4]);                 fl._value2 = Double.Parse(e[5]);                 fl._id = SolidFibonacci.NextID++;                 _data.Add(fl);             }         }         public void SaveTo(StorageNode parent)         {             StringBuilder bld = new StringBuilder();             foreach (SolidFibonacci sl in _data)             {                 if (bld.Length > 0) bld.Append(",");                 String format;                 switch (sl._targetFormat)                 {                     case ChartFormat.Daily:                     default:                         format = "D";                         break;                     case ChartFormat.Weekly:                         format = "W";                         break;                     case ChartFormat.Monthly:                         format = "M";                         break;                     case ChartFormat.Yearly:                         format = "Y";                         break;                 }                 if (sl._logScale)                 {                     format += "L";                 }                 bld.Append(String.Format("{0}:{1}:{2}:{3:F2}:{4}:{5:F2}", sl._code, format, sl._date1, sl._value1, sl._date2, sl._value2));             }             parent["fibonacci-lines"] = bld.ToString();         }     } }`