DA
Topics
07 Mar 2019, 21:46
1685
7
Replies
daniel.agg
08 Mar 2019, 10:07
That's strange, the .cs files should have been in the corresponding subfolders.
Anyway, here's the bot:
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.Internet)] public class MACDTestBot : Robot { #region indicator parameters [Parameter("Divergence Ledge", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)] public int Divergence_Ledge { get; set; } [Parameter("Divergence Extremums", DefaultValue = false)] public bool Divergence_Extremums { get; set; } [Parameter("Divergence Min Length", DefaultValue = 6, MinValue = 4, MaxValue = 10, Step = 1)] public int Divergence_Min_Length { get; set; } [Parameter("Last Points", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)] public int Last_Points { get; set; } [Parameter("MACD: Short Cycle", DefaultValue = 12)] public int MACD_Short_Cycle { get; set; } [Parameter("MACD: Long Cycle", DefaultValue = 26)] public int MACD_Long_Cycle { get; set; } [Parameter("MACD: Signal Period", DefaultValue = 9)] public int MACD_Signal_Period { get; set; } [Parameter("MACD: Reverse", DefaultValue = false)] public bool MACD_Reverse { get; set; } #endregion private MACDDivergence indicator; private int indicatorDataCount; protected override void OnStart() { indicator = Indicators.GetIndicator<MACDDivergence>( Divergence_Ledge, Divergence_Extremums, Divergence_Min_Length, Last_Points, MACD_Short_Cycle, MACD_Long_Cycle, MACD_Signal_Period, MACD_Reverse); indicatorDataCount = indicator.Data.Count(); } protected override void OnTick() { if(indicatorDataCount != indicator.Data.Count()) { // do something } } protected override void OnStop() { // Put your deinitialization logic here } } }
And here's the indicator:
using System; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; using cAlgo.Indicators; //using System.Linq; using System.Collections.Generic; namespace cAlgo.Indicators { [Indicator(TimeZone = TimeZones.UTC, IsOverlay = false, AutoRescale = true, ScalePrecision = 7, AccessRights = AccessRights.None)] public class MACDDivergence : Indicator { [Parameter("Divergence Ledge", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)] public int Divergence_Ledge { get; set; } [Parameter("Divergence Extremums", DefaultValue = false)] public bool Divergence_Extremums { get; set; } [Parameter("Divergence Min Length", DefaultValue = 6, MinValue = 4, MaxValue = 10, Step = 1)] public int Divergence_Min_Length { get; set; } [Parameter("Last Points", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)] public int Last_Points { get; set; } [Parameter("MACD: Short Cycle", DefaultValue = 12)] public int MACD_Short_Cycle { get; set; } [Parameter("MACD: Long Cycle", DefaultValue = 26)] public int MACD_Long_Cycle { get; set; } [Parameter("MACD: Signal Period", DefaultValue = 9)] public int MACD_Signal_Period { get; set; } [Parameter("MACD: Reverse", DefaultValue = false)] public bool MACD_Reverse { get; set; } [Output("Main", PlotType = PlotType.Histogram, Color = Colors.DeepSkyBlue)] public IndicatorDataSeries Result { get; set; } /// Indicator private MacdHistogram I_MACD; /// Properties string Chart_Object_Title = "MACD Divergence"; private DivergenceType HIGH = DivergenceType.High; private DivergenceType LOW = DivergenceType.Low; private ExtremumActionType for_Update = ExtremumActionType.Update; private ExtremumActionType for_New = ExtremumActionType.New; /// Data to use in Bot private List<Label> High_Extremums = new List<Label>(); private List<Label> Low_Extremums = new List<Label>(); public List<Divergence> Data = new List<Divergence>(); public List<TrendType> Trend = new List<TrendType>(); /// Models public struct Divergence { public DivergenceType T; public Label A; public Label B; public Divergence(DivergenceType _Type = DivergenceType.None, Label Label_A = new Label(), Label Label_B = new Label()) { T = _Type; A = Label_A; B = Label_B; } public string Text { get { return string.Format("- A - {0} - B - {1}", A.Text, B.Text); } } public Colors Color { get { switch (T) { case DivergenceType.High: return Colors.SpringGreen; break; case DivergenceType.Low: return Colors.DeepPink; break; default: return Colors.Yellow; break; } } } } public struct Label { public Point MACD; public Point MS; public Label(Point M1 = new Point(), Point M2 = new Point()) { MACD = M1; MS = M2; } public string Text { get { return string.Format("MACD = {0} MS = {1}", MACD.Text, MS.Text); } } } public struct Point { public int Index; public double Value; public Point(int I = 0, double V = 0) { Index = I; Value = V; } public string Text { get { return string.Format("{0} ({1})", Value.ToString("N6"), Index); } } } public enum ExtremumActionType { Update, New } public enum DivergenceType { High, Low, None } public enum TrendType { Up, Down, None } /// TODO: Init protected override void Initialize() { I_MACD = Indicators.MacdHistogram(MACD_Short_Cycle, MACD_Long_Cycle, MACD_Signal_Period); Print("MACD Divergence Calculator is initialized. Results = {0} Data = {1} Data_Trend = {2}", Result.Count, Data.Count, Trend.Count); } /// TODO: Indicator public override void Calculate(int index) { /// MACD Calc Result[index] = MACD_Reverse ? I_MACD.Histogram[index] - I_MACD.Signal[index] : I_MACD.Signal[index] - I_MACD.Histogram[index]; /// MACD Divergence if (index <= Divergence_Ledge) return; /// TODO: High Divergence Point MACD_Max = Max_MACD(From: index - 1, For_Last_Bars: Divergence_Ledge); Point MS_Max = Max_MS(From: index - 1, For_Last_Bars: Divergence_Ledge); Label Max = new Label(MACD_Max, MS_Max); if (High_Extremums.Count == 0) { if (Is_Max(L: Max, At: index)) Update_Data(Stage: "1 Step: FIRST", _Type: HIGH, New_Extremum: Max, At: index, Action: for_New); } else { Label Last = High_Extremums[High_Extremums.Count - 1]; if (Math.Max(Max.MACD.Index, Max.MS.Index) - Last.MACD.Index <= Divergence_Min_Length) { //if (Last.MACD.Value < MACD(index) && Last.MACD.Index == index - 1 && Max.MACD.Index - Last.MACD.Index <= Divergence_Ledge) //{ // Max.MACD.Value = MACD(index); // Max.MACD.Index = index; // Update_Data(Stage: "3 Step: update NOW", _Type: HIGH, New_Extremum: Max, At: index, Action: for_Update); //} if (Allow_To_Update_High(L: Last, New: Max, At: index)) Update_Data(Stage: "3 Step: update LAST", _Type: HIGH, New_Extremum: Max, At: index, Action: for_Update); } else if (Is_Next_High_Wave(A: Last, B: Max, At: index)) Update_Data(Stage: "4 Step: NEW", _Type: HIGH, New_Extremum: Max, At: index, Action: for_New); } /// TODO: Low Divergence Point MACD_Min = Min_MACD(From: index - 1, For_Last_Bars: Divergence_Ledge); Point MS_Min = Min_MS(From: index - 1, For_Last_Bars: Divergence_Ledge); Label Min = new Label(MACD_Min, MS_Min); if (Low_Extremums.Count == 0) { if (Is_Min(L: Min, At: index)) Update_Data(Stage: "1 Step: FIRST", _Type: LOW, New_Extremum: Min, At: index, Action: for_New); } else { Label Last = Low_Extremums[Low_Extremums.Count - 1]; if (Math.Max(Min.MACD.Index, Min.MS.Index) - Last.MACD.Index <= Divergence_Min_Length) { //if (Last.MACD.Value < MACD(index) && Last.MACD.Index == index - 1 && Min.MACD.Index - Last.MACD.Index <= Divergence_Ledge) //{ // Min.MACD.Value = MACD(index); // Min.MACD.Index = index; // Update_Data(Stage: "3 Step: update NOW", _Type: LOW, New_Extremum: Min, At: index, Action: for_Update); //} if (Allow_To_Update_Low(L: Last, New: Min, At: index)) Update_Data(Stage: "3 Step: update LAST", _Type: LOW, New_Extremum: Min, At: index, Action: for_Update); } else if (Is_Next_Low_Wave(A: Last, B: Min, At: index)) Update_Data(Stage: "4 Step: NEW", _Type: LOW, New_Extremum: Min, At: index, Action: for_New); } /// Update Trend List if (Trend.Count == 0) while (Trend.Count < index) Trend.Add(TrendType.None); if (Data.Count > 0) { Divergence D = Data[Data.Count - 1]; bool T_High = D.T == DivergenceType.High; bool T_Low = D.T == DivergenceType.Low; TrendType T = T_High ? TrendType.Down : (T_Low ? TrendType.Up : TrendType.None); if (Trend.Count < index) Trend.Add(T); else if (Trend.Count - 1 == index) Trend[index] = T; } else { TrendType T = TrendType.None; if (Trend.Count < index) Trend.Add(T); else if (Trend.Count - 1 == index) Trend[index] = T; } } /// Methods /// Info private void Info(string Stage, Label Last, Label Extremum, int At, DivergenceType _Type) { //if (IsBacktesting) // return; Print("{0} - {1} - {2} - {3} - {4} - Last {5} - Extremum {6}", At, MarketSeries.OpenTime[At].Date.ToShortDateString(), Data.Count, _Type.ToString(), Stage, Last.Text, Extremum.Text); } /// Update list Data_Divergence private void Update_Data(string Stage, DivergenceType _Type, Label New_Extremum, int At, ExtremumActionType Action) { if (_Type == HIGH ? High_Extremums.Count > 0 : Low_Extremums.Count > 0) { Label Previous_Extremum = _Type == HIGH ? High_Extremums[High_Extremums.Count - 1] : Low_Extremums[Low_Extremums.Count - 1]; Info(Stage: Stage, Last: Previous_Extremum, Extremum: New_Extremum, At: At, _Type: _Type); if (Action == for_New) if (_Type == HIGH) High_Extremums.Add(New_Extremum); else if (_Type == LOW) Low_Extremums.Add(New_Extremum); Label Last_Extremum = _Type == HIGH ? High_Extremums[High_Extremums.Count - 1] : Low_Extremums[Low_Extremums.Count - 1]; int N_Extremums = _Type == HIGH ? High_Extremums.Count - 1 : Low_Extremums.Count - 1; for (int Index = Math.Max(N_Extremums - Last_Points, 0); Index < N_Extremums; Index++) { Label Current_Extremum = _Type == HIGH ? High_Extremums[Index] : Low_Extremums[Index]; Divergence Last = new Divergence(_Type: _Type, Label_A: Current_Extremum, Label_B: Last_Extremum); Divergence New = new Divergence(_Type: _Type, Label_A: Current_Extremum, Label_B: New_Extremum); if (No_Obstacles(D: New) && Is_Divergence(D: New)) { if (Data.Contains(Last)) { int D_Index = Data.IndexOf(Last); Data[D_Index] = New; Info(Stage: "7 Step: update DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type); Draw(D: New, Prefix: D_Index.ToString()); } else if (!Data.Exists(D => D.B.MACD.Index == New.B.MACD.Index)) { Data.Add(New); Info(Stage: "7 Step: new DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type); Draw(D: New, Prefix: (Data.Count - 1).ToString()); } } else if (Data.Contains(Last)) { Info(Stage: "7 Step: remove DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type); Remove(D: Last, Prefix: Data.IndexOf(Last).ToString()); Data.Remove(Last); } } } else { if (Action == for_New) if (_Type == HIGH) High_Extremums.Add(New_Extremum); else if (_Type == LOW) Low_Extremums.Add(New_Extremum); } if (Action == for_Update) if (_Type == HIGH) High_Extremums[High_Extremums.Count - 1] = New_Extremum; else if (_Type == LOW) Low_Extremums[Low_Extremums.Count - 1] = New_Extremum; } /// Draw and remove chart objects private void Draw(Divergence D, string Prefix) { //if (IsBacktesting) // return; string Name = Prefix + Chart_Object_Title + D.T.ToString() + D.A.MACD.Index.ToString(); int Index_1 = D.A.MACD.Index; int Index_2 = D.B.MACD.Index; double Value_1 = D.A.MACD.Value; double Value_2 = D.B.MACD.Value; Colors Color = D.Color; ChartObjects.DrawLine(Name, Index_1, Value_1, Index_2, Value_2, Color); ChartObjects.DrawText(Name + "A", "•", Index_1, Value_1, VerticalAlignment.Center, HorizontalAlignment.Center, Color); ChartObjects.DrawText(Name + "B", "•", Index_2, Value_2, VerticalAlignment.Center, HorizontalAlignment.Center, Color); Info(Stage: "Draw Divergence:", Last: D.A, Extremum: D.B, At: D.A.MACD.Index, _Type: D.T); } private void Remove(Divergence D, string Prefix) { //if (IsBacktesting) // return; string Name = Prefix + Chart_Object_Title + D.T.ToString() + D.A.MACD.Index.ToString(); ChartObjects.RemoveObject(Name); ChartObjects.RemoveObject(Name + "A"); ChartObjects.RemoveObject(Name + "B"); } /// Helpers private double MACD(int Index) { return Result[Index]; } private bool Is_Divergence(Divergence D) { bool T1 = D.A.MACD.Value >= D.B.MACD.Value && D.A.MS.Value < D.B.MS.Value; bool T2 = D.A.MACD.Value <= D.B.MACD.Value && D.A.MS.Value > D.B.MS.Value; bool T_P = D.T == HIGH ? D.A.MACD.Value > 0 : D.A.MACD.Value < 0; return (T1 || T2) && T_P; } /// Is Max private bool Is_Max(Label L, int At) { return (MACD_Is_Max(P: L.MACD, At: At) && MS_Is_Max(P: L.MS, At: At)); } private bool MACD_Is_Max(Point P, int At) { return P.Value > 0 && P.Value > MACD(At) && P.Value > MACD(P.Index - 1); } private bool MS_Is_Max(Point P, int At) { return P.Value > MS_High(At) && P.Value > MS_High(P.Index - 1); } /// Is Min private bool Is_Min(Label L, int At) { return (MACD_Is_Min(P: L.MACD, At: At) && MS_Is_Min(P: L.MS, At: At)); } private bool MACD_Is_Min(Point P, int At) { return P.Value < 0 && P.Value < MACD(At) && P.Value < MACD(P.Index - 1); } private bool MS_Is_Min(Point P, int At) { return P.Value < MS_High(At) && P.Value < MS_High(P.Index - 1); } /// Allow to update private bool Allow_To_Update_High(Label L, Label New, int At) { if (New.MACD.Index == At) return false; if ((L.MACD.Value < New.MACD.Value && MACD_Is_Max(P: New.MACD, At: At)) || (L.MS.Value < New.MS.Value && MS_Is_Max(P: New.MS, At: At))) return true; return false; } private bool Allow_To_Update_Low(Label L, Label New, int At) { if (New.MACD.Index == At) return false; if ((L.MACD.Value > New.MACD.Value && MACD_Is_Min(P: New.MACD, At: At)) || (L.MS.Value > New.MS.Value && MS_Is_Min(P: New.MS, At: At))) return true; return false; } /// Next Wave private bool Is_Next_High_Wave(Label A, Label B, int At) { bool Was_Lower = MACD_Was_Lower(From: A.MACD.Index, To: B.MACD.Index); bool B_MACD_Max = MACD_Is_Max(P: B.MACD, At: At); bool B_MS_Max = MS_Is_Max(P: B.MS, At: At); bool T1 = A.MACD.Value > 0 && B.MACD.Value > 0 && Was_Lower && B_MACD_Max && B_MS_Max; bool T2 = A.MACD.Value < 0 && B.MACD.Value > 0 && Was_Lower && B_MACD_Max && B_MS_Max; bool T3 = A.MACD.Value > 0 && B.MACD.Value < 0 && A.MS.Value < B.MS.Value && B_MS_Max && MACD(Index: B.MS.Index) < 0; return (T1 || T2 || T3); } private bool Is_Next_Low_Wave(Label A, Label B, int At) { bool Was_Higher = MACD_Was_Higher(From: A.MACD.Index, To: B.MACD.Index); bool B_MACD_Min = MACD_Is_Min(P: B.MACD, At: At); bool B_MS_Min = MS_Is_Min(P: B.MS, At: At); bool T1 = A.MACD.Value < 0 && B.MACD.Value < 0 && Was_Higher && B_MACD_Min && B_MS_Min; bool T2 = A.MACD.Value > 0 && B.MACD.Value < 0 && Was_Higher && B_MACD_Min && B_MS_Min; bool T3 = A.MACD.Value < 0 && B.MACD.Value > 0 && A.MS.Value > B.MS.Value && B_MS_Min && MACD(Index: B.MS.Index) > 0; return (T1 || T2 || T3); } /// Нет препятсвий private bool No_Obstacles(Divergence D) { bool T_MACD = D.T == HIGH ? MACD_Was_Not_Higher(D: D) : MACD_Was_Not_Lower(D: D); bool T_MS = D.T == HIGH ? MS_Was_Not_Higher(D: D) : MS_Was_Not_Lower(D: D); //Info(Stage: string.Format("No O: MACD = {0} MS = {1}", T_MACD, T_MS), D: D, At: D.B.MACD.Index); return (T_MACD && T_MS); } /// MS Not higher or lower than private bool MACD_Was_Not_Higher(Divergence D) { return MACD_Was_Not_Higher(From: D.A.MACD.Index, To: D.B.MACD.Index, Value: Math.Max(D.A.MACD.Value, D.B.MACD.Value)); } private bool MACD_Was_Not_Lower(Divergence D) { return MACD_Was_Not_Lower(From: D.A.MACD.Index, To: D.B.MACD.Index, Value: Math.Min(D.A.MACD.Value, D.B.MACD.Value)); } private bool MACD_Was_Not_Higher(int From, int To, double Value) { if (From + 1 > To) return false; for (int Index = From + 1; Index < To; Index++) if (MACD(Index) > Value) return false; return true; } private bool MACD_Was_Not_Lower(int From, int To, double Value) { if (From + 1 > To) return false; for (int Index = From + 1; Index < To; Index++) if (MACD(Index) < Value) return false; return true; } /// MACD: was lower or higher 2 points private bool MACD_Was_Lower_Zero(int From, int To) { if (From > To) return false; for (int Index = From + 1; Index < To; Index++) if (MACD(Index) < 0) return true; return false; } private bool MACD_Was_Lower(int From, int To) { if (From + 1 > To) return false; double From_Value = MACD(From); double To_Value = MACD(To); for (int Index = From + 1; Index < To; Index++) if (MACD(Index) < From_Value && MACD(Index) < To_Value) return true; return false; } /// MACD: was higher or lower 0 private bool MACD_Was_Higher_Zero(int From, int To) { if (From > To) return false; for (int Index = From + 1; Index < To; Index++) if (MACD(Index) > 0) return true; return false; } private bool MACD_Was_Higher(int From, int To) { if (From + 1 > To) return false; double From_Value = MACD(From); double To_Value = MACD(To); for (int Index = From + 1; Index < To; Index++) if (MACD(Index) > From_Value && MACD(Index) > To_Value) return true; return false; } // MS: high & low private double MS_High(int Index) { return Divergence_Extremums ? MarketSeries.High[Index] : MarketSeries.Close[Index]; } private double MS_Low(int Index) { return Divergence_Extremums ? MarketSeries.Low[Index] : MarketSeries.Close[Index]; } /// MS Not higher or lower than private bool MS_Was_Not_Higher(Divergence D) { return MS_Was_Not_Higher(From: D.A.MS.Index, To: D.B.MS.Index, Value: Math.Max(D.A.MS.Value, D.B.MS.Value)); } private bool MS_Was_Not_Lower(Divergence D) { return MS_Was_Not_Lower(From: D.A.MS.Index, To: D.B.MS.Index, Value: Math.Min(D.A.MS.Value, D.B.MS.Value)); } private bool MS_Was_Not_Higher(int From, int To, double Value) { if (From + 1 > To) return false; for (int Index = From + 1; Index < To; Index++) if (MS_High(Index) > Value) return false; return true; } private bool MS_Was_Not_Lower(int From, int To, double Value) { if (From + 1 > To) return false; for (int Index = From + 1; Index < To; Index++) if (MS_Low(Index) < Value) return false; return true; } /// MS: max & min points private Point Max_MS(int From, int For_Last_Bars) { int Index = From; double Value = MS_High(Index); for (int Bar = 1; Bar <= For_Last_Bars; Bar++) { int New_Index = From - Bar; double New_Value = MS_High(New_Index); if (New_Value > Value) { Value = New_Value; Index = New_Index; } } return new Point(Index, Value); } private Point Min_MS(int From, int For_Last_Bars) { int Index = From; double Value = MS_Low(Index); for (int Bar = 1; Bar <= For_Last_Bars; Bar++) { int New_Index = From - Bar; double New_Value = MS_Low(New_Index); if (New_Value < Value) { Value = New_Value; Index = New_Index; } } return new Point(Index, Value); } /// MACD: max & min points private Point Max_MACD(int From, int For_Last_Bars) { int Index = From; double Value = MACD(Index); for (int Bar = 1; Bar <= For_Last_Bars; Bar++) { int New_Index = From - Bar; double New_Value = MACD(New_Index); if (New_Value < 0) return new Point(Index, Value); if (New_Value > Value) { Value = New_Value; Index = New_Index; } } return new Point(Index, Value); } private Point Min_MACD(int From, int For_Last_Bars) { int Index = From; double Value = MACD(Index); for (int Bar = 1; Bar <= For_Last_Bars; Bar++) { int New_Index = From - Bar; double New_Value = MACD(New_Index); if (New_Value > 0) return new Point(Index, Value); if (New_Value < Value) { Value = New_Value; Index = New_Index; } } return new Point(Index, Value); } } }
@daniel.agg
daniel.agg
07 Mar 2019, 21:51
Sorry, seems like the link to the source code is broken. Reuploaded:
https://drive.google.com/file/d/1CuMe7hKGLAK3XJW0HDQ9RucmDDiEps0S/view?usp=sharing
@daniel.agg
daniel.agg
26 Mar 2019, 18:09
Hi, the problem is solved (using a different indicator). Can you please delete this post?
Thanks in advance,
Dan
@daniel.agg