Replies

westend.trading
20 Mar 2021, 19:14

RE:

PanagiotisCharalampous said:

Hi westend.trading,

Our economic calendar is provided by a third party source and we do not have the right to redistribute the information. You can contact these providers yourself and ask about direct access to the calendar.

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagiotis,

it sounds paradox since this information is somehow distributed by the cTrader app anyway. But if that is the way it is...
It is giving MT5 a head start, though.

Best regards,
Ben;


@westend.trading

westend.trading
15 Mar 2021, 21:25

RE: Here is what I found on the matter...

heliodorstar said:

So basically in cAlgo they don't have a message or alert popup so you have to used the generic System.Windows.Forms which should be referenced from "Manage References".

 

By default the AccessRights of the robot are set to None and when you try to access System.Windows.Forms you get a pretty nasty error. That thing alone cost me the whole evening looking for and testing all kinds of weird stuff.

Two things are to be done here: 1. First in Control Panel > Administrative Tools > Microsoft Net > Runtime Security Policy > Adjust Zone Security you need to put almost everything {except Untrusted Sites} to "Full Trust". And 2) {Yepp, you guessed right!} you need to change the robot AccessRights to "FullAccess". I assure you it is very easy to do when you know it ;)))

Next thing you write in your algo:

using System.Windows.Forms; // Of course ;)

...

var message = MessageBox.Show("New bar!"); // end of code

 

...and Voila! You get a really ugly Message {or Alert} Box!

I gonna find a way to make the thing much more pretty for I can't stand the present "beauty" of it for 15 hours a day!

Really helpful. Although it seems not to be necessary anymore to adjust Zone Security settings. Works just by adding forms reference and settings AccessRights to full.


@westend.trading

westend.trading
20 Jul 2019, 13:23

Visual Studio 2017 wraps private variables (using operation "Encapsulate Field") by default in properties like this:

private string prov;
public string Provider { get => prov; }

This causes compilation error:

Error CS1043: { or ; expected

Which is due to the lower compiler version.

Not dramatic but still looking forward to the update.


@westend.trading

westend.trading
19 Jul 2019, 12:06

Hi Panagiotis,

Now that a year has passed: is there any news here?

Apparently the suggestions have disappeared from the voting board.

Can we assume that this api is not going to happen?

Best regards,

Ben


@westend.trading

westend.trading
19 Jul 2019, 12:05

Just an hint: probably it is a good idea to give the thread a more describing name instead of your username. More users may read it!?


@westend.trading

westend.trading
15 Jan 2019, 21:43

Hi Panagiotis,

this is the place I did not look. Wasn't really expecting an exception.

But, yes, I need(ed) the text in backtesting. There is no other option to output this kind of data "live". I admit it is not the smoothest way.

Is there a property which allows to know whether a robot is called by the optimizer?
Like: IsBacktest, IsOptimizer or so?

This would be my last question in this thread.

Thanks a lot!

Best regards,

Benjamin


@westend.trading

westend.trading
14 Jan 2019, 21:55

Hi Panagiotis,

please find below a code stub with the described behaviour.

To reproduce problem:

  1. Run Backtest with default values, Tickdata from server (accurate)
  2. Run Optimization with above parameter, and optimize e.g. only Stoploss 5 to 9 with stepsize 1
  3. Backtest produces output with any parameter for stoploss from 5 to 9
  4. Optimization passes have zero trades
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.None)]
    public class UITest : Robot
    {
        [Parameter(DefaultValue = 60)]
        public double Samples { get; set; }

        [Parameter(DefaultValue = 15)]
        public int HistogramBins { get; set; }

        [Parameter(DefaultValue = 20)]
        public int PeakMinHeight { get; set; }

        [Parameter("Lifetime", DefaultValue = 3)]
        public double Lifetime { get; set; }
        [Parameter("Stoploss", DefaultValue = 5)]
        public double Stoploss { get; set; }
        [Parameter("Hedge Size", DefaultValue = 7)]
        public double Hedgesize { get; set; }
        [Parameter("Trigger When Gaining", DefaultValue = 5)]
        public double TriggerWhenGaining { get; set; }
        [Parameter("Trailing Stop Loss Distance", DefaultValue = 2)]
        public double TrailingStopLossDistance { get; set; }

        long ticks_prev = 0;
        long ticks_act = 0;
        int ticks_neg = 0;
        int ticks_pos = 0;
        double bid = 0;
        double bid_last = 0;
        bool first = true;

        //Stopwatch s;
        double tick_per_min = 0;
        double last_val = 0;
        double delta_t_max = 0;
        double delta_t_min = 0;
        double delta_t_median = 0;
        List<double> delta_t = new List<double>();
        int tick_temp = -1;
        bool update = false;
        int h = 0;
        int negative_ticks = 0;
        int positive_ticks = 0;

        protected override void OnStart()
        {
            Positions.Opened += PositionsOnOpened;
        }


        protected override void OnBar()
        {
            tick_per_min = (double)tick_temp;
            negative_ticks = ticks_neg;
            positive_ticks = ticks_pos;
            ticks_pos = 0;
            ticks_neg = 0;
            tick_temp = 0;
        }

        protected override void OnTick()
        {
            int peaks = 0;

            checkOrder();
            bid = Symbol.Bid;
            ticks_act = Server.Time.Ticks;
            if (first)
            {
                ticks_prev = ticks_act;
                bid_last = bid;
                first = false;
                return;
            }
            double change = (bid - bid_last);
            //double sign = 1;
            if (change > 0)
            {
                ticks_pos++;
            }
            else
            {
                ticks_neg++;
                // sign = -1;
            }

            bid_last = bid;
            tick_temp++;
            double delta_t_tick = ((new TimeSpan(ticks_act - ticks_prev)).Milliseconds);
            ticks_prev = ticks_act;
            delta_t.Add(delta_t_tick);
            delta_t_max = delta_t.Max();
            delta_t_min = delta_t.Min();
            if (delta_t.Count > Samples)
            {
                delta_t.RemoveAt(0);
                double[] ta = delta_t.ToArray();

                string hist = "";

                double binsize = ta.Max() / ((double)HistogramBins);
                int[] histogram = new int[HistogramBins + 1];
                for (int i = 0; i < ta.Length; i++)
                {
                    int index = (int)Math.Floor(ta[i] / binsize);
                    if (index >= histogram.Length)
                    {
                        Print("{0} {1} {2}", index, ta[i], binsize);
                    }
                    else
                    {
                        histogram[index]++;
                    }
                }

                for (int i = 0; i < histogram.Length; i++)
                {
                    string xt = "";
                    for (int j = 0; j < histogram[i]; j++)
                    {
                        if (histogram[i] >= PeakMinHeight)
                        {
                            peaks++;
                        }
                        xt += "X";
                    }
                    hist += xt + "\r\n";
                }
                Chart.DrawStaticText("hist", hist, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Green);
            }

            last_val = tick_per_min;
            Chart.DrawStaticText("tpm", String.Format("Tick/min: {0:0.0}\r\nHist Items {1}", tick_per_min, HistogramBins), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Red);
            if (peaks > 0)
            {
                int d = positive_ticks - negative_ticks;
                Color c = Color.AliceBlue;
                if (PendingOrders.Count == 0 && Positions.Count == 0)
                {
                    ExecuteOrder();
                }
            }
        }

        private bool IsBusyTime()
        {
            if (Server.Time.TimeOfDay > new TimeSpan(5, 45, 0) && Server.Time.TimeOfDay < new TimeSpan(19, 45, 0))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void PositionsOnOpened(PositionOpenedEventArgs args)
        {
            if (PendingOrders.Count == 1)
            {
                PendingOrders[0].Cancel();
            }
            _highestGain = Positions[0].Pips;
            _isTrailing = false;
            Print("Position Opened. Gain: {0}", _highestGain);
        }

        double profit = 0;
        double last_profit = 0;
        private void ExecuteOrder()
        {
            profit = 0;
            last_profit = 0;
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(0.1);
            var result = PlaceStopOrder(TradeType.Buy, Symbol, volumeInUnits, Symbol.Ask + Hedgesize * Symbol.PipSize, "UP", Stoploss, null, Server.Time.AddMinutes(Lifetime), "", false);
            result = PlaceStopOrder(TradeType.Sell, Symbol, volumeInUnits, Symbol.Bid - Hedgesize * Symbol.PipSize, "DOWN", Stoploss, null, Server.Time.AddMinutes(Lifetime), "", false);
            if (result.Error == ErrorCode.NoMoney)
                Stop();
        }

        private double _highestGain;
        private bool _isTrailing;

        void checkOrder()
        {
            if (Positions.Count == 1)
            {
                //If the trigger is reached, the robot starts trailing
                if (!_isTrailing && Positions[0].Pips >= TriggerWhenGaining)
                {
                    _isTrailing = true;
                }
                //If the cBot is trailing and the profit in pips is at the highest level, we need to readjust the stop loss
                if (_isTrailing && _highestGain < Positions[0].Pips)
                {
                    //Based on the position's direction, we calculate the new stop loss price and we modify the position
                    if (Positions[0].TradeType == TradeType.Buy)
                    {
                        var newSLprice = Math.Round(Symbol.Bid - TrailingStopLossDistance * Symbol.PipSize, Symbol.Digits);
                        //var newSLprice = Symbol.Ask - (Symbol.PipSize * TrailingStopLossDistance);
                        if (newSLprice > Positions[0].StopLoss)
                        {
                            ModifyPosition(Positions[0], newSLprice, null);
                        }
                    }
                    else
                    {
                        var newSLprice = Math.Round(Symbol.Ask + TrailingStopLossDistance * Symbol.PipSize, Symbol.Digits);
                        //var newSLprice = Symbol.Bid + (Symbol.PipSize * TrailingStopLossDistance);
                        if (newSLprice < Positions[0].StopLoss)
                        {
                            ModifyPosition(Positions[0], newSLprice, null);
                        }
                    }
                    //We reset the highest gain
                    _highestGain = Positions[0].Pips;
                }
            }

        }
    }
}

Best regards,

Benjamin

 


@westend.trading

westend.trading
10 Jan 2019, 22:11 ( Updated at: 21 Dec 2023, 09:21 )

Hi Panagiotis,

I was just preparing the code to post (it is huge and I was removing all parts not related to the issue). Funny thing is: the stripped down version works in optimization mode.
Only non-relevant parts have been removed.

Backtest looks like this:
Screenshot Backtest

Optimization mode (same parameter, modifying one value only) -no output:

Core feature is a incoming tick data histogram.

Weird.

Best regards,

Ben


@westend.trading

westend.trading
09 Jan 2019, 19:51

Hi Panagiotis,

thank you again. This is what I expected. Will find a workaround for this.

Nonetheless I can run a robot that e.g. calculates time between incoming ticks and processes this data somehow. This works for simple backtesting precisely as far as I can verify. But runnning the same robot in Optimization mode (using same parameter and a dummy value for optimization) fails. The robot does not open any position in optimization mode. In backtest it works fine.

Can you please comment on that?

Best regards,

Ben


@westend.trading

westend.trading
04 Jan 2019, 22:03

Hi Panagiotis,

thanks for the hint.

Server.Time

actually solves the issue. And the Timer class is working precisely as well.

Is it possible to acquire the specific timestamps of past price ticks as well when creating an indicator or does this only work for a robot (including backtesting)?

Thank you again.

Best regards,

Benjamin


@westend.trading

westend.trading
19 Dec 2018, 20:53

Hi Panagiotis,

thank you for the quick response!
Can I assume it to run precisely in millisecond range?
The signal processing I intent to implement requires a very reliable reference clock. In realtime mode, this is no problem but results in backtest seem to be unrealistic.

How can I get the server timestamp of incoming ticks in backtest and normal operation mode?
Is it possible at all?

Best regards,

Ben


@westend.trading