Topics
11 Nov 2023, 15:28
 462
 4
20 Jul 2022, 12:21
 866
 4
31 Mar 2022, 15:01
 1098
 2
04 Jan 2021, 08:52
 1022
 5
14 Apr 2020, 07:20
 951
 1
14 Apr 2020, 06:28
 865
 2
07 Apr 2020, 08:45
 842
 2
27 Feb 2020, 03:11
 934
 2
11 Feb 2020, 13:54
 987
 7
08 Feb 2020, 17:46
 1
 976
 1
06 Feb 2020, 11:58
 0
 1012
 1
06 Feb 2020, 11:51
 0
 999
 1
Replies

gennimatas
13 Nov 2023, 14:30

RE: Grids not showing

Panagiotis,

Another thing that i observe is that when placing two or more indicators on the same area

the indicators are rescaled individually regardless of the AutoRescale property.

This can be clearly seen scrolling back.

Regards


@gennimatas

gennimatas
12 Nov 2023, 09:54

RE: Grids not showing

PanagiotisCharalampous said: 

Hi Takis,

Can you please record a video demonstrating the steps that lead to this behavior?

Best regards,

Panagiotis

Hi Panagiotis,

Here is some minimum code extracted from my indicators to help reproduce the issue.

Adding the indicator in a NewPanel, Grid does not show.

Saving and reloading the workspace, it will show.

Move it on Chart, then back to NewPanel and it's hidden again.

 

I was expecting that with given code the Result output would work correctly even with IsOverlay = false

And indi placed on Chart but this does not happen. My expectation was based on the assumption that after the 

addition of Chart/NewPanel the IsOverlay would become obsolete. Anyway, this case is not very important.

 

Regards

Takis

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace TestGrid
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TestGrid : Indicator
    {
        [Parameter("periods", DefaultValue = 7)]
        public int periods { get; set; }

        [Parameter("hAlign", DefaultValue = HorizontalAlignment.Left)]
        public HorizontalAlignment hAlign { get; set; }

        [Parameter("vAlign", DefaultValue = VerticalAlignment.Bottom)]
        public VerticalAlignment vAlign { get; set; }

        [Parameter("setYRange", DefaultValue = 0, MinValue = 0)]
        public int setYRange { get; set; }

        [Output("Result", LineColor = "White")]
        public IndicatorDataSeries Result { get; set; }

        ChartArea Area;
        TextBlock tb;

        protected override void Initialize()
        {
            Area = IndicatorArea is null ? Chart : IndicatorArea;

            AddControls();

            if (Area is IndicatorArea)
                Area.DrawHorizontalLine("zero", 0, Color.Cyan);
        }

        public override void Calculate(int index)
        {
            Result[index] = Bars.ClosePrices.TakeLast(periods).Average();
            if (Area is IndicatorArea)
                Result[index] -= Bars.ClosePrices.TakeLast(periods * 2).Average();
            tb.Text = Result[index].ToString("F2");

            if (Area is IndicatorArea && setYRange > 0)
                Area.SetYRange(-setYRange, setYRange);
        }

        public void AddControls()
        {
            ScrollViewer sv = new ScrollViewer
            {
                HorizontalAlignment = hAlign,
                VerticalAlignment = vAlign,
                BackgroundColor = Color.Black
            };
            Area.AddControl(sv);

            StackPanel panel = new StackPanel();
            sv.Content = panel;

            panel.AddChild(new TextBlock() { Text = Area == IndicatorArea ? "Oscillator" : "Chart", TextAlignment = TextAlignment.Center, BackgroundColor = Color.Blue });

            Border border = new Border
            {
                BorderColor = Color.Yellow,
                BorderThickness = 1,
                Margin = new Thickness(2, 2, 2, 2)
            };
            panel.AddChild(border);

            Grid grid = new Grid
            {
                BackgroundColor = Color.Black,
                Margin = new Thickness(2, 2, 2, 2)
            };
            grid.AddColumns(2);
            grid.AddRows(1);
            border.Child = grid;

            string[] labels = { "V" };
            for (int r = 0; r < labels.Length; r++)
            {
                var bt = new Button
                {
                    Margin = new Thickness(0, 0, 5, 0),
                    Text = labels[r]
                };
                grid.AddChild(bt, r, 0);

                tb = new TextBlock
                {
                    Margin = new Thickness(0, 0, 5, 0),
                    VerticalAlignment = VerticalAlignment.Center
                };
                grid.AddChild(tb, r, 1);
            }
        }

    }
}

@gennimatas

gennimatas
26 Jan 2023, 20:53

RE:

Spotware said:

Dear traders,

Thanks for reporting this problem. 4.6.2 hotfix has been released. Please let us know if you still experience issues in 4.6.2.

Best regards,

cTrader Team

4.6.2 gave me a headache.

Everything was going wrong until I discovered that ver (1.*) or (1.0.5) dependency was stucked in my projects and for some reason we're not automatically updating.

Manually updating those nuget packages all is smooth like it was supposed to be.

Very minor errors still exist but the developers team will fix them.

Regards 


@gennimatas

gennimatas
24 Jan 2023, 18:08

Same here 


@gennimatas

gennimatas
21 Jul 2022, 12:09

RE:

PanagiotisCharalampous said:

Hi Takis, 

I could not reproduce any problem. Please let me know the following

  1. Explain to us what do you think the indicator is doing. The logic as is does not make any sense to me.
  2. Provide broker, symbol and timeframe, as well as screenshots demonstrating the problem.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook

 

Hi Pano,

Hahahahaa What logic. This is paralogic.

HasCrossedAbove(0, index) should be HasCrossedAbove(0, 0)

I'm getting old, sorry Pano!

Regards

 


@gennimatas

gennimatas
08 Apr 2022, 09:27

Source code not available

Hi,

I had the same problem.

It appears that older versions of visual studio leave attributes in the csproj file

that cause this behavior. I had to manually clean all csproj files.

Remove lines like

    <EnableDefaultItems>False</EnableDefaultItems>
    <GenerateAssemblyInfo>False</GenerateAssemblyInfo>

 

Regards


@gennimatas

gennimatas
01 Apr 2022, 11:54

RE:

de.dorpstafel.est said:

Debugging support

Both .NET 4.x and .NET 6 algos can NOT be debugged in Visual Studio 2022 and 2017

loaded new SDK  
System libraries menu gone in Manage reference menu.
Browsed libs not recognized!

Debugging just does not work (no symbols loaded, weird errors, libraries not found) in vs2017 and vs2022

for us it's a useless update! Please notify when things are fixed!
how to roll-back?

 

 

Select all algo processes.

 


@gennimatas

gennimatas
10 Mar 2021, 17:43

RE:

PanagiotisCharalampous said:

Hi Takis,

This is caused due to a lazy loading design of the IndicatorDataSeries. Calculate function is only called when Last() method and LastValue property are called for an output IndicatorDataSeries. This was always the case.

Best Regards,

Panagiotis 

Join us on Telegram

Thanks Panagiotis


@gennimatas

gennimatas
04 Jan 2021, 16:41

RE: RE:

Shares4us said:

You can use workaround like:


int PrevIndex=-1;
public override void Calculate(int index)
{
    if(PrevIndex!=index)
    {
        // do your barstuff here;
        PrevIndex=index;
    }
}

 

Thanx

I fixed in place and it seems it works.

Don't know why but it does. LOL

if (DateTime.UtcNow.Subtract(obj.Bars.LastBar.OpenTime).TotalSeconds < 0)

DoSomething()

 


@gennimatas

gennimatas
04 Jan 2021, 16:37

RE:

PanagiotisCharalampous said:

Hi Takis,

It is a known issue and will be fixed in an upcoming release.

Best Regards,

Panagiotis 

Join us on Telegram

Thanks Panagiotis


@gennimatas

gennimatas
14 Apr 2020, 10:34

RE:

PanagiotisCharalampous said:

Hi Takis,

This behavior is by design. But even if it was a bug, you are still in the wrong section :).

Best Regards,

Panagiotis 

Join us on Telegram

Oh! Am i? lol


@gennimatas

gennimatas
14 Apr 2020, 10:28

RE:

PanagiotisCharalampous said:

Hi Takis,

Please use the Suggestions section for suggestions.

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagiotis,

This is not a suggestion!

This is a call to fix Functions class that misbehave when LastIndex != true

Thnx


@gennimatas

gennimatas
12 Feb 2020, 16:46

RE:

PanagiotisCharalampous said:

Hi Takis,

Your code works fine for me. How do you test it?

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagioti,

I wrote a separate indi to test it, didn't work and deleted it.

The code is part of another indi. Will test it again and let you know.

Thanks and regards


@gennimatas

gennimatas
12 Feb 2020, 16:10

RE: RE: RE:

thoy1 said:

Takis Genn said:

I saw this some days ago and forced it out with the line PlusMinusColors(true) 

Server.IsConnected and events OnServerConnected, OnServerDisconnected do not work.

The way i use them:

        Color clrPlus = Color.Gray;
        Color clrMinus = Color.Gray;

        protected override void Initialize()
        {
            Server.Connected += OnServerConnected;
            Server.Disconnected += OnServerDisconnected;
            PlusMinusColors(Server.IsConnected);
            //PlusMinusColors(true);

 

        void OnServerConnected()
        {
            PlusMinusColors(true);
        }

        void OnServerDisconnected()
        {
            PlusMinusColors(false);
        }

        void PlusMinusColors(bool plus)
        {
            if (plus)
            {
                clrPlus = Color.Lime;
                clrMinus = Color.Tomato;
            }
            else
            {
                clrPlus = Color.Gray;
                clrMinus = Color.Gray;
            }
        }

 

Hi Takis,

You legend! I had tried so many OnTimer options and none of them seemed to register the re-connections. Your version works beautifully!

For anybody else reading this thread I have completed the code to have the Thread.Sleep included. The reason for this script is upon reconnecting, the server at times sends a false Bid/Ask price and my bot likes to trade on it - creating a label which is well out of the array my bot runs. This delay allows ctrader to fully catch-up and have accurate Bid/Ask prices.

 

Now I just need to solve my BollingerBand issue.

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ConnectionTest : Robot
    {

        Color clrPlus = Color.Gray;
        Color clrMinus = Color.Gray;

        protected override void OnStart()
        {
            // Put your initialization logic here
            Server.Connected += OnServerConnected;
            Server.Disconnected += OnServerDisconnected;
            PlusMinusColors(Server.IsConnected);
        }

        void OnServerConnected()
        {
            PlusMinusColors(true);
        }


        void OnServerDisconnected()
        {
            PlusMinusColors(false);
        }

        void PlusMinusColors(bool plus)
        {
            if (plus)
            {
                clrPlus = Color.Lime;
                clrMinus = Color.Tomato;
                Print("Connected, pausing trades for 15 seconds.");
                System.Threading.Thread.Sleep(15000);
                Print("Trading active again.");
            }
            else
            {
                clrPlus = Color.Gray;
                clrMinus = Color.Gray;
                Print("Disconnected");
            }
        }

        protected override void OnTick()
        {
            Print("Tick");
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

I didn't post the whole thing as it is more than 700 lines of code

Glad it helped you

Still the Server connection state and the events do not work for me

Takis


@gennimatas

gennimatas
11 Feb 2020, 14:57

RE:

PanagiotisCharalampous said:

Hi Takis,

I am still missing something

Double click on the file name and change it.

Which filename? I renamed a cBot in Automate but the instance is not removed.

Best Regards,

Panagiotis 

Here is a video Panagioti to see what's happening here :)

 


@gennimatas

gennimatas
11 Feb 2020, 14:14

RE:

PanagiotisCharalampous said:

Hi Takis,

Renaming a running robot correctly removes it's instance

I could not reproduce this. Can you provide exact steps? Where does it happen? In Trade or Automate?

Best Regards,

Panagiotis 

Join us on Telegram


 

Hey Panagioti

I repeated it just to make sure.

beta curver.

In automate, run a robot.

Double click on the file name and change it.

The instance is removed.

In code, the class name is changing so you have to save.

Now the compile button is red and grayed.

You can add an instance, start it, stop it, remove it,

but the compile button remains red and grayed.

You will have to restart the app.

Regards


@gennimatas

gennimatas
11 Feb 2020, 14:14

RE:

PanagiotisCharalampous said:

Hi Takis,

Renaming a running robot correctly removes it's instance

I could not reproduce this. Can you provide exact steps? Where does it happen? In Trade or Automate?

Best Regards,

Panagiotis 

Join us on Telegram


 

Hey Panagioti

I repeated it just to make sure.

beta curver.

In automate, run a robot.

Double click on the file name and change it.

The instance is removed.

In code, the class name is changing so you have to save.

Now the compile button is red and grayed.

You can add an instance, start it, stop it, remove it,

but the compile button remains red and grayed.

You will have to restart the app.

Regards


@gennimatas

gennimatas
11 Feb 2020, 13:44

RE:

PanagiotisCharalampous said:

Hi thoy1,

1) You have placed your checks in OnTick. If the server is disconnected, you will not receive any ticks hence no checks will be made. Use a timer instead.

2) I could not reproduce any NaN values with your BollingerTest. Can you provide exact steps to reproduce this problem and post some screenshots as well?

Best Regards,

Panagiotis 

Join us on Telegram

 

I saw this some days ago and forced it out with the line PlusMinusColors(true) 

Server.IsConnected and events OnServerConnected, OnServerDisconnected do not work.

The way i use them:

        Color clrPlus = Color.Gray;
        Color clrMinus = Color.Gray;

        protected override void Initialize()
        {
            Server.Connected += OnServerConnected;
            Server.Disconnected += OnServerDisconnected;
            PlusMinusColors(Server.IsConnected);
            //PlusMinusColors(true);

 

        void OnServerConnected()
        {
            PlusMinusColors(true);
        }

        void OnServerDisconnected()
        {
            PlusMinusColors(false);
        }

        void PlusMinusColors(bool plus)
        {
            if (plus)
            {
                clrPlus = Color.Lime;
                clrMinus = Color.Tomato;
            }
            else
            {
                clrPlus = Color.Gray;
                clrMinus = Color.Gray;
            }
        }

 


@gennimatas

gennimatas
04 Feb 2020, 11:00

Hi Panagiotis

weird, isn't it?

I have an i5 set to 15% max cpu load. Want to try it? lol

I will increase max cpu load, test it again and let you know.

I might also record it, i have the tools.

Takis


@gennimatas

gennimatas
03 Feb 2020, 16:41

RE:

PanagiotisCharalampous said:

Hi Takis Genn,

Unfortunately I cannot know what the issue could be if I do not have any source code that reproduces such a behavior.

Best Regards,

Panagiotis 

Join us on Telegram

Here is the code Panagiotis,

Regards

 

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

// The issue:
//  The condition: Chart.LastVisibleBarIndex != (Bars.ClosePrices.Count - 1)
//  should happen only when the chart's last bar is not visible.
//  In that case, at the Top Right below HHLL range, appear FirstVisibleBarIndex
//  and ClosePrices.Count
//  But there are cases where those two appear with the last bar visible, which is wrong.
//  The issue is intermidient.
//
// To reproduce the issue:
//  1.Run
//  2.Change to one minute timeframe
//  3.Load more bars (Home button)
//  4.Return to the right (End button)
//  5.If the problem doesn't show, change to m5 then back to m1 or load more bars.
//
// When reproduced, the "TicksLine" TrendLine will separate from the chart's Ask and Bid lines
// on Y axis while moving on the X axis.
//
// When function ShowRiskPct is placed inside the OnTimer event and
// commented out from Calc event, i could not reproduce the issue.

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class InfoTEST : Indicator
    {
        [Parameter("Offset", DefaultValue = 0, MinValue = -23, MaxValue = 23)]
        public int Offset { get; set; }

        [Parameter("Wellington", DefaultValue = 21, MinValue = -1, MaxValue = 23)]
        public int Wellington { get; set; }

        [Parameter("Sydney", DefaultValue = 22, MinValue = -1, MaxValue = 23)]
        public int Sydney { get; set; }

        [Parameter("Tokyo", DefaultValue = 0, MinValue = -1, MaxValue = 23)]
        public int Tokyo { get; set; }

        [Parameter("Singapore", DefaultValue = 1, MinValue = -1, MaxValue = 23)]
        public int Singapore { get; set; }

        [Parameter("Frankfurt", DefaultValue = 7, MinValue = -1, MaxValue = 23)]
        public int Frankfurt { get; set; }

        [Parameter("London", DefaultValue = 8, MinValue = -1, MaxValue = 23)]
        public int London { get; set; }

        [Parameter("NewYork", DefaultValue = 13, MinValue = -1, MaxValue = 23)]
        public int NewYork { get; set; }

        [Parameter("DrawDays", DefaultValue = 1, MinValue = 0, MaxValue = 31)]
        public int DrawDays { get; set; }

        [Parameter("WatchListName", DefaultValue = "Forex Cluster")]
        public string WatchListName { get; set; }

        [Parameter("ClusterDays\n  comma separated", DefaultValue = "")]
        public string ClusterDays { get; set; }

        [Parameter("SpreadF", DefaultValue = 1, MinValue = 1, MaxValue = 2)]
        public double SpreadF { get; set; }

        [Parameter("TicksMax", DefaultValue = 300)]
        public int TicksMax { get; set; }

        [Parameter("RiskPct", DefaultValue = 1, MinValue = 0, MaxValue = 100)]
        public double RiskPct { get; set; }

        //private CommonLib cLib;
        int[] Ticks = new int[60];
        int[] TicksDOM = new int[60];
        List<double> Spread = new List<double>();
        Dictionary<string, int> Sessions = new Dictionary<string, int>();
        //public List<ClusterOsc> iCluster = new List<ClusterOsc>();
        int DrawState = 0;
        string[] DrawStates = "info,tpm,hid".Split(',');
        Dictionary<string, Button> ClusterButtons = new Dictionary<string, Button>();
        Panel ClusterPanel;

        private string IndicatorName = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;

        protected override void Initialize()
        {
            //cLib = Indicators.GetIndicator<CommonLib>();

            Sessions.Add("Wellington", Wellington);
            Sessions.Add("Sydney", Sydney);
            Sessions.Add("Tokyo", Tokyo);
            Sessions.Add("Singapore", Singapore);
            Sessions.Add("Frankfurt", Frankfurt);
            Sessions.Add("London", London);
            Sessions.Add("NewYork", NewYork);

            //if (ClusterDays != "")
            //    foreach (string pDays in ClusterDays.Split(','))
            //        iCluster.Add(Indicators.GetIndicator<ClusterOsc>(WatchListName, "*", Convert.ToInt32(pDays), 60));

            MarketDepth DOM = MarketData.GetMarketDepth(Bars.SymbolName);
            DOM.Updated += DOM_Updated;

            Ticks ticks = MarketData.GetTicks();
            foreach (Tick tick in ticks)
                Spread.Add(tick.Ask - tick.Bid);
            TimeSpan span = new TimeSpan(ticks.LastTick.Time.AddTicks(-ticks[0].Time.Ticks).Ticks);
            Print("SpreadTicks=" + ticks.Count + " Span=" + Convert.ToInt32(span.TotalHours));

            Panel panel = AddStackPanel(HorizontalAlignment.Left, VerticalAlignment.Top);
            AddButton(panel, 1, DrawStates[DrawState], Color.Cyan);

            //if (iCluster.Count > 0)
            //{
            //    int w = 72;
            //    int h = 17;
            //    double f = 11;
            //    ClusterPanel = AddWrapPanel(HorizontalAlignment.Left, VerticalAlignment.Bottom, Orientation.Horizontal);
            //    ClusterPanel.Width = w * iCluster.Count;
            //    for (int c = 0; c < iCluster.Count; c++)
            //    {
            //        Button button = AddButton(ClusterPanel, 2 + c, c.ToString(), Color.White, false, w, h, f);
            //        ClusterButtons.Add("Head." + c, button);
            //    }
            //    for (int r = 0; r < iCluster[0].CLUSTER.Count; r++)
            //        for (int c = 0; c < iCluster.Count; c++)
            //        {
            //            string key = r + "." + c;
            //            Button button = AddButton(ClusterPanel, 5 + (r * 3 + c), key, Color.Cyan, true, w, h, f);
            //            ClusterButtons.Add(key, button);
            //        }
            //}

            Timer.Start(1);
        }

        public override void Calculate(int index)
        {
            if (!IsLastBar)
            {
                DrawSessionBoxes(index);
                return;
            }
            Ticks[DateTime.Now.Second] += 1;

            if (IsLastBar)
                ShowRiskPct();
        }

        void DOM_Updated()
        {
            TicksDOM[DateTime.Now.Second] += 1;
        }

        protected override void OnTimer()
        {
            int sec = DateTime.Now.Second + 1;
            if (sec > 59)
                sec = 0;
            Ticks[sec] = 0;
            TicksDOM[sec] = 0;

            if (DrawState == 0 | DrawState == 1)
            {
                ShowText();
                ShowHiLo();
                DrawSessionBoxes(Bars.Count - 1);
                //if (IsLastBar)
                //    ShowRiskPct();
            }
            if (DrawState == 0)
            {
                ShowCluster();
            }
        }

        private void ShowText()
        {
            StringBuilder sb1 = new StringBuilder();
            int bars = Chart.LastVisibleBarIndex - Chart.FirstVisibleBarIndex;
            //int minutes = bars * cLib.TimeFrameToMinutes(Bars.TimeFrame);
            int minutes = bars * TimeFrameToMinutes(Bars.TimeFrame);
            TimeSpan chartSpan = new TimeSpan(0, minutes, 0);
            sb1.AppendLine(Chart.LastVisibleBarIndex - Chart.FirstVisibleBarIndex + "    " + chartSpan.ToString().Remove(chartSpan.ToString().LastIndexOf(":00")));
            sb1.AppendLine("v" + Application.Version);
            try
            {
                sb1.Append(Symbol.MarketHours.IsOpened() ? "Opened " : "Closed ");
                if (Symbol.MarketHours.IsOpened())
                    sb1.AppendLine(DateTime.UtcNow.AddTicks(Symbol.MarketHours.TimeTillClose().Ticks).ToLocalTime().ToShortTimeString());
                else
                    sb1.AppendLine(DateTime.UtcNow.AddTicks(Symbol.MarketHours.TimeTillOpen().Ticks).ToLocalTime().ToShortTimeString());
            } catch
            {
                sb1.AppendLine();
            }
            sb1.AppendLine("TpM:  " + Ticks.Sum() + " " + TicksDOM.Sum());
            sb1.AppendLine();
            int fb = Chart.FirstVisibleBarIndex;
            int lb = Chart.LastVisibleBarIndex;
            //int TicksR = (int)cLib.Map(TicksDOM.Sum(), 0, TicksMax, fb, lb);
            int TicksR = (int)Map(TicksDOM.Sum(), 0, TicksMax, fb, lb);
            double price = Bars.ClosePrices.LastValue;
            //double price = (Symbol.Ask + Symbol.Bid) / 2;
            Chart.DrawTrendLine("TicksLine", fb, price, TicksR, price, Color.White, 5, LineStyle.Solid);
            double SpreadAvg = Spread.ToArray().Average() / Symbol.PipSize;
            double SpreadNow = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
            Color SpreadColor = Color.Cyan;
            if (SpreadNow > SpreadAvg * SpreadF)
                SpreadColor = Color.Red;
            Spread.Add(Symbol.Ask - Symbol.Bid);
            sb1.AppendLine("Spread: (" + Math.Round(SpreadAvg, 2) + ") " + Math.Round(SpreadNow, 2));
            sb1.AppendLine();
            Chart.DrawStaticText("Ticks", sb1.ToString(), VerticalAlignment.Top, HorizontalAlignment.Left, SpreadColor);
        }

        private void ShowCluster()
        {
            //if (iCluster.Count > 0)
            //{
            //    for (int c = 0; c < iCluster.Count; c++)
            //    {
            //        ClusterButtons["Head." + c].Text = iCluster[c].DaysActual.ToString();
            //    }
            //    for (int r = 0; r < iCluster[0].StrengthList.Count; r++)
            //    {
            //        for (int c = 0; c < iCluster.Count; c++)
            //        {
            //            ClusterButtons[r + "." + c].Text = iCluster[c].StrengthList[r].ToUpper();
            //        }
            //    }
            //}
        }

        private void ShowHiLo()
        {
            StringBuilder sb2 = new StringBuilder();
            //double H = cLib.SeriesMaximum(Bars.HighPrices, Chart.FirstVisibleBarIndex, Chart.LastVisibleBarIndex);
            double H = SeriesMaximum(Bars.HighPrices, Chart.FirstVisibleBarIndex, Chart.LastVisibleBarIndex);
            //double L = cLib.SeriesMinimum(Bars.LowPrices, Chart.FirstVisibleBarIndex, Chart.LastVisibleBarIndex);
            double L = SeriesMinimum(Bars.LowPrices, Chart.FirstVisibleBarIndex, Chart.LastVisibleBarIndex);
            sb2.AppendLine("" + Math.Round((H - L) / Symbol.PipSize, 0));
            if (Chart.LastVisibleBarIndex != (Bars.ClosePrices.Count - 1))
            {
                sb2.AppendLine("" + Chart.FirstVisibleBarIndex);
                sb2.AppendLine("" + Bars.ClosePrices.Count);
            }
            Chart.DrawStaticText("HiLo", sb2.ToString(), VerticalAlignment.Top, HorizontalAlignment.Right, Color.Cyan);
        }

        private void ShowRiskPct()
        {
            if (RiskPct > 0)
            {
                string txt = RiskPct + "% ";
                //txt += "U=" + (cLib.RiskToUnits(RiskPct, Symbol) / 1000).ToString() + "k";
                txt += "U=" + (RiskToUnits(RiskPct, Symbol) / 1000).ToString() + "k";
                //txt += " L=" + cLib.RiskToLots(RiskPct, Symbol).ToString();
                txt += " L=" + RiskToLots(RiskPct, Symbol).ToString();
                Chart.DrawStaticText("Volume", txt, VerticalAlignment.Bottom, HorizontalAlignment.Left, Color.White);
            }
        }

        private void DrawSessionBoxes(int idx)
        {
            DateTime ot = Bars.OpenTimes[idx].AddHours(1);
            if (ot < DateTime.Now.AddDays(-DrawDays))
                return;
            if (ot.Second != 0)
                return;

            foreach (KeyValuePair<string, int> kvp in Sessions)
            {
                if (kvp.Value >= 0)
                    try
                    {
                        if (ot.Hour >= kvp.Value && ot.Hour < kvp.Value + 9)
                            DrawSessionBox(kvp, ot);
                    } catch
                    {
                    }
            }
        }

        private void DrawSessionBox(KeyValuePair<string, int> kvp, DateTime BarTime)
        {
            DateTime d1 = new DateTime(BarTime.Year, BarTime.Month, BarTime.Day, 0, 0, 0).AddHours(kvp.Value - Offset);
            DateTime d2 = d1.AddHours(9).AddMinutes(-1);
            int x1 = Bars.OpenTimes.GetIndexByTime(d1);
            int x2 = Bars.OpenTimes.GetIndexByTime(d2);
            double y1 = MaxH(x1, x2);
            double y2 = MinL(x1, x2);

            Color c;
            if (kvp.Key.StartsWith("W"))
                c = Color.Magenta;
            else if (kvp.Key.StartsWith("Sy"))
                c = Color.Blue;
            else if (kvp.Key.StartsWith("T"))
                c = Color.Orange;
            else if (kvp.Key.StartsWith("Si"))
                c = Color.Green;
            else if (kvp.Key.StartsWith("F"))
                c = Color.Yellow;
            else if (kvp.Key.StartsWith("L"))
                c = Color.Lime;
            else if (kvp.Key.StartsWith("N"))
                c = Color.Red;
            else
                c = Color.Gray;
            string Session = kvp.Key + "-" + kvp.Value + "-" + BarTime.DayOfYear;
            Chart.DrawRectangle(Session, d1, y1, d2, y2, c, 1, LineStyle.DotsVeryRare);
            Chart.DrawText(Session + "Txt", Session.Split('-')[0].Substring(0, 1), d1, y1, c);
        }

        private double MaxH(int x1, int x2)
        {
            double max = double.MinValue;
            for (int i = x1; i <= x2; i++)
                max = Math.Max(max, Bars.HighPrices[i]);
            return max;
        }

        private double MinL(int x1, int x2)
        {
            double min = double.MaxValue;
            for (int i = x1; i <= x2; i++)
                min = Math.Min(min, Bars.LowPrices[i]);
            return min;
        }

        public StackPanel AddStackPanel(HorizontalAlignment hor = HorizontalAlignment.Right, VerticalAlignment ver = VerticalAlignment.Bottom, Orientation orient = Orientation.Vertical)
        {
            StackPanel panel = new StackPanel();
            if (IndicatorArea == null)
                Chart.AddControl(panel);
            else
                IndicatorArea.AddControl(panel);
            panel.HorizontalAlignment = hor;
            panel.VerticalAlignment = ver;
            panel.Orientation = orient;
            return panel;
        }

        public WrapPanel AddWrapPanel(HorizontalAlignment hor = HorizontalAlignment.Right, VerticalAlignment ver = VerticalAlignment.Bottom, Orientation orient = Orientation.Vertical)
        {
            WrapPanel panel = new WrapPanel();
            if (IndicatorArea == null)
                Chart.AddControl(panel);
            else
                IndicatorArea.AddControl(panel);
            panel.HorizontalAlignment = hor;
            panel.VerticalAlignment = ver;
            panel.Orientation = orient;
            return panel;
        }

        public Button AddButton(Panel panel, int ID, string txt, Color clr, bool WithEvent = true, int width = 40, int height = 20, double fsize = 11)
        {
            Button btn = new Button();
            btn.Left = ID;
            if (WithEvent)
                btn.Click += OnButtonClick;
            panel.AddChild(btn);
            btn.ForegroundColor = clr;
            btn.BackgroundColor = Color.Black;
            btn.BorderColor = btn.ForegroundColor;
            btn.Width = width;
            btn.Height = height;
            btn.Text = txt;
            btn.HorizontalContentAlignment = HorizontalAlignment.Left;
            btn.VerticalContentAlignment = VerticalAlignment.Center;
            btn.FontSize = fsize;
            return btn;
        }

        string Pri = "";
        string Sec = "";

        private void OnButtonClick(ButtonClickEventArgs obj)
        {
            Print(obj.Button.Left, " ", obj.Button.Text);
            if (obj.Button.Left == 1)
            {
                DrawState += 1;
                if (DrawState == DrawStates.Length)
                    DrawState = 0;
                obj.Button.Text = DrawStates[DrawState];
                if (DrawState == 0)
                    if (ClusterPanel != null)
                        ClusterPanel.IsVisible = true;
                if (DrawState == 1 | DrawState == 2)
                    if (ClusterPanel != null)
                        ClusterPanel.IsVisible = false;
                if (DrawState == 2)
                    Chart.RemoveAllObjects();
            }
            if (obj.Button.Left >= 2)
            {
                if (Sec != "")
                {
                    Pri = "";
                    Sec = "";
                }
                if (Pri == "")
                {
                    Pri = obj.Button.Text.Split(" ".ToCharArray(), 2)[1];
                }
                else
                {
                    Sec = obj.Button.Text.Split(" ".ToCharArray(), 2)[1];
                }
                Print(Pri, " ", Sec);
                if (Pri != "" && Sec != "")
                    if (!Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame, Pri + Sec))
                        Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame, Sec + Pri);
            }
        }

//  imported from cLib VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV

        public int TimeFrameToMinutes(TimeFrame TF)
        {
            if (TF.ToString() == "Minute")
                return 1;
            else if (TF.ToString().StartsWith("Minute"))
                return int.Parse(TF.ToString().Replace("Minute", ""));
            else if (TF.ToString() == "Hour")
                return 60;
            else if (TF.ToString().StartsWith("Hour"))
                return 60 * int.Parse(TF.ToString().Replace("Hour", ""));
            else if (TF.ToString() == "Daily")
                return 60 * 24;
            else if (TF.ToString().StartsWith("Day"))
                return 60 * 24 * int.Parse(TF.ToString().Replace("Day", ""));
            else if (TF.ToString() == "Weekly")
                return 60 * 24 * 5;
            else if (TF.ToString() == "Monthly")
                return 60 * 24 * 5 * 4;
            else
                return 0;
        }

        public double Map(double v, string Scale)
        {
            double[] scale = StringToDoubleArray(Scale);
            return Map(v, scale[0], scale[1], scale[2], scale[3]);
        }

        public double Map(double v, double fromBot, double fromTop, double toBot, double toTop)
        {
            double ret = toBot + (v - fromBot) * (toTop - toBot) / (fromTop - fromBot);
            return ret;
        }

        public double[] StringToDoubleArray(string str)
        {
            return str.Split(',').Select(z => double.Parse(z)).ToArray();
        }

        public double SeriesMaximum(DataSeries s, int idx1, int idx2)
        {
            double max = double.MinValue;
            for (int i = idx1; i <= idx2; i++)
                max = Math.Max(max, s[i]);
            return max;
        }

        public double SeriesMinimum(DataSeries s, int idx1, int idx2)
        {
            double min = double.MaxValue;
            for (int i = idx1; i <= idx2; i++)
                min = Math.Min(min, s[i]);
            return min;
        }

        public double SeriesMaximum(IndicatorDataSeries s, int idx1, int idx2)
        {
            double max = double.MinValue;
            for (int i = idx1; i <= idx2; i++)
                max = Math.Max(max, s[i]);
            return max;
        }

        public double SeriesMinimum(IndicatorDataSeries s, int idx1, int idx2)
        {
            double min = double.MaxValue;
            for (int i = idx1; i <= idx2; i++)
                min = Math.Min(min, s[i]);
            return min;
        }

        public double RiskToLots(double RiskPct, Symbol s = null)
        {
            if (s == null)
                return Symbol.VolumeInUnitsToQuantity(RiskToUnits(RiskPct));
            else
                return s.VolumeInUnitsToQuantity(RiskToUnits(RiskPct, s));
        }

        public double RiskToUnits(double RiskPct, Symbol s = null)
        {
            if (s == null)
                return Symbol.NormalizeVolumeInUnits((Account.FreeMargin * RiskPct / 100 / Symbol.Ask * Account.PreciseLeverage), RoundingMode.Down);
            else
                return s.NormalizeVolumeInUnits((Account.FreeMargin * RiskPct / 100 / s.Ask * Account.PreciseLeverage), RoundingMode.Down);
        }

    }
}

 


@gennimatas