Skip to content

Customisable parameters in Python algorithms

When developing Python trading bots, technical indicators or plugins for cTrader, you may need to add and configure customisable parameters. This article explains how to declare and use customisable parameters for a Python algorithm in .cs and .json files.

Note

Define all customisable parameters for a Python algorithm in either its .cs or .json file, but not in both.

Location

The location of the .cs or .json file for a Python algorithm depends on the algorithm type, whether it is a cBot, indicator or plugin, as well as the name of the algorithm.

  • For cBots: Documents/cAlgo/Sources/Robots/{cBot-name}/{cBot-name}/
  • For indicators: Documents/cAlgo/Sources/Indicators/{Indicator-name}/{Indicator-name}/
  • For plugins: Documents/cAlgo/Sources/Plugins/{Plugin-name}/{Plugin-name}/

Note

When you create a Python algorithm in cTrader Windows or Mac, the necessary .cs and .json files are automatically generated in the relevant folder.

You can follow these instructions to locate the required folder:

  1. Right-click the algorithm in cTrader Windows or Mac, then select Show in folder.

  2. Navigate through {name-of-algorithm}/{name-of-algorithm}, then identify the .cs (C# source file) or .json (JSON source file) item.

    The .cs file typically has the same name as the algorithm, with all spaces removed. For example, an algorithm named Amazing Aroon cBot results in a AmazingArooncBot.cs file.

    Tip

    In the same folder, you can access the main Python code for your algorithm, stored in a .py file such as Amazing Aroon cBot_main.py. The Python file follows a simple naming convention:

    • For cBots: cBot-name_main.py
    • For indicators: Indicator-name_main.py
    • For plugins: Plugin-name_main.py

    config.json is always the exact name.

    Tip

    In the same folder, you can access the main Python code for your algorithm, stored in a .py file such as Ultimate Indicator_main.py. The Python file follows a simple naming convention:

    • For cBots: cBot-name_main.py
    • For indicators: Indicator-name_main.py
    • For plugins: Plugin-name_main.py

Content

Open the .cs or .json file in any editor, such as Visual Studio Code, and you should see code similar to this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
using cAlgo.API;

namespace cAlgo.Robots;

[Robot(AccessRights = AccessRights.None, AddIndicators = true)]
public partial class AmazingArooncBot : Robot
{
    [Parameter("Volume (Lots)", DefaultValue = 0.01)]
    public double VolumeInLots { get; set; }

    [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)]
    public double StopLossInPips { get; set; }

    [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)]
    public double TakeProfitInPips { get; set; }

    [Parameter("Label", DefaultValue = "AmazingArooncBot")]
    public string Label { get; set; }

    [Parameter("Periods", DefaultValue = 25, Group = "Aroon", MinValue = 2)]
    public int Periods { get; set; }
}

Note

You should see an empty class if you created your Python algorithm from scratch without using a template.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{
"TimeZone": "Arab Standard Time",
"AccessRights": "FullAccess",
"AdditionalInfoUrl": "https://ctrader.com/",
"IsOverlay": true,
"Parameters": [
    {
    "DisplayName": "My Color",
    "Name": "MyColor",
    "DefaultValue": "#102049",
    "Type": "Color"
    },
    {
    "DisplayName": "My String",
    "Name": "MyString",
    "DefaultValue": "Test",
    "Type": "String",
    "Group": "Strings"
    },
    {
    "DisplayName": "My Int",
    "Name": "MyInt",
    "DefaultValue": 10,
    "MinValue": 1,
    "MaxValue": 100,
    "Step": 5,
    "Type": "Integer"
    },
    {
    "DisplayName": "My Double",
    "Name": "MyDouble",
    "DefaultValue": 10.5,
    "MinValue": 1.5,
    "MaxValue": 100.5,
    "Step": 5.5,
    "Type": "Double"
    },
    {
    "DisplayName": "My TimeFrame",
    "Name": "MyTimeFrame",
    "DefaultValue": "Hour",
    "Type": "TimeFrame"
    },
    {
    "DisplayName": "My Symbol",
    "Name": "MySymbol",
    "DefaultValue": "GBPUSD",
    "Type": "Symbol"
    },
    {
    "DisplayName": "My Enum",
    "Name": "MyEnum",
    "DefaultValue": "Buy",
    "EnumTypeFullName": "cAlgo.API.TradeType",
    "Type": "Enum"
    },
    {
    "DisplayName": "My Time",
    "Name": "MyTime",
    "DefaultValue": "00:01:00",
    "MinValue": "-10:00:00",
    "MaxValue": "10:00:00",
    "Step": 100,
    "Type": "TimeSpan"
    },
    {
    "DisplayName": "Custom Enum",
    "Name": "CustomEnum",
    "DefaultValue": "High",
    "EnumTypeFullName": "RiskLevel",
    "Type": "Enum"
    }
],
"LineOutputs": [
    {
    "DisplayName": "My Line 1",
    "Name": "Line1",
    "LineStyle": "Dots",
    "Description": "Good line"
    },
    {
    "DisplayName": "My Line 2",
    "Name": "Line2",
    "LineStyle": "Dots",
    "Description": "Good line"
    },
    {
    "DisplayName": "My Line 3",
    "Name": "Line3",
    "LineStyle": "Dots",
    "Description": "Good line"
    },
    {
    "DisplayName": "My Line 4",
    "Name": "Line4",
    "LineStyle": "Dots",
    "Description": "Good line"
    }
],
"BarOutputs": [
    {
    "DisplayName": "My Bars",
    "Name": "MyBars",
    "ChartType": "Line",
    "BullFillColor": "Green",
    "BearFillColor": "Red",
    "BullOutlineColor": "Yellow",
    "BearOutlineColor": "Orange",
    "TickVolumeColor": "#F43562",
    "AreaChartFillColor": "#F41552",
    "DotChartColor": "#F67552",
    "Description": "Beautiful bars"
    }
],
"Clouds": [
    {
    "FirstLineName": "My Line 1",
    "SecondLineName": "My Line 2",
    "FirstColor": "Red",
    "SecondColor": "Blue",
    "Opacity": 0.5
    },
    {
    "FirstLineName": "My Line 3",
    "SecondLineName": "My Line 4",
    "FirstColor": "Yellow",
    "SecondColor": "Black",
    "Opacity": 0.8
    }
],
"Levels": [10.1, 20.5, 80.7],
"Enums": [
    {
    "Name": "RiskLevel",
    "Values": ["Low", "Medium", "High"]
    }
]
}

Any parameter declared in the .cs or .json file can be used in the main Python file, which houses the code displayed in the code editor.

The main Python code below illustrates the usage of the customisable parameters:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *

# Import trading wrapper functions
from robot_wrapper import *

class AmazingArooncBot():
    def on_start(self):
        self.volumeInUnits = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.aroon = api.Indicators.Aroon(api.Periods)

    def on_bar_closed(self):
        if self.aroon.Up.Last(0) > self.aroon.Down.Last(0) and self.aroon.Up.Last(1) < self.aroon.Down.Last(1):
            self.close_positions(TradeType.Sell)
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, self.volumeInUnits, api.Label, api.StopLossInPips, api.TakeProfitInPips)
        elif self.aroon.Up.Last(0) < self.aroon.Down.Last(0) and self.aroon.Up.Last(1) > self.aroon.Down.Last(1):
            self.close_positions(TradeType.Buy)
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, self.volumeInUnits, api.Label, api.StopLossInPips, api.TakeProfitInPips)

    def get_bot_positions(self):
        return api.Positions.FindAll(api.Label)

    def close_positions(self, tradeType):
        for position in self.get_bot_positions():
            if position.TradeType != tradeType:
                continue
            api.ClosePosition(position)

The main Python code below illustrates the usage of a customisable parameter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class UltimateIndicator():
    def initialize(self):
        print(f"Custom Enum: {api.CustomEnum}")
        if api.CustomEnum == RiskLevel.High:
            print("It's high")

    def calculate(self, index):
        pass

Advantages

The primary advantage of customisable parameters is that they appear as editable fields in the UI of all cTrader apps, including cTrader Mobile, Web, Windows and Mac. The values in these fields can be changed easily to suit any need or operation, without the need to access or modify the algorithm's source code.

In cTrader Store, sellers often use customisable parameters to ensure that buyers of algorithms are able to adjust the algos to suit their goals and workflows.

Image title