Topics
Replies

firemyst
20 Aug 2019, 17:59

RE:

khongkhongaaa said:

Hello cTrader team,

 

I programmed a robot in cTrader Automate.

 

But,

I don't want to sell the source code.

I only want to rent (no sell) and earn profits.


I mean:

My customer can only use robot, but don't view source code. And when the expiry date, the robot will end.

 

Is there any idea to do that?

Is there an expiration time (end time) for the Robot?

Has anyone ever done this before?

 

Thank you & Happy Trading!

One of the most fool-proof ways is:

1) you have to create a robot that has full access

2) read the unique value of a windows registry key every time the bot runs. One that's installed by Windows so you know it won't be changing or get uninstalled.

3) open up a web service call to a webservice you have running somewhere

4) when your bot calls the webservice for the first time, save that unique guid and current date time

5) every day your robot is running, make another webservice call with the same unique guid and the current date time. Compare against the one saved on the server where your web service is hosted.

6) if the current date/time difference between the robot's latest time and the time saved on the webservice server is past the expirational period, have the bot stop.

This will make sure that if the user changes the local date time on the computer they're running the bot on, it won't matter. It also won't matter if they look on the computer for saved information because you're not saving it there either. You also know that the computer your bot is running on must have internet access to be able to trade.


@firemyst

firemyst
20 Aug 2019, 17:48

One option you have is to keep a running total of your robot using a C# Dictionary<string,double> object in your close event method:

//Keep the running total of losses and consecutive trade losses
                    if (_runningTotalsGainLoss.ContainsKey(p1.Label))
                        _runningTotalsGainLoss[p1.Label] += p1.NetProfit;
                    else
                        _runningTotalsGainLoss.Add(p1.Label, p1.NetProfit);

And then do a simple check:

if (_runningTotalsGainLoss[p1.Label] < [your loss threshold parameter])
                    {
                        Print("WARNING! Running total {0} has fallen below {1} threshold! Stopping bot for \"{2}\"!", String.Format("{0:$#,###.00}", _runningTotalsGainLoss[p1.Label]), String.Format("{0:$#,###.00}", [your loss threshold parameter]), p1.Label);
                        Stop();
                        return;
                    }

 


@firemyst

firemyst
20 Aug 2019, 17:38

I don't know if there's an API call for it, but you could always try writing the stop loss in an encoded string within the "comment" when the order is placed.

Then parse it from the historical trade info.

For instance, make your encoded string %SL:xx.x% where xx.x is the pips SL.

Then all you need do is parse the string to find it. :-)


@firemyst

firemyst
17 Aug 2019, 18:37

RE:

gutygs said:

Hi everyone!

I am new to this forum and cTrader for the matter! I come from using MQL4 but I-m now switching to cTrader for it's many features!

I'm sorry if this has been solved before. I've looked for it without any luck; I'm trying to build an array of close prices beginning from the last candle up until a term iCandle. When I call MarketSeries.Close[index] outside a for loop, the data is displayed nicely. Nonetheless, upon calling the method inside a for loop, I don't get any value back. I am also new to C# as I've been coding in Python for the last 2 years, so I'm guessing there must be something I'm doing wrong.

Any help will be much appreciated! Thank you!

Code:


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.None)]
    public class Strategy5 : Robot
    {
        [Parameter("iCandle", DefaultValue = 7)]
        public int iCandle { get; set; }

        protected override void OnStart()
        {

            Print("initializing console");

        }

        protected override void OnBar()
        {

            //lets print the last 7 candle closes
            Print("Printing the last 7 candles");
            var lastIndex = MarketSeries.Close.Count - 1;

            string data = "";
    
            for (int i = lastIndex; i <= lastIndex-iCandle; i--)
            {
            string strclose = MarketSeries.Close[i].ToString();
            data += strclose + ", ";
            }

            Print("last prices are {0}", data);


        }

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

 

Of course you won't get any values inside the for loop. Look at the conditions of your for loop.

 for (int i = lastIndex; i <= lastIndex-iCandle; i--)

lastIndex is set to the last index.

i is set to this value.

So how is "i" going to be less than the "lastIndex - iCandle"?

Say lastIndex is 3000. So i starts off at 3000.

how is 3000 going to be <= (3000 - 5)?

It never will be.

So it never enters your for-loop.

And thus nothing is printed.


@firemyst

firemyst
17 Aug 2019, 18:26

You need to calculate the difference in pips between the two emas.

Here's a function that will help you:

 private double DifferenceInPips(Symbol s, double firstPrice, double secondPrice, bool returnAbs)
        {
            if (returnAbs)
                return Math.Abs((firstPrice - secondPrice) / s.PipSize);
            else
                return (firstPrice - secondPrice) / s.PipSize;
        }

 

Then change your condition from:

if (_sma1.Result.LastValue > _sma2.Result.LastValue)

to:

if (_sma1.Result.LastValue > _sma2.Result.LastValue && DifferenceInPips(Symbol, _sma1.Result.LastValue, _sma2.Result.LastValue, false) > whatever_amount_you_want)


@firemyst

firemyst
17 Aug 2019, 18:19

RE:

A few suggestions:

1) You know it gets to line 35 from the log file and prints out "Hour4", so comment out every line after that and see if things work. If so, Uncomment line by line to see exactly which one is causing you the error.

2) Change your "catch" statement to "catch (Exception e)" and then change the print statement to be:

Print("Error: {0}", e.Message);

 

That should hopefully give you a good start.


@firemyst

firemyst
17 Aug 2019, 18:09

RE:

ChrisCz said:

Hi,

I'm sure, I'm missing something obvious.

I wanna share some of my indicators with hte source code readable. But all my friends get is the executable source code, when they import and install the Algo I sent them. They get the messsage: Source code not available, when they try to modify my code.

Any help would be appreciated,

 

Chris

When you send them the algo file, also send them the .cs (c-sharp) source file.

When they save the files, save them both in the "C:\Users\<user id>\Documents\cAlgo\Sources\Indicators" folder.

Double click the algo file to install, and then they should be able to see the source code from cTrader. Or, they can just look at the source code from the .cs file you send them.

if they don't have a source code editor, just have them rename the file, add ".txt" to the end, and then they can open it easily Notepad.

Hope this helps.


@firemyst

firemyst
17 Aug 2019, 18:01 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Sorry for not clarifying, I thought you were familiar with this. The next time this happens, press Ctrl+Alt+Shift+T in cTrader and a pop up will appear. Paste a link to this discussion into the test box and press submit. This action will send us all the necessary information we need. Leave a comment here so that we can go and check.

Best Regards, 

Panagiotis

@Panagiotis:

I'll do you one better. Here's the source code needed to reproduce this issue. Details on what to do are in the comments.

Screen capture below too from Visual Studio showing the the breakpoints, and that it goes into the code block that the position's stoploss is zero immediately after fulfilling the order with a 1.2 pip SL.

Set these values when backtesting:

Here's the code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using Microsoft.Win32;

namespace cAlgo.Robots
{

//THIS CODE DEMONSTRATES THE BUG OF PLACING AN ORDER WITH A STOP LOSS of 1.2 pips,
//AND UPON SUCCESS, Position.StopLoss.GetValueOrDefault() returns 0!

//Run this in Back testing mode Aug 12 - 16
//Market: US30
//M1 time frame
//Use the setting "Tick data from server (accurate)"
//It will bomb out shortly after 1am server time. 

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BugBot : Robot
    {
        private string _positionLabel;
        private string _comment;
        private ParabolicSAR _psar;

        protected override void OnStart()
        {
            _psar = Indicators.ParabolicSAR(0.02, 0.2);
            _positionLabel = MarketSeries.TimeFrame + " " + Symbol.Name + " Bug Bot";
            _comment = "this is a bug hunt test.";
            Print("OnStart: Starting \"{0}\"", _positionLabel);
        }

        protected override void OnTick()
        {
            double _psarLastValue = _psar.Result.Last(1);
            if (Server.Time.Hour >= 1)
            {
                double psarSL = RoundPipsOrPrice(Symbol, DifferenceInPips(Symbol, Symbol.Bid, _psarLastValue, false), true);
                if (psarSL == 1.2)
                {
                    TradeResult r = ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1, _positionLabel, psarSL, psarSL * 5, "Does this have a stop loss after the order is executed?", false);
                    if (r.IsSuccessful)
                    {
                        Position _p = Positions.Find(_positionLabel, Symbol.Name);
                        Print("L2 Long Order Successful. \"{0} {1}\" Entry Price: {2}, SL: {3}, {4}", _p.Id, _p.Label, _p.EntryPrice, _p.StopLoss.GetValueOrDefault(), _p.Comment);

                        if (_p.StopLoss.GetValueOrDefault() == 0)
                        {
                            Print("WARNING! Stop loss is zero! Why?! Closing position \"{0} {1}\".", _p.Id, _p.Label);
                            ClosePosition(_p);
                            Stop();
                            return;
                        }
                    }
                }
            }
        }

        protected override void OnStop()
        {
        }

        private double DifferenceInPips(Symbol s, double firstPrice, double secondPrice, bool returnAbs)
        {
            if (returnAbs)
                return Math.Abs((firstPrice - secondPrice) / s.PipSize);
            else
                return (firstPrice - secondPrice) / s.PipSize;
        }

        private double RoundPipsOrPrice(Symbol s, double pipsOrPrice, bool isPips)
        {
            string k = s.Name.ToUpper();
            decimal result = 0;
            decimal factor = 0;

            if (!isPips)
                factor = (decimal)Math.Pow(10, s.Digits);
            else
                factor = (decimal)Math.Pow(10, 1);

            result = Math.Truncate(factor * (decimal)pipsOrPrice) / factor;
            return Convert.ToDouble(result);
        }
    }
}

And here's a screen capture from Visual Studio in debug mode attached to cTrader:

What's happening to cause this?

Thank you.


@firemyst

firemyst
14 Aug 2019, 10:04

RE:

anton.kovalchuk said:

The example exists in cAlgo confluence. 

var position = Positions.Find("myLabel", Symbol, TradeType.Buy);
if (position != null )
{
    double? stopLoss = Symbol.Ask- 10*Symbol.PipSize;
    double? takeProfit = Symbol.Ask + 10 * Symbol.PipSize;
    ModifyPosition(position, stopLoss,  takeProfit);
}

 

 

Shouldn't the above example be:

var position = Positions.Find("myLabel", Symbol, TradeType.Buy);
if (position != null )
{
    double? stopLoss = Symbol.Ask- 10*Symbol.PipValue; // use PipValue instead of PipSize because we are subtracting from price
    double? takeProfit = Symbol.Ask + 10 * Symbol.PipValue; //use PipValue instead of PipSize becacuse we are adding to a price
    ModifyPosition(position, stopLoss,  takeProfit);
}

because it's working in prices, not sizes?


@firemyst

firemyst
09 Aug 2019, 15:03

RE:

Panagiotis Charalampous said:

Hi FireMyst,

We tried reproducing the problem but we could not. To investigate further we will need more information like the full cBot code, the number of instances running concurrently and the cBot parameters for each of them. We need to setup the exact same environment as you have. If you can send this information we can have another look.

Best Regards,

Panagiotis

I will try setting it up with simplified code and let you know. It didn't happen often, but often enough. I typically had 23 bot instances running.


@firemyst

firemyst
09 Aug 2019, 15:00

RE:

Panagiotis Charalampous said:

Hi FireMyst,

It seems that in the VPS instance you are in cTrader Automate. The workspaces are available when you are in Trade tab.

Best Regards,

Panagiotis

@Panagiotis:

Lol. Glad you have better eyes than me. Such a "duh" moment on my part.

Thanks again :-)


@firemyst

firemyst
08 Aug 2019, 18:09 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

We have investigated this issue further

  1. The message seems to appear because you have instances with different workspaces running. When connection is lost and then restored then cTrader attempts to load the last used workspace, therefore tries to change the workspace for one of the instances. Thus you get the message. This behavior will change in 3.6
  2. We could not reproduce performance issues. As far as we can tell you are using several custom cBots/indicators which could be the cause of the problem. To investigate further we will need all the custom indicators and cBots running as well as your settings file

Best Regards,

Panagiotis 

Thanks @Panagiotis:

When I run Pepperstone cTrader 3.5 on Windows Server 2012 VPS, as you can see, there's no options there to change workspaces:

When I run it on my local laptop, look at the difference:

I'm downloading from here:

https://pepperstone.com/au/trading-platforms/platforms/ctrader

The top one is on a VPS running Windows Server 2012; the bottom one is on a Windows 10 laptop.

Why would there be a difference? Shouldn't they both have the drop-down menu to change workspaces?

 


@firemyst

firemyst
06 Aug 2019, 17:36 ( Updated at: 19 Mar 2025, 08:57 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Send us the video at support@ctrader.com.

Best Regards,

Panagiotis

Sent the mp4 file as requested.

It will show you me clicking on the button and not doing anything; however, I can click on other buttons fine to start/stop bot instances.

 

 


@firemyst

firemyst
06 Aug 2019, 17:14

Hi Team Spotware:

After running on multiple computers today, it didn't happen once when I switched back to using:

p.StopLoss.GetValueOrDefault() in the ModifyPositionAsync call.

Yesterday after I reported it in the forums here, but before making the code change, it happened again on the GBPAUD pair.

So I definitely believe that using p.StopLoss.Value in the ModifyPositionAsync call is causing the issue and needs further investigation.

 

Thank you.


@firemyst

firemyst
06 Aug 2019, 17:11 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

If you can send us troubleshooting information when this happens again it will help us investigate.

Best Regards,

Panagiotis

Hi @Panagiotis:

It just happened again on my VPS in a demo account while trading in a live account on my local laptop.

22:10 UTC + 8 time.

I did a ctrl-alt-shift-T in cTrader and sent it in with a note that I posted about it in the forums.


@firemyst

firemyst
30 Jul 2019, 10:15

RE:

Panagiotis Charalampous said:

Hi FireMyst,

It will override all locally saved settings not only bot instances. 

Best Regards,

Panagiotis

Thanks @Panagiotis.

I have different settings between a VPS and my local computers.

So, this would be an obvious suggestion for SpotWare to consider changing for future version... so users can copy bot instances and their settings separately. Much like we can copy ".algo" files.

Thank you


@firemyst

firemyst
29 Jul 2019, 11:08

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Go to C:\Users\User\AppData\Roaming\Broker cTrader\Settings and copy the settings file. It should copy your cBot instances to the computer.

Best Regards,

Panagiotis

Thanks. Before I try this, I want to confirm - will it copy ALL cTrader settings? Or only just the bot-instances and their settings?

I obviously don't want anything else I have configured between the two computers to be over-written.

Thank you.

 


@firemyst

firemyst
26 Jul 2019, 09:57

RE:

Panagiotis Charalampous said:

Hi FireMyst,

The indicator you are showing has UpTrend and DownTrend values. In your code you use Result

            GetLatestIndicatorData();
            double b0 = _superTrend.Result.Last(0);
            double b1 = _superTrend.Result.Last(1);
            double b2 = _superTrend.Result.Last(2);

Also the multiplier you are showing is 1.5. In the code you have 2.5

_superTrend = Indicators.GetIndicator<Supertrend>(13, 2.5);

Best Regards,

Panagiotis

You're absolutely right. See my edited post above.


@firemyst

firemyst
26 Jul 2019, 09:43

RE:

Panagiotis Charalampous said:

Are you sure you are using the same indicator with the same parameters? Because it doesn't to me. The indicator in your image has two colors while the indicator in the post does not have such a feature.

Best Regards,

Panagiotis

Yes, I am using same indicator. Sorry for the confusion. The indicator has options to show "uptrend" and "downtrend" in different colors, or a "main" line which keeps it with one color.

 

As I was going to email you the code, I just noticed in the code that I had the parameters hard-coded in one portion of the bot and were different than the display paramter of the indicator on the chart.

 

I'm so sorry for wasting your time @Panagiotis. Grrr... talk about feeling stupid now. Thank you for your patience. :-)

 

 


@firemyst

firemyst
25 Jul 2019, 17:54 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Panagiotis Charalampous said:

Hi FireMyst,

Same explanation applies. The values you get in the log are the correct since all ticks are considered. The values you see on the chart are not as accurate as some ticks are skipped. 

Best Regards,

Panagiotis

So I ran it "live", not in backtesting mode, as you can see below.

1) Is this what you mean by "live execution"?

2) Just so we're on the same page, which bar is considered the current bar? 1? 2? or 3?

Notice in none of the cases does the indicator get drawn down to the 0.91337 level as logged!

3) Still not an issue? I'm convinced it is because running it like this live, the indicator should show me the exact values on the chart - not "skipping" any ticks.

 

 


@firemyst