Manual Strategy Tester with Source Code

by astevani in category Other at 05/05/2019
Description

This bot is usefull to check your manual strategy.

You can choose some past days and trade on ctrader in backtesting.

To use this bot you must set visual mode flag in backtesting and run the back testing.

After start the back testing you will see a windows form where you can buy and sell by hand.

There is also a combobox where you can choose one of open positions and change the stop loss, the take profit and the volume.

Enjoy

Amerigo

 

 

Download
439 downloads
How to install
Warning! Executing the following cBot may result in loss of funds. Use it at your own risk.
Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.
Formula / Source Code
Language: C#
Trading Platform: cAlgo
using System;
using System.IO;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

//using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace cAlgo
{

    public class CmdForm : Form
    {
        public Interactive theRobot;
        TextBox txtSL;
        TextBox txtTP;
        TextBox txtVol;
        ComboBox cbPositions;

        public CmdForm()
        {
            Text = "Command Board";
            AddLabel("Positions", 13, 13);
            AddLabel("Lots", 13, 43);
            AddLabel("Stop Loss", 13, 73);
            AddLabel("Take Profit", 13, 103);
            AddButton("Buy", 13, 133, 50, (s, e) => { CmdBuy(); });
            AddButton("Sell", 63, 133, 50, (s, e) => { CmdSell(); });
            AddButton("Set", 150, 133, 50, (s, e) => { CmdSet(); });
            AddButton("Close", 200, 133, 50, (s, e) => { CmdClose(); });
            txtVol = AddTextBox(100, 43, 100);
            txtSL = AddTextBox(100, 73, 100);
            txtTP = AddTextBox(100, 103, 100);
            txtVol.Text = "1";
            cbPositions = AddComboBox(100, 13, 100, (s, e) => { UpdateForm(); });
            TopMost = true;
        }

        private void AddLabel(string text, int x, int y)
        {
            Label lbl = new Label();
            lbl.Location = new Point(x, y);
            lbl.Text = text;
            lbl.AutoSize = true;
            Controls.Add(lbl);

        }

        private ComboBox AddComboBox(int x, int y, int width, EventHandler eh)
        {
            ComboBox cb = new ComboBox();
            cb.Location = new Point(x, y);
            cb.Width = width;
            cb.SelectedIndexChanged += eh;
            Controls.Add(cb);
            return cb;
        }

        private TextBox AddTextBox(int x, int y, int width)
        {
            TextBox txt = new TextBox();
            txt.Location = new Point(x, y);
            txt.Width = width;
            txt.Height = 30;
            txt.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            Controls.Add(txt);
            return txt;
        }

        private void AddButton(string text, int x, int y, int width, EventHandler eh)
        {
            Button btn = new Button();
            btn.Location = new Point(x, y);
            btn.Text = text;
            btn.Click += eh;
            btn.Width = width;
            Controls.Add(btn);

        }

        protected void UpdateForm()
        {
            if (cbPositions.SelectedItem != null)
            {
                string text = cbPositions.GetItemText(cbPositions.SelectedItem);
                int posId = Int32.Parse(text);
                var t = new Thread(() =>
                {
                    Position p = theRobot.FindPos2(posId);
                    if (p != null)
                    {
                        double? sl = p.StopLoss;
                        double? tp = p.TakeProfit;
                        double vol = p.VolumeInUnits / 100000;
                        if (sl != null)
                            sl = Math.Round((double)(p.EntryPrice - sl) / theRobot.PipSize * (p.TradeType == TradeType.Buy ? 1 : 1), 1);
                        if (tp != null)
                            tp = Math.Round((double)(tp - p.EntryPrice) / theRobot.PipSize * (p.TradeType == TradeType.Buy ? 1 : 1), 1);

                        UpdateForm2(vol, sl, tp);
                    }
                });

                t.Start();
            }

        }

        delegate void SafeCallUpdateForm2(double vol, double? sl, double? tp);
        delegate void SafeCallUpdateComboBox(Positions pos);

        protected void UpdateForm2(double vol, double? sl, double? tp)
        {
            if (txtSL.InvokeRequired)
            {
                var d = new SafeCallUpdateForm2(UpdateForm2);
                Invoke(d, new object[] 
                {
                    vol,
                    sl,
                    tp
                });
            }
            else
            {
                txtSL.Text = "";
                txtTP.Text = "";
                if (sl != null)
                    txtSL.Text = sl.ToString();
                if (tp != null)
                    txtTP.Text = tp.ToString();
                txtVol.Text = vol.ToString();
            }
        }

        protected void CmdBuy()
        {
            double? sl = null, tp = null;
            double? vol = 0;
            sl = Parse(txtSL.Text);
            tp = Parse(txtTP.Text);
            vol = Parse(txtVol.Text);

            if (vol == null)
                return;
            double volume = (double)vol;

            var t = new Thread(() => theRobot.OpenPos(TradeType.Buy, volume, sl, tp));
            t.Start();

        }

        public void UpdateComboBox(Positions pos)
        {
            if (cbPositions.InvokeRequired)
            {
                var d = new SafeCallUpdateComboBox(UpdateComboBox);
                Invoke(d, new object[] 
                {
                    pos
                });
            }
            else
            {
                cbPositions.Items.Clear();
                foreach (var p in pos)
                    cbPositions.Items.Add(p.Id.ToString());
                if (cbPositions.Items.Count > 0)
                    cbPositions.SelectedIndex = cbPositions.Items.Count - 1;
            }

        }

        protected void CmdSell()
        {
            double? sl = null, tp = null;
            double? vol = 0;
            sl = Parse(txtSL.Text);
            tp = Parse(txtTP.Text);
            vol = Parse(txtVol.Text);

            if (vol == null)
                return;
            double volume = (double)vol;

            var t = new Thread(() => theRobot.OpenPos(TradeType.Sell, volume, sl, tp));
            t.Start();

        }

        protected void CmdClose()
        {
            if (cbPositions.SelectedItem != null)
            {
                string text = cbPositions.GetItemText(cbPositions.SelectedItem);
                int posId = Int32.Parse(text);
                var t = new Thread(() => theRobot.ClosePos(posId));
                t.Start();
            }
        }

        protected void CmdSet()
        {
            if (cbPositions.SelectedItem != null)
            {
                string text = cbPositions.GetItemText(cbPositions.SelectedItem);
                int posId = Int32.Parse(text);
                double? sl = null, tp = null;
                double? vol = 0;
                sl = Parse(txtSL.Text);
                tp = Parse(txtTP.Text);
                vol = Parse(txtSL.Text);

                if (vol == null)
                    return;

                double volume = (double)vol;
                var t = new Thread(() => theRobot.SetPosPips(posId, volume, sl, tp));
                t.Start();
            }
        }

        private double? Parse(string text)
        {
            double result;
            bool e = Double.TryParse(text, out result);
            return e ? (double?)result : (double?)null;
        }

    }

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class Interactive : Robot
    {
        [Parameter()]
        public DataSeries SourceSeries { get; set; }

        const string filename = "c:\\calgodb\\cmd.txt";
        const string label = "manual";
        /* 
        [Parameter ("Quantity (Lots)", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }
        */
        CmdForm form;
        protected override void OnStart()
        {
            Thread t = new Thread(() =>
            {
                Application.EnableVisualStyles();
                form = new CmdForm();
                form.theRobot = this;
                Application.Run(form);
            });
            t.Priority = ThreadPriority.BelowNormal;
            t.IsBackground = true;
            t.Start();
            Positions.Closed += onClosed;
            Positions.Opened += onOpened;
        }

        protected void onClosed(PositionClosedEventArgs e)
        {
            form.UpdateComboBox(Positions);
        }

        protected void onOpened(PositionOpenedEventArgs e)
        {
            form.UpdateComboBox(Positions);
        }

        protected override void OnStop()
        {
        }

        private Position FindPos(string pos)
        {
            foreach (var p in Positions.FindAll(label, Symbol))
                if (p.Comment == "#" + pos)
                    return p;
            return null;
        }

        public Position FindPos2(int id)
        {
            foreach (var p in Positions.FindAll(label, Symbol))
                if (p.Id == id)
                    return p;
            return null;
        }

        public double PipSize
        {
            get { return Symbol.PipSize; }
        }

        public int OpenPos(TradeType trade, double vol, double? sl, double? tp)
        {
            var ts = ExecuteMarketOrder(trade, Symbol, VolumeInUnits(vol), label, sl, tp);
            if (!ts.IsSuccessful)
                return ts.Position.Id;
            return 0;
        }

        public void ClosePos(int posId)
        {
            Position p = FindPos2(posId);
            if (p != null)
                p.Close();
        }

        public void SetPosPips(int posId, double vol, double? sl, double? tp)
        {
            Position p = FindPos2(posId);
            if (p != null)
            {
                if (p.VolumeInUnits != VolumeInUnits(vol))
                    p.ModifyVolume(VolumeInUnits(vol));
                p.ModifyTakeProfitPips(tp);
                p.ModifyStopLossPips(sl);
            }
        }

        public void SetPosPrices(int posId, double vol, double? sl, double? tp)
        {
            Position p = FindPos2(posId);
            if (p != null)
            {
                if (p.VolumeInUnits != VolumeInUnits(vol))
                    p.ModifyVolume(VolumeInUnits(vol));
                p.ModifyTakeProfitPrice(tp);
                p.ModifyStopLossPrice(sl);
            }
        }

        protected override void OnTick()
        {

            if (false)
                if (File.Exists(filename))
                {
                    string text = System.IO.File.ReadAllText(filename);
                    text = text.Replace("\n", "").Replace("\r", "");
                    Print("[{0}]", text);
                    File.Delete(filename);
                    Position pos = null;
                    double? sl = null;
                    double? tp = null;
                    TradeType trade = TradeType.Buy;
                    bool deal = false;
                    bool change = false;
                    string posNumber = "";
                    double vol = 1;
                    bool toClose = false;

                    foreach (var cmdfull in text.Split(';'))
                    {
                        var ops = cmdfull.Split(':');
                        var cmd = ops[0];
                        var arg = ops[1];
                        Print("[{0}] [{1}]", cmd, arg);
                        switch (cmd)
                        {
                            case "VOL":
                                vol = Double.Parse(arg);
                                break;

                            case "CMD":
                                switch (arg)
                                {
                                    case "SELL":
                                        trade = TradeType.Sell;
                                        deal = true;
                                        break;
                                    case "BUY":
                                        trade = TradeType.Buy;
                                        deal = true;
                                        break;
                                    case "CLOSE":
                                        toClose = true;
                                        break;
                                    case "SET":
                                        change = true;
                                        break;
                                }
                                break;
                            case "POS":
                                pos = FindPos(arg);
                                posNumber = arg;
                                break;

                            case "TP*":
                                tp = Double.Parse(arg);
                                if (change && pos != null)
                                    pos.ModifyTakeProfitPips(tp);
                                break;
                            case "SL*":
                                sl = Double.Parse(arg);
                                if (change && pos != null)
                                    pos.ModifyStopLossPips(sl);
                                break;
                            case "TP":
                                tp = Double.Parse(arg);
                                if (change && pos != null)
                                    pos.ModifyTakeProfitPrice(tp);
                                break;
                            case "SL":
                                sl = Double.Parse(arg);
                                if (change && pos != null)
                                    pos.ModifyStopLossPrice(sl);
                                break;
                        }
                    }

                    if (deal)
                        ExecuteMarketOrder(trade, Symbol, VolumeInUnits(vol), label, sl, tp, null, "#" + posNumber);

                    if (toClose && pos != null)
                        pos.Close();
                }

        }

        private double VolumeInUnits(double vol)
        {
            var v = Symbol.QuantityToVolumeInUnits(vol);
            v = Symbol.NormalizeVolumeInUnits(v, RoundingMode.Down);
            return v;
        }
    }
}
Comments

jumpycalm - May 09, 2019 @ 17:11

Nice job!

astevani - May 09, 2019 @ 19:01

thanks

gastaodm - June 09, 2019 @ 10:48

Hi, I am enjoying a lot your robot. It would be wonderful to have pending orders.
Thanks.

5