diff --git a/Plugins/ASP Section Example/ASP Section Example/ASP Section Example.cs b/Plugins/ASP Section Example/ASP Section Example/ASP Section Example.cs index 549fe29..c5d4ffb 100644 --- a/Plugins/ASP Section Example/ASP Section Example/ASP Section Example.cs +++ b/Plugins/ASP Section Example/ASP Section Example/ASP Section Example.cs @@ -5,26 +5,32 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The sample demonstrates how to create and configure a custom block in Active Symbol Panel (ASP) +// using the cTrader Algo API. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class ASPSectionExample : Plugin { + // This method is triggered when the plugin starts. protected override void OnStart() { - var block = Asp.SymbolTab.AddBlock("My title"); - block.Index = 2; - block.Height = 500; - block.IsExpanded = true; + var block = Asp.SymbolTab.AddBlock("My title"); // Add a custom block to the ASP under the Symbol tab. + + block.Index = 2; // Set the position index of the block in the panel. + block.Height = 500; // Define the height of the block in pixels. + block.IsExpanded = true; // Make the block expanded by default. - var webView = new WebView(); - block.Child = webView; + var webView = new WebView(); // Create a WebView control to display a webpage. + block.Child = webView; // Adding the WebView as a child element to the block. - webView.NavigateAsync("https://ctrader.com/"); + webView.NavigateAsync("https://ctrader.com/"); // Navigate the WebView to the cTrader website. } } -} \ No newline at end of file +} diff --git a/Plugins/ActiveFrameChanged Sample/ActiveFrameChanged Sample/ActiveFrameChanged Sample.cs b/Plugins/ActiveFrameChanged Sample/ActiveFrameChanged Sample/ActiveFrameChanged Sample.cs index c5c42d7..1a7694f 100644 --- a/Plugins/ActiveFrameChanged Sample/ActiveFrameChanged Sample/ActiveFrameChanged Sample.cs +++ b/Plugins/ActiveFrameChanged Sample/ActiveFrameChanged Sample/ActiveFrameChanged Sample.cs @@ -5,9 +5,10 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a new block into the ASP. The block displays the percentage difference between -// the current price of a symbol its price a month ago; the symbol is taken from the currently active -// chart frame. This is achieved by handling the ChartManager.ActiveFrameChanged event. +// The sample adds a new block into Active Symbol Panel (ASP). The block displays the percentage +// difference between the current price of a symbol its price a month ago; the symbol is taken from +// the currently active chart frame. This is achieved by handling the ChartManager.ActiveFrameChanged +// event. // // ------------------------------------------------------------------------------------------------- @@ -19,19 +20,19 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class ActiveFrameChangedSample : Plugin { - - // Declaring the necessary UI elements + // Declare the necessary UI elements. private Grid _grid; private TextBlock _percentageTextBlock; private Frame _activeFrame; + // This method is triggered when the plugin starts. protected override void OnStart() { - // Initialising the grid and the TextBlock - // displaying the percentage difference + // Initialise the grid and the TextBlock displaying the percentage difference. _grid = new Grid(1, 1); _percentageTextBlock = new TextBlock { @@ -40,38 +41,36 @@ protected override void OnStart() Text = "Monthly change: ", }; - _grid.AddChild(_percentageTextBlock, 0, 0); + _grid.AddChild(_percentageTextBlock, 0, 0); // Add the TextBlock to the grid at row 0, column 0. - // Initialising a new block inside the ASP - // and adding the grid as a child + // Initialise a new block inside the ASP tab and add the grid as a child. var block = Asp.SymbolTab.AddBlock("Monthly Change Plugin"); block.Child = _grid; - // Attaching a custom handler to the - // ActiveFrameChanged event + // Attach a custom handler to the ActiveFrameChanged event. ChartManager.ActiveFrameChanged += ChartManager_ActiveFrameChanged; } + // This method is triggered whenever the active frame changes in the chart manager. private void ChartManager_ActiveFrameChanged(ActiveFrameChangedEventArgs obj) { + // Check if the new frame is a ChartFrame. if (obj.NewFrame is ChartFrame) { - // Casting the Frame into a ChartFrame + // Cast the Frame into a ChartFrame. var newChartFrame = obj.NewFrame as ChartFrame; - // Attaining market data for the symbol for which - // the currently active ChartFrame is opened + // Attain market data for the symbol for which the currently active ChartFrame is opened. var dailySeries = MarketData.GetBars(TimeFrame.Daily, newChartFrame.Symbol.Name); - // Calculating the monthly change and displaying it - // inside the TextBlock + // Calculate the monthly change and display it inside the TextBlock. double monthlyChange = (newChartFrame.Symbol.Bid - dailySeries.ClosePrices[dailySeries.ClosePrices.Count - 30]) / 100; - _percentageTextBlock.Text = $"Monthly change: {monthlyChange}"; + _percentageTextBlock.Text = $"Monthly change: {monthlyChange}"; // Update the TextBlock with the calculated change. } } } -} \ No newline at end of file +} diff --git a/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs b/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs index 9ceb1ec..6397c82 100644 --- a/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs +++ b/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a trade watch tab, and uses AlgoRegistry API to show stats about installed algo types. +// The sample adds a trade watch tab and uses Algo Registry API to show stats about installed algo types. // // ------------------------------------------------------------------------------------------------- @@ -13,23 +13,25 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class AlgoRegistrySample : Plugin { + // This method is triggered when the plugin starts. protected override void OnStart() { - var tradeWatchTab = TradeWatch.AddTab("Algo Registry"); + var tradeWatchTab = TradeWatch.AddTab("Algo Registry"); // Add a new tab to the Trade Watch section, named "Algo Registry". - var panel = new StackPanel + var panel = new StackPanel // Initialise a StackPanel to hold UI elements. { - Orientation = Orientation.Horizontal, - HorizontalAlignment = HorizontalAlignment.Center, + Orientation = Orientation.Horizontal, // Set the panel orientation to horizontal. + HorizontalAlignment = HorizontalAlignment.Center, // Centre the panel within its parent container horizontally. }; - panel.AddChild(new AlgoStatsControl(AlgoRegistry) {Margin = 10, VerticalAlignment = VerticalAlignment.Top}); - panel.AddChild(new AlgoTypeInfoControl(AlgoRegistry) {Margin = 10, VerticalAlignment = VerticalAlignment.Top}); + panel.AddChild(new AlgoStatsControl(AlgoRegistry) {Margin = 10, VerticalAlignment = VerticalAlignment.Top}); // Add the AlgoStatsControl to the panel with a margin and top vertical alignment. + panel.AddChild(new AlgoTypeInfoControl(AlgoRegistry) {Margin = 10, VerticalAlignment = VerticalAlignment.Top}); // Add the AlgoTypeInfoControl to the panel with a margin and top vertical alignment. - tradeWatchTab.Child = panel; + tradeWatchTab.Child = panel; // Set the StackPanel containing the controls as the content of the "Algo Registry" tab in the Trade Watch section. } } -} \ No newline at end of file +} diff --git a/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoStatsControl.cs b/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoStatsControl.cs index eeff422..bcc7c80 100644 --- a/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoStatsControl.cs +++ b/Plugins/AlgoRegistry Sample/AlgoRegistry Sample/AlgoStatsControl.cs @@ -1,84 +1,94 @@ -using System.Linq; +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This code is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// The sample creates a custom control that displays statistics about registered algorithms in the +// platform. It shows counts for total algos, custom indicators, standard indicators, cBots and +// plugins. The statistics dynamically update when algo types are installed or deleted. +// +// ------------------------------------------------------------------------------------------------- + + +using System.Linq; using cAlgo.API; namespace cAlgo.Plugins; public class AlgoStatsControl: CustomControl { - private const string FontFamily = "Calibri"; + private const string FontFamily = "Calibri"; // Define a constant for the font family used in the UI. + private readonly AlgoRegistry _algoRegistry; // Hold a reference to the Algo Registry for accessing algorithm data. - private readonly AlgoRegistry _algoRegistry; - private readonly TextBlock _algosCountTextBlock; - private readonly TextBlock _customIndicatorsCountTextBlock; - private readonly TextBlock _standardIndicatorsCountTextBlock; - private readonly TextBlock _botsCountTextBlock; - private readonly TextBlock _pluginsCountTextBlock; + private readonly TextBlock _algosCountTextBlock; // TextBlock to display the total number of algorithms. + private readonly TextBlock _customIndicatorsCountTextBlock; // Number of custom indicators. + private readonly TextBlock _standardIndicatorsCountTextBlock; // Number of standard indicators. + private readonly TextBlock _botsCountTextBlock; // Number of cBots. + private readonly TextBlock _pluginsCountTextBlock; // Number of plugins. + // This method initialises the control that displays stats for installed algorithms, including cBots, custom indicators and plugins. public AlgoStatsControl(AlgoRegistry algoRegistry) { - _algoRegistry = algoRegistry; - - var panel = new Grid(6, 2); - - var titleTextBlock = GetTextBlock("Algo Stats"); - - titleTextBlock.HorizontalAlignment = HorizontalAlignment.Center; - - panel.AddChild(titleTextBlock, 0, 0, 1, 2); + _algoRegistry = algoRegistry; // Assign the provided Algo Registry instance to the private field. - panel.AddChild(GetTextBlock("Algos #"), 1, 0); - - _algosCountTextBlock = GetTextBlock(); + var panel = new Grid(6, 2); // Create a grid with 6 rows and 2 columns for organising UI elements. + var titleTextBlock = GetTextBlock("Algo Stats"); // Create a title TextBlock with the text "Algo Stats". + titleTextBlock.HorizontalAlignment = HorizontalAlignment.Center; // Centre the title horizontally. + panel.AddChild(titleTextBlock, 0, 0, 1, 2); // Add the title to the first row, spanning both columns. - panel.AddChild(_algosCountTextBlock, 1, 1); + // Add a label and its corresponding TextBlock for "Algos #" to the grid. + panel.AddChild(GetTextBlock("Algos #"), 1, 0); // Add a label and its corresponding TextBlock for "Algos #" to the grid. + _algosCountTextBlock = GetTextBlock(); // Create a TextBlock to display the total algorithm count. + panel.AddChild(_algosCountTextBlock, 1, 1); // Add the TextBlock to the grid. + // Add a label and TextBlock for "Standard Indicators #". panel.AddChild(GetTextBlock("Standard Indicators #"), 2, 0); - _standardIndicatorsCountTextBlock = GetTextBlock(); - panel.AddChild(_standardIndicatorsCountTextBlock, 2, 1); + // Add a label and TextBlock for "Custom Indicators #". panel.AddChild(GetTextBlock("Custom Indicators #"), 3, 0); - _customIndicatorsCountTextBlock = GetTextBlock(); - panel.AddChild(_customIndicatorsCountTextBlock, 3, 1); + // Add a label and TextBlock for "cBots #". panel.AddChild(GetTextBlock("cBots #"), 4, 0); - _botsCountTextBlock = GetTextBlock(); - panel.AddChild(_botsCountTextBlock, 4, 1); + // Add a label and TextBlock for "Plugins #". panel.AddChild(GetTextBlock("Plugins #"), 5, 0); - _pluginsCountTextBlock = GetTextBlock(); - panel.AddChild(_pluginsCountTextBlock, 5, 1); - AddChild(panel); + AddChild(panel); // Add the grid containing all UI elements to the control. - Populate(); + Populate(); // Populate the TextBlocks with the initial statistics. - _algoRegistry.AlgoTypeInstalled += _ => Populate(); - _algoRegistry.AlgoTypeDeleted += _ => Populate(); + // Subscribe to events to update statistics when an algorithm type is installed or deleted. + _algoRegistry.AlgoTypeInstalled += _ => Populate(); // Call Populate() on algorithm installation. + _algoRegistry.AlgoTypeDeleted += _ => Populate(); // Call Populate() on algorithm deletion. } + // This method updates the statistics displayed in the TextBlocks. private void Populate() { - _algosCountTextBlock.Text = _algoRegistry.Count.ToString(); - _botsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.Robot).ToString(); - _customIndicatorsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.CustomIndicator).ToString(); - _standardIndicatorsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.StandardIndicator).ToString(); - _pluginsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.Plugin).ToString(); + _algosCountTextBlock.Text = _algoRegistry.Count.ToString(); // Set the total algorithm count. + _botsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.Robot).ToString(); // Count cBots. + _customIndicatorsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.CustomIndicator).ToString(); // Count custom indicators. + _standardIndicatorsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.StandardIndicator).ToString(); // Count standard indicators. + _pluginsCountTextBlock.Text = _algoRegistry.Count(type => type.AlgoKind == AlgoKind.Plugin).ToString(); // Count plugins. } + // This method creates and returns a new TextBlock with optional text. private TextBlock GetTextBlock(string text = null) => new() { - Margin = 3, - FontSize = 20, - FontWeight = FontWeight.Bold, - FontFamily = FontFamily, - Text = text + Margin = 3, // Set a margin around the TextBlock for spacing. + FontSize = 20, // Set the font size to 20. + FontWeight = FontWeight.Bold, // Set the font weight to bold. + FontFamily = FontFamily, // Use the defined font family. + Text = text // Set the text content, if provided. }; -} \ No newline at end of file +} diff --git a/Plugins/All placements/All placements/All placements.cs b/Plugins/All placements/All placements/All placements.cs index e285cee..ddf3348 100644 --- a/Plugins/All placements/All placements/All placements.cs +++ b/Plugins/All placements/All placements/All placements.cs @@ -5,6 +5,10 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The sample demonstrates how to integrate and customise various components in cTrader, such as +// adding commands to toolbars, creating Active Symbol Panel (ASP) blocks, tabs and custom frames. +// It also demonstrates customising the active chart appearance and functionality. +// // ------------------------------------------------------------------------------------------------- using System; @@ -15,62 +19,70 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class Allplacements : Plugin { - const string WebViewUrl = "https://ctrader.com"; + const string WebViewUrl = "https://ctrader.com"; // Define the URL to be used in WebView instances. + // This method is triggered when the plugin starts. protected override void OnStart() { var icon = new SvgIcon(@" -"); - Commands.Add(CommandType.ChartContainerToolbar, OnIconClicked, icon); +"); // Define an icon to be used in the toolbar. + + Commands.Add(CommandType.ChartContainerToolbar, OnIconClicked, icon); // Add the icon to the chart toolbar, which will trigger the OnIconClicked method when clicked. } + // This method is triggered when the toolbar icon is clicked. private CommandResult OnIconClicked(CommandArgs args) { - var buttonStyle = new Style(); - buttonStyle.Set(ControlProperty.Margin, new Thickness(0, 5, 0, 0)); - buttonStyle.Set(ControlProperty.Width, 150); - var stackPanel = new StackPanel(); + var buttonStyle = new Style(); // Create a new style for buttons. + buttonStyle.Set(ControlProperty.Margin, new Thickness(0, 5, 0, 0)); // Set the margin for the button. + buttonStyle.Set(ControlProperty.Width, 150); // Set the button width. + var stackPanel = new StackPanel(); // Create a StackPanel to stack UI elements vertically. + // Define the first button that shows a message box when clicked. var showMessageBoxButton = new Button { Text = "show MessageBox", Style = buttonStyle }; - showMessageBoxButton.Click += args => + showMessageBoxButton.Click += args => // Define the event handler for button click. { - MessageBox.Show("Some message", "Caption", MessageBoxButton.YesNo); + MessageBox.Show("Some message", "Caption", MessageBoxButton.YesNo); // Show a message box with a Yes/No prompt. }; - stackPanel.AddChild(showMessageBoxButton); + stackPanel.AddChild(showMessageBoxButton); // Add the button to the stack panel. + // Define the second button that opens a custom window with a WebView. var showCustomWindowButton = new Button { Text = "show Custom Window", Style = buttonStyle }; - showCustomWindowButton.Click += args => + showCustomWindowButton.Click += args => // Define the event handler for button click. { - var window = new Window(); - var webView = new WebView(); - window.Child = webView; + var window = new Window(); // Create a new window. + var webView = new WebView(); // Create a WebView control inside the window. + window.Child = webView; // Set the WebView as the child of the window. - window.Show(); - webView.NavigateAsync(WebViewUrl); + window.Show(); // Show the window. + webView.NavigateAsync(WebViewUrl); // Navigate to the URL in the WebView. }; - stackPanel.AddChild(showCustomWindowButton); + stackPanel.AddChild(showCustomWindowButton); // Add the button to the stack panel. - var blockCounter = 1; - var addAspBlockButton = new Button { Text = "add ASP Block", Style = buttonStyle }; - addAspBlockButton.Click += args => + // Define the parameters of the first option in the drop-down list ("add ASP Block"). + var blockCounter = 1; // Counter for adding ASP blocks dynamically. + var addAspBlockButton = new Button { Text = "add ASP Block", Style = buttonStyle }; // Button labeled "add ASP Block" with the defined button style. + addAspBlockButton.Click += args => // Define the event handler for adding a new ASP block. { - var newBlock = Asp.SymbolTab.AddBlock("One more block " + blockCounter); - newBlock.IsExpanded = true; - newBlock.Height = 600; - blockCounter++; - - var webView = new WebView(); - newBlock.Child = webView; - webView.NavigateAsync(WebViewUrl); + var newBlock = Asp.SymbolTab.AddBlock("One more block " + blockCounter); // Add a new block in the symbol tab. + newBlock.IsExpanded = true; // Expand the block to show content. + newBlock.Height = 600; // Set the block height. + blockCounter++; // Increment the block counter. + + var webView = new WebView(); // Create a WebView to display in the new block. + newBlock.Child = webView; // Add the WebView as the child of the new block. + webView.NavigateAsync(WebViewUrl); // Navigate to the specified URL in the WebView. }; - stackPanel.AddChild(addAspBlockButton); + stackPanel.AddChild(addAspBlockButton); // Add the button to the stack panel. + // Define the parameters of the next option in the drop-down list ("add ASP Tab"). var aspTabCounter = 1; var addAspTabButton = new Button { Text = "add ASP Tab", Style = buttonStyle }; addAspTabButton.Click += args => @@ -85,6 +97,7 @@ private CommandResult OnIconClicked(CommandArgs args) }; stackPanel.AddChild(addAspTabButton); + // Define the parameters of the next option in the drop-down list ("add TradeWatch Tab"). var tradewatchTabCounter = 1; var addTradeWatchTabButton = new Button { Text = "add TradeWatch Tab", Style = buttonStyle }; addTradeWatchTabButton.Click += args => @@ -100,6 +113,7 @@ private CommandResult OnIconClicked(CommandArgs args) }; stackPanel.AddChild(addTradeWatchTabButton); + // Define the parameters of the next option in the drop-down list ("add Custom Frame"). var addCustomFrameButton = new Button { Text = "add Custom Frame", Style = buttonStyle }; var customFrameCounter = 1; addCustomFrameButton.Click += args => @@ -113,6 +127,7 @@ private CommandResult OnIconClicked(CommandArgs args) }; stackPanel.AddChild(addCustomFrameButton); + // Define the parameters of the next option in the drop-down list ("customize Active Chart"). var customizeActiveChartButton = new Button { Text = "customize Active Chart", Style = buttonStyle }; customizeActiveChartButton.Click += args => { @@ -127,16 +142,16 @@ private CommandResult OnIconClicked(CommandArgs args) }; stackPanel.AddChild(customizeActiveChartButton); - var border = new Border(); - border.Padding = 5; - border.BackgroundColor = "#1A1A1A"; - border.CornerRadius = 3; - border.BorderThickness = 1; - border.BorderColor = "525252"; - border.Child = stackPanel; - border.Width = 170; - border.Height = 190; - return new CommandResult(border); + var border = new Border(); // Create a border container for the stack panel. + border.Padding = 5; // Add padding inside the border. + border.BackgroundColor = "#1A1A1A"; // Set the background color of the border. + border.CornerRadius = 3; // Round the corners of the border with a radius of 3. + border.BorderThickness = 1; // Set the thickness of the border to 1. + border.BorderColor = "525252"; // Set the color of the border to a gray shade. + border.Child = stackPanel; // Assign the stack panel as the child of the border. + border.Width = 170; // Set the width of the border. + border.Height = 190; // Set the height of the border. + return new CommandResult(border); // Return the border as the result of the command, completing the customisation UI. } } -} \ No newline at end of file +} diff --git a/Plugins/BacktestingInPlugins Sample/BacktestingInPlugins Sample/BacktestingInPlugins Sample.cs b/Plugins/BacktestingInPlugins Sample/BacktestingInPlugins Sample/BacktestingInPlugins Sample.cs index d32c5f2..c1a55ed 100644 --- a/Plugins/BacktestingInPlugins Sample/BacktestingInPlugins Sample/BacktestingInPlugins Sample.cs +++ b/Plugins/BacktestingInPlugins Sample/BacktestingInPlugins Sample/BacktestingInPlugins Sample.cs @@ -5,10 +5,10 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a new block into the ASP. The block contains a ComboBox, a custom Button, -// and a TextBlock. Upon choosing one of their installed cBots in the ComboBox, the user can click -// on the Button and backtest the chosen cBot on EURUSD h1. When backtesting is finished, the plugin -// will display its results in the TextBlock. +// The sample adds a new block into Active Symbol Panel (ASP). The block contains a ComboBox, +// a custom Button and a TextBlock. Upon choosing one of their installed cBots in the ComboBox, +// the user can click on the Button and backtest the chosen cBot on EURUSD h1. When backtesting +// is finished, the plugin will display its results in the TextBlock. // // ------------------------------------------------------------------------------------------------- @@ -23,29 +23,33 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class BacktestingInPluginsSample : Plugin { - - // Declaring the necessary UI elements - // and the cBot (RobotType) selected in the ComboBox + // Declaring the necessary UI elements and the cBot (RobotType) selected in the ComboBox. private Grid _grid; private ComboBox _cBotsComboBox; private Button _startBacktestingButton; private TextBlock _resultsTextBlock; private RobotType _selectedRobotType; + // This method is triggered when the plugin starts. protected override void OnStart() { - // Initialising and structuring the UI elements + // Initialising and structuring the UI elements into a grid layout. _grid = new Grid(3, 1); _cBotsComboBox = new ComboBox(); + + // Initialising a button for starting the backtesting process. _startBacktestingButton = new Button { BackgroundColor = Color.Green, CornerRadius = new CornerRadius(5), Text = "Start Backtesting", }; + + // Creating a TextBlock to display information. _resultsTextBlock = new TextBlock { HorizontalAlignment = HorizontalAlignment.Center, @@ -53,30 +57,28 @@ protected override void OnStart() Text = "Select a cBot...", }; + // Adding UI elements to the grid. _grid.AddChild(_cBotsComboBox, 0, 0); _grid.AddChild(_startBacktestingButton, 1, 0); _grid.AddChild(_resultsTextBlock, 2, 0); - + // Adding a new block in the ASP with the grid as its content. var block = Asp.SymbolTab.AddBlock("Backtesting Plugin"); - block.Child = _grid; - // Populating the ComboBox with existing cBots + // Populating the ComboBox with existing cBots. PopulateCBotsComboBox(); - // Assigning event handlers to the Button.Click, - // ComboBox.SelectedItemChanged, and Backtesting.Completed events + // Assigning event handlers to the Button.Click, ComboBox.SelectedItemChanged and Backtesting.Completed events. _startBacktestingButton.Click += StartBacktestingButton_Click; _cBotsComboBox.SelectedItemChanged += CBotsComboBox_SelectedItemChanged; Backtesting.Completed += Backtesting_Completed; - } + // Event handler triggered when the backtesting button is clicked. protected void StartBacktestingButton_Click(ButtonClickEventArgs obj) { - - // Initialising and configuring the backtesting settings + // Initialising and configuring the backtesting settings. var backtestingSettings = new BacktestingSettings { DataMode = BacktestingDataMode.M1, @@ -85,48 +87,48 @@ protected void StartBacktestingButton_Click(ButtonClickEventArgs obj) Balance = 10000, }; - // Starting backtesting on EURUSD h1 + // Starting backtesting on EURUSD h1. Backtesting.Start(_selectedRobotType, "EURUSD", TimeFrame.Hour, backtestingSettings); - // Disabling other controls and changing - // the text inside the TextBlock + // Disabling other controls and changing the text inside the TextBlock. _cBotsComboBox.IsEnabled = false; _startBacktestingButton.IsEnabled = false; _resultsTextBlock.Text = "Backtesting in progress..."; } + // Populating the ComboBox with the names of all installed cBots available in the Algo Registry. protected void PopulateCBotsComboBox() { - // Iterating over the AlgoRegistry and - // getting the names of all installed cBots + // Iterating over the Algo Registry and getting the names of all installed cBots. foreach (var robotType in AlgoRegistry.OfType()) { _cBotsComboBox.AddItem(robotType.Name); } } + // Event handler triggered when backtesting is completed. protected void Backtesting_Completed(BacktestingCompletedEventArgs obj) { - // Attaining the JSON results of backtesting + // Attaining the JSON results of backtesting. string jsonResults = obj.JsonReport; - // Converting the JSON string into a JsonNode + // Converting the JSON string into a JsonNode. JsonNode resultsNode = JsonNode.Parse(jsonResults); - // Attaining the ROI and net profit from backtesting results + // Attaining the ROI and net profit from backtesting results. _resultsTextBlock.Text = $"ROI: {resultsNode["main"]["roi"]}\nNet Profit: {resultsNode["main"]["netProfit"]}"; - // Re-enabling controls after backteting is finished + // Re-enabling controls after backteting is finished. _cBotsComboBox.IsEnabled = true; _startBacktestingButton.IsEnabled = true; } + // Event handler triggered when the ComboBox selection changes. protected void CBotsComboBox_SelectedItemChanged(ComboBoxSelectedItemChangedEventArgs obj) { - // Updading the variable to always contain - // the cBto selected in the ComboBox + // Updading the variable to always contain the cBot selected in the ComboBox. _selectedRobotType = AlgoRegistry.Get(obj.SelectedItem) as RobotType; } } -} \ No newline at end of file +} diff --git a/Plugins/ChartId Sample/ChartId Sample/ChartId Sample.cs b/Plugins/ChartId Sample/ChartId Sample/ChartId Sample.cs index 58613d0..ead3e4c 100644 --- a/Plugins/ChartId Sample/ChartId Sample/ChartId Sample.cs +++ b/Plugins/ChartId Sample/ChartId Sample/ChartId Sample.cs @@ -5,8 +5,9 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// Using ChartManager, the plugin reacts to new charts being added or removed. On every such action, -// the plugin prints a message with the log containing the Id of the Chart that has just been added or removed. +// Using ChartManager, the plugin reacts to new charts being added or removed. On every +// such action, the plugin prints a message with the log containing the Id of the chart +// that has just been added or removed. // // ------------------------------------------------------------------------------------------------- @@ -18,27 +19,26 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class ChartIdSample : Plugin { protected override void OnStart() { - // Assigning custom handlers for the ChartManager.FramesAdded - // and ChartManager.FramesRemoved events + // Assigning custom handlers for the ChartManager.FramesAdded and ChartManager.FramesRemoved events. ChartManager.FramesAdded += ChartManager_FramesAdded; ChartManager.FramesRemoved += ChartManager_FramesRemoved; } private void ChartManager_FramesRemoved(FramesRemovedEventArgs obj) { - // Iterating over a collection of removed Frames + // Iterating over a collection of removed frames. foreach(var frame in obj.RemovedFrames) { - // Checking if a removed Frame is a ChartFrame + // Checking if a removed frame is a ChartFrame. if (frame is ChartFrame) { - // Downcasting the Frame to a ChartFrame - // and printing the message + // Downcasting the frame to a ChartFrame and printing the message. var chartFrame = frame as ChartFrame; Print($"Chart {chartFrame.Chart.Id} removed"); } @@ -47,14 +47,13 @@ private void ChartManager_FramesRemoved(FramesRemovedEventArgs obj) private void ChartManager_FramesAdded(FramesAddedEventArgs obj) { - // Iterating over a collection of added Frames + // Iterating over a collection of added frames. foreach(var frame in obj.AddedFrames) { - // Checking if an added Frame is a ChartFrame + // Checking if an added frame is a ChartFrame. if (frame is ChartFrame) { - // Downcasting the Frame to a ChartFrame - // and printing the message + // Downcasting the frame to a ChartFrame and printing the message. var chartFrame = frame as ChartFrame; Print($"Chart {chartFrame.Chart.Id} added"); } @@ -63,4 +62,4 @@ private void ChartManager_FramesAdded(FramesAddedEventArgs obj) } -} \ No newline at end of file +} diff --git a/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs b/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs index 8e28585..ead3e4c 100644 --- a/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs +++ b/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs @@ -5,42 +5,61 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds an active symbol panel tab, and uses ChartIndicators API to show stats about -// active chart indicators and lets you add and remove indicators to active chart. +// Using ChartManager, the plugin reacts to new charts being added or removed. On every +// such action, the plugin prints a message with the log containing the Id of the chart +// that has just been added or removed. // // ------------------------------------------------------------------------------------------------- +using System; using cAlgo.API; +using cAlgo.API.Collections; +using cAlgo.API.Indicators; +using cAlgo.API.Internals; namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] - public class ChartIndicatorsSample : Plugin + public class ChartIdSample : Plugin { - private ChartIndicatorsControl _chartIndicatorsControl; - protected override void OnStart() { - var aspTab = Asp.AddTab("Chart Indicators"); - - _chartIndicatorsControl = new ChartIndicatorsControl(AlgoRegistry) - { - VerticalAlignment = VerticalAlignment.Top - }; - - aspTab.Child = _chartIndicatorsControl; - - SetControlChart(); - - ChartManager.ActiveFrameChanged += _ => SetControlChart(); + // Assigning custom handlers for the ChartManager.FramesAdded and ChartManager.FramesRemoved events. + ChartManager.FramesAdded += ChartManager_FramesAdded; + ChartManager.FramesRemoved += ChartManager_FramesRemoved; } - private void SetControlChart() + private void ChartManager_FramesRemoved(FramesRemovedEventArgs obj) { - if (ChartManager.ActiveFrame is not ChartFrame chartFrame) - return; + // Iterating over a collection of removed frames. + foreach(var frame in obj.RemovedFrames) + { + // Checking if a removed frame is a ChartFrame. + if (frame is ChartFrame) + { + // Downcasting the frame to a ChartFrame and printing the message. + var chartFrame = frame as ChartFrame; + Print($"Chart {chartFrame.Chart.Id} removed"); + } + } + } - _chartIndicatorsControl.Chart = chartFrame.Chart; + private void ChartManager_FramesAdded(FramesAddedEventArgs obj) + { + // Iterating over a collection of added frames. + foreach(var frame in obj.AddedFrames) + { + // Checking if an added frame is a ChartFrame. + if (frame is ChartFrame) + { + // Downcasting the frame to a ChartFrame and printing the message. + var chartFrame = frame as ChartFrame; + Print($"Chart {chartFrame.Chart.Id} added"); + } + } } + + } -} \ No newline at end of file +} diff --git a/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicatorsControl.cs b/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicatorsControl.cs index 2b44eed..454a781 100644 --- a/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicatorsControl.cs +++ b/Plugins/ChartIndicators Sample/ChartIndicators Sample/ChartIndicatorsControl.cs @@ -1,42 +1,55 @@ -using System.Linq; +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This code is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// The sample implements a custom control for managing chart indicators using the ChartIndicators API. +// It allows the user to view, add and remove indicators on the active chart. +// +// ------------------------------------------------------------------------------------------------- + +using System.Linq; using cAlgo.API; namespace cAlgo.Plugins; public class ChartIndicatorsControl: CustomControl { - private readonly AlgoRegistry _algoRegistry; + private readonly AlgoRegistry _algoRegistry; // Reference to the Algo Registry for accessing algorithm data. - private const string FontFamily = "Calibri"; + private const string FontFamily = "Calibri"; // Specify the font family for UI elements. - private readonly Grid _panel; - private readonly TextBlock _indicatorsCountTextBlock; - private readonly TextBlock _indicatorsTextBlock; - private readonly ComboBox _indicatorTypesComboBox; - private readonly Button _addIndicatorButton; - private readonly Button _removeIndicatorsButton; + private readonly Grid _panel; // Represent the main grid layout for arranging UI components. + private readonly TextBlock _indicatorsCountTextBlock; // Count of active indicators on the chart. + private readonly TextBlock _indicatorsTextBlock; // Names of active indicators on the chart. + private readonly ComboBox _indicatorTypesComboBox; // Dropdown to select indicator types to add. + private readonly Button _addIndicatorButton; // Button to add a selected indicator to the chart. + private readonly Button _removeIndicatorsButton; // Button to remove all indicators from the chart. - private Chart _chart; + private Chart _chart; // Hold a reference to the current active chart. + // This method initialises the control, accepting an Algo Registry object for managing available indicators. public ChartIndicatorsControl(AlgoRegistry algoRegistry) { - _algoRegistry = algoRegistry; + _algoRegistry = algoRegistry; // Assign the provided Algo Registry to the field. - _panel = new Grid(6, 2); + _panel = new Grid(6, 2); // Create a grid with 6 rows and 2 columns. - _panel.AddChild(GetTextBlock("Indicators #"), 0, 0); + _panel.AddChild(GetTextBlock("Indicators #"), 0, 0); // Add a label for the indicators count to the grid. - _indicatorsCountTextBlock = GetTextBlock(); + _indicatorsCountTextBlock = GetTextBlock(); // Create a text block for displaying the indicators count. - _panel.AddChild(_indicatorsCountTextBlock, 0, 1); + _panel.AddChild(_indicatorsCountTextBlock, 0, 1); // Add the indicators count text block to the grid. - _panel.AddChild(GetTextBlock("Indicators"), 1, 0); + _panel.AddChild(GetTextBlock("Indicators"), 1, 0); // Add a label for the indicators list to the grid. - _indicatorsTextBlock = GetTextBlock(); + _indicatorsTextBlock = GetTextBlock(); // Create a text block for displaying the indicators list. - _panel.AddChild(_indicatorsTextBlock, 1, 1); + _panel.AddChild(_indicatorsTextBlock, 1, 1); // Add the indicators list text block to the grid. - _indicatorTypesComboBox = new ComboBox + _indicatorTypesComboBox = new ComboBox // Initialise the combo box for selecting indicator types. { Margin = 3, FontSize = 16, @@ -44,9 +57,9 @@ public ChartIndicatorsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - PopulateTypes(); + PopulateTypes(); // Populate the combo box with available indicator types. - _addIndicatorButton = new Button + _addIndicatorButton = new Button // Initialise the button to add an indicator. { Text = "Add Indicator", Margin = 3, @@ -55,16 +68,16 @@ public ChartIndicatorsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _addIndicatorButton.Click += OnAddIndicatorButtonClick; + _addIndicatorButton.Click += OnAddIndicatorButtonClick; // Assign the click event handler for the add button. - var addIndicatorPanel = new StackPanel {Orientation = Orientation.Horizontal}; + var addIndicatorPanel = new StackPanel {Orientation = Orientation.Horizontal}; // Create a horizontal panel for the combo box and button. - addIndicatorPanel.AddChild(_indicatorTypesComboBox); - addIndicatorPanel.AddChild(_addIndicatorButton); + addIndicatorPanel.AddChild(_indicatorTypesComboBox); // Add the combo box to the panel. + addIndicatorPanel.AddChild(_addIndicatorButton); // Add the add button to the panel. - _panel.AddChild(addIndicatorPanel, 2, 0, 1, 2); + _panel.AddChild(addIndicatorPanel, 2, 0, 1, 2); // Add the horizontal panel to the grid. - _removeIndicatorsButton = new Button + _removeIndicatorsButton = new Button // Initialise the button to remove all indicators. { Text = "Remove All Indicators", Margin = 3, @@ -73,85 +86,94 @@ public ChartIndicatorsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _removeIndicatorsButton.Click += OnRemoveIndicatorsButtonClick; + _removeIndicatorsButton.Click += OnRemoveIndicatorsButtonClick; // Assign the click event handler for the remove button. - _panel.AddChild(_removeIndicatorsButton, 3, 0, 1, 2); + _panel.AddChild(_removeIndicatorsButton, 3, 0, 1, 2); // Add the remove button to the grid. - AddChild(_panel); + AddChild(_panel); // Add the main grid to the control. - _algoRegistry.AlgoTypeInstalled += _ => PopulateTypes(); - _algoRegistry.AlgoTypeDeleted += _ => PopulateTypes(); + _algoRegistry.AlgoTypeInstalled += _ => PopulateTypes(); // Update the combo box when a new algorithm is installed. + _algoRegistry.AlgoTypeDeleted += _ => PopulateTypes(); // Update the combo box when an algorithm is deleted. } + // Property to get or set the current chart. public Chart Chart { - get => _chart; + get => _chart; // Return the current chart. set { - if (_chart == value) + if (_chart == value) // Check if the new chart is the same as the current chart. return; - UpdateChart(value); + UpdateChart(value); // Update the chart and event subscriptions. } } + // Update the chart reference and subscriptions. private void UpdateChart(Chart newChart) { - var previousChart = _chart; + var previousChart = _chart; // Store the previous chart. - _chart = newChart; + _chart = newChart; // Update the chart reference. - UpdateStatus(); + UpdateStatus(); // Update the status of indicators on the new chart. - newChart.Indicators.IndicatorAdded += OnIndicatorsAdded; - newChart.Indicators.IndicatorRemoved += OnIndicatorRemoved; + newChart.Indicators.IndicatorAdded += OnIndicatorsAdded; // Subscribe to the indicator added event. + newChart.Indicators.IndicatorRemoved += OnIndicatorRemoved; // Subscribe to the indicator removed event. - if (previousChart is null) + if (previousChart is null) // If there is no previous chart, exit early. return; - previousChart.Indicators.IndicatorAdded -= OnIndicatorsAdded; - previousChart.Indicators.IndicatorRemoved -= OnIndicatorRemoved; + previousChart.Indicators.IndicatorAdded -= OnIndicatorsAdded; // Unsubscribe from the indicator added event for the previous chart. + previousChart.Indicators.IndicatorRemoved -= OnIndicatorRemoved; // Unsubscribe from the indicator removed event for the previous chart. } + // Update the status when an indicator is removed. private void OnIndicatorRemoved(ChartIndicatorRemovedEventArgs obj) => UpdateStatus(); + // Update the status when a new indicator is added. private void OnIndicatorsAdded(ChartIndicatorAddedEventArgs obj) => UpdateStatus(); + // Event handler for removing all indicators. private void OnRemoveIndicatorsButtonClick(ButtonClickEventArgs obj) { - foreach (var chartIndicator in _chart.Indicators) + foreach (var chartIndicator in _chart.Indicators) // Iterate through all indicators on the chart. { - _chart.Indicators.Remove(chartIndicator); + _chart.Indicators.Remove(chartIndicator); // Remove each indicator from the chart. } } + // Event handler for adding a selected indicator. private void OnAddIndicatorButtonClick(ButtonClickEventArgs obj) { if (_algoRegistry.Get(_indicatorTypesComboBox.SelectedItem) is not {AlgoKind: AlgoKind.CustomIndicator or AlgoKind.StandardIndicator} indicatorType) - return; + return; // Exit if the selected item is not a valid indicator type. - _chart.Indicators.Add(indicatorType.Name); + _chart.Indicators.Add(indicatorType.Name); // Add the selected indicator to the chart. } + // Update the displayed status of indicators on the chart. private void UpdateStatus() { - _indicatorsCountTextBlock.Text = _chart.Indicators.Count.ToString(); - _indicatorsTextBlock.Text = string.Join(", ", _chart.Indicators.Select(i => i.Name)); + _indicatorsCountTextBlock.Text = _chart.Indicators.Count.ToString(); // Update the count of indicators. + _indicatorsTextBlock.Text = string.Join(", ", _chart.Indicators.Select(i => i.Name)); // Update the list of indicator names. } + // Populate the combo box with available indicator types. private void PopulateTypes() { - foreach (var algoType in _algoRegistry) + foreach (var algoType in _algoRegistry) // Iterate through all registered algorithms. { if (algoType.AlgoKind is not (AlgoKind.CustomIndicator or AlgoKind.StandardIndicator)) - continue; + continue; // Skip algorithms that are not indicators. - _indicatorTypesComboBox.AddItem(algoType.Name); + _indicatorTypesComboBox.AddItem(algoType.Name); // Add the algorithm name to the combo box. } - _indicatorTypesComboBox.SelectedItem = _algoRegistry.FirstOrDefault(i => i.AlgoKind == AlgoKind.StandardIndicator)?.Name; + _indicatorTypesComboBox.SelectedItem = _algoRegistry.FirstOrDefault(i => i.AlgoKind == AlgoKind.StandardIndicator)?.Name; // Set the default selection to a standard indicator. } + // Helper method to create a styled text block. private TextBlock GetTextBlock(string text = null) => new() { Margin = 3, @@ -160,4 +182,4 @@ private void PopulateTypes() FontFamily = FontFamily, Text = text }; -} \ No newline at end of file +} diff --git a/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobots Sample.cs b/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobots Sample.cs index 2377f85..4be875e 100644 --- a/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobots Sample.cs +++ b/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobots Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds an active symbol panel tab, and uses ChartRobots API to show stats about +// This sample adds an Active Symbol Panel (ASP) tab and uses ChartRobots API to show stats about // active chart cBots and lets you add and remove cBots to active chart. // // ------------------------------------------------------------------------------------------------- @@ -14,33 +14,42 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class ChartRobotsSample : Plugin { private ChartRobotsControl _chartRobotsControl; + // This method is executed when the plugin starts. protected override void OnStart() { - var aspTab = Asp.AddTab("Chart Robots"); + var aspTab = Asp.AddTab("Chart Robots"); // Add a new tab to the ASP named "Chart Robots". + // Create an instance of ChartRobotsControl and set its properties. _chartRobotsControl = new ChartRobotsControl(AlgoRegistry) { - VerticalAlignment = VerticalAlignment.Top + VerticalAlignment = VerticalAlignment.Top // Align the control at the top of the panel. }; + // Assign the created ChartRobotsControl as the child control of the ASP tab. aspTab.Child = _chartRobotsControl; + // Call the method to set the chart for the control. SetControlChart(); + // Subscribe to the ActiveFrameChanged event to update the chart whenever the active chart frame changes. ChartManager.ActiveFrameChanged += _ => SetControlChart(); } + // This method sets the chart for the ChartRobotsControl based on the active chart frame. private void SetControlChart() { + // Check if the active frame is a ChartFrame. if (ChartManager.ActiveFrame is not ChartFrame chartFrame) return; + // Set the chart property of the ChartRobotsControl to the active chart from the ChartFrame. _chartRobotsControl.Chart = chartFrame.Chart; } } -} \ No newline at end of file +} diff --git a/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobotsControl.cs b/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobotsControl.cs index bd63a87..5a67752 100644 --- a/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobotsControl.cs +++ b/Plugins/ChartRobots Sample/ChartRobots Sample/ChartRobotsControl.cs @@ -1,14 +1,27 @@ -using System.Linq; +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This code is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// This sample implements a custom control that interacts with the ChartRobots API to provide +// statistics about cBots on the active chart. It also allows adding, removing, starting and +// stopping cBots directly from the control interface. +// +// ------------------------------------------------------------------------------------------------- + +using System.Linq; using cAlgo.API; namespace cAlgo.Plugins; public class ChartRobotsControl: CustomControl { - private readonly AlgoRegistry _algoRegistry; - - private const string FontFamily = "Calibri"; + private readonly AlgoRegistry _algoRegistry; // Hold a reference to the Algo Registry for accessing algorithm data. + private const string FontFamily = "Calibri"; // Define a constant for the font family used in the UI. + // Define controls for the user interface. private readonly Grid _panel; private readonly TextBlock _robotsCountTextBlock; private readonly TextBlock _robotsTextBlock; @@ -19,32 +32,29 @@ public class ChartRobotsControl: CustomControl private readonly Button _startRobotsButton; private readonly Button _stopRobotsButton; - private Chart _chart; + private Chart _chart; // Represent the active chart associated with this control. + // This method initialises the control and sets up UI components. public ChartRobotsControl(AlgoRegistry algoRegistry) { - _algoRegistry = algoRegistry; + _algoRegistry = algoRegistry; // Store the reference to the algo registry. - _panel = new Grid(7, 2); + _panel = new Grid(7, 2); // Create a grid with 7 rows and 2 columns. - _panel.AddChild(GetTextBlock("Robots #"), 0, 0); + // Add and configure text blocks and buttons to the grid. + _panel.AddChild(GetTextBlock("Robots #"), 0, 0); // Label for robot count. + _robotsCountTextBlock = GetTextBlock(); // Display robot count dynamically. + _panel.AddChild(_robotsCountTextBlock, 0, 1); // Add robot count text block. - _robotsCountTextBlock = GetTextBlock(); + _panel.AddChild(GetTextBlock("Running Robots #"), 1, 0); // Label for running robots. + _runningRobotsCountTextBlock = GetTextBlock(); // Display running robot count. + _panel.AddChild(_runningRobotsCountTextBlock, 1, 1); // Add running robot count text block. - _panel.AddChild(_robotsCountTextBlock, 0, 1); - - _panel.AddChild(GetTextBlock("Running Robots #"), 1, 0); - - _runningRobotsCountTextBlock = GetTextBlock(); - - _panel.AddChild(_runningRobotsCountTextBlock, 1, 1); - - _panel.AddChild(GetTextBlock("Robots"), 2, 0); - - _robotsTextBlock = GetTextBlock(); - - _panel.AddChild(_robotsTextBlock, 2, 1); + _panel.AddChild(GetTextBlock("Robots"), 2, 0); // Label for robot names. + _robotsTextBlock = GetTextBlock(); // Display robot names dynamically. + _panel.AddChild(_robotsTextBlock, 2, 1); // Add robot names text block. + // Initialise and configure the dropdown menu for selecting robot types. _robotTypesComboBox = new ComboBox { Margin = 3, @@ -53,8 +63,9 @@ public ChartRobotsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - PopulateTypes(); + PopulateTypes(); // Populate the dropdown with available robot types. + // Create and configure the button for adding robots. _addRobotButton = new Button { Text = "Add Robot", @@ -64,15 +75,15 @@ public ChartRobotsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _addRobotButton.Click += OnAddRobotButtonClick; - - var addRobotPanel = new StackPanel {Orientation = Orientation.Horizontal}; + _addRobotButton.Click += OnAddRobotButtonClick; // Attach the click event handler to the button. - addRobotPanel.AddChild(_robotTypesComboBox); - addRobotPanel.AddChild(_addRobotButton); - - _panel.AddChild(addRobotPanel, 3, 0, 1, 2); + // Create a horizontal panel to hold the dropdown and the add button. + var addRobotPanel = new StackPanel {Orientation = Orientation.Horizontal}; // Panel for dropdown and button. + addRobotPanel.AddChild(_robotTypesComboBox); // Add dropdown to panel. + addRobotPanel.AddChild(_addRobotButton); // Add button to panel. + _panel.AddChild(addRobotPanel, 3, 0, 1, 2); // Add the panel to the grid. + // Initialise and configure the remove all robots button. _removeRobotsButton = new Button { Text = "Remove All Robots", @@ -82,10 +93,10 @@ public ChartRobotsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _removeRobotsButton.Click += OnRemoveRobotsButtonClick; - - _panel.AddChild(_removeRobotsButton, 4, 0, 1, 2); + _removeRobotsButton.Click += OnRemoveRobotsButtonClick; // Attach click event handler. + _panel.AddChild(_removeRobotsButton, 4, 0, 1, 2); // Add to the grid, spanning two columns. + // Initialize and configure the start all robots buttonю _startRobotsButton = new Button { Text = "Start All Robots", @@ -95,10 +106,10 @@ public ChartRobotsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _startRobotsButton.Click += OnStartRobotsButtonClick; - - _panel.AddChild(_startRobotsButton, 5, 0, 1, 2); + _startRobotsButton.Click += OnStartRobotsButtonClick; // Attach click event handler. + _panel.AddChild(_startRobotsButton, 5, 0, 1, 2); // Add to the grid, spanning two columns. + // Initialise and configure the stop all robots button. _stopRobotsButton = new Button { Text = "Stop All Robots", @@ -108,41 +119,45 @@ public ChartRobotsControl(AlgoRegistry algoRegistry) FontFamily = FontFamily, }; - _stopRobotsButton.Click += OnStopRobotsButtonClick; - - _panel.AddChild(_stopRobotsButton, 6, 0, 1, 2); + _stopRobotsButton.Click += OnStopRobotsButtonClick; // Attach click event handler. + _panel.AddChild(_stopRobotsButton, 6, 0, 1, 2); // Add to the grid, spanning two columns. - AddChild(_panel); + AddChild(_panel); // Add the grid to the control as its root UI element. - _algoRegistry.AlgoTypeInstalled += _ => PopulateTypes(); - _algoRegistry.AlgoTypeDeleted += _ => PopulateTypes(); + // Subscribe to events from the algorithm registry for updating dropdown options. + _algoRegistry.AlgoTypeInstalled += _ => PopulateTypes(); // Update dropdown on new installations. + _algoRegistry.AlgoTypeDeleted += _ => PopulateTypes(); // Update dropdown on deletions. } + // Property to get or set the current chart. public Chart Chart { - get => _chart; + get => _chart; // Return the current chart. set { - if (_chart == value) + if (_chart == value) // Check if the new chart is the same as the current chart. return; - UpdateChart(value); + UpdateChart(value); // Update the chart and event subscriptions. } } + // Update the control with a new chart instance, subscribing to events and updating the UI to reflect the new chart state. private void UpdateChart(Chart newChart) { - var previousChart = _chart; + var previousChart = _chart; // Store the current chart before updating, to manage event unsubscriptions. - _chart = newChart; + _chart = newChart; // Update the control with the new chart. - UpdateStatus(); + UpdateStatus(); // Refresh the UI to display the status of robots in the new chart. + // Subscribe to various robot-related events for the new chart. newChart.Robots.RobotAdded += OnRobotsAdded; newChart.Robots.RobotRemoved += OnRobotRemoved; newChart.Robots.RobotStarted += OnRobotStarted; newChart.Robots.RobotStopped += OnRobotStopped; + // If there is a previous chart, unsubscribe from its events to prevent memory leaks. if (previousChart is null) return; @@ -152,72 +167,84 @@ private void UpdateChart(Chart newChart) previousChart.Robots.RobotStopped -= OnRobotStopped; } - private void OnRobotRemoved(ChartRobotRemovedEventArgs obj) => UpdateStatus(); + private void OnRobotRemoved(ChartRobotRemovedEventArgs obj) => UpdateStatus(); // Update status when a robot is removed. - private void OnRobotsAdded(ChartRobotAddedEventArgs obj) => UpdateStatus(); + private void OnRobotsAdded(ChartRobotAddedEventArgs obj) => UpdateStatus(); // Update status when a robot is added. - private void OnRobotStopped(ChartRobotStoppedEventArgs obj) => UpdateStatus(); + private void OnRobotStopped(ChartRobotStoppedEventArgs obj) => UpdateStatus(); // Update status when a robot stops. - private void OnRobotStarted(ChartRobotStartedEventArgs obj) => UpdateStatus(); + private void OnRobotStarted(ChartRobotStartedEventArgs obj) => UpdateStatus(); // Update status when a robot starts. + // Remove all robots from the chart when the "Remove All Robots" button is clicked. private void OnRemoveRobotsButtonClick(ButtonClickEventArgs obj) { foreach (var chartRobot in _chart.Robots) { - _chart.Robots.Remove(chartRobot); + _chart.Robots.Remove(chartRobot); // Remove each robot from the chart. } } + // Add a new robot to the chart when the "Add Robot" button is clicked. private void OnAddRobotButtonClick(ButtonClickEventArgs obj) { + // Exit if no valid robot type is selected. if (_algoRegistry.Get(_robotTypesComboBox.SelectedItem) is not {AlgoKind: AlgoKind.Robot} robotType) return; - _chart.Robots.Add(robotType.Name); + _chart.Robots.Add(robotType.Name); // Add the selected robot to the chart. } + // Update the status display with the current counts and names of robots on the chart. private void UpdateStatus() { - _robotsCountTextBlock.Text = _chart.Robots.Count.ToString(); - _runningRobotsCountTextBlock.Text = _chart.Robots.Count(r => r.State == RobotState.Running).ToString(); - _robotsTextBlock.Text = string.Join(", ", _chart.Robots.Select(r => r.Name)); + _robotsCountTextBlock.Text = _chart.Robots.Count.ToString(); // Display the total number of robots. + _runningRobotsCountTextBlock.Text = _chart.Robots.Count(r => r.State == RobotState.Running).ToString(); // Display the count of running robots. + _robotsTextBlock.Text = string.Join(", ", _chart.Robots.Select(r => r.Name)); // Display the names of robots on the chart. } + // Populate the dropdown list with available robot types from the algorithm registry. private void PopulateTypes() { foreach (var algoType in _algoRegistry) { + // Only include robots in the dropdown. if (algoType.AlgoKind != AlgoKind.Robot) continue; - _robotTypesComboBox.AddItem(algoType.Name); + _robotTypesComboBox.AddItem(algoType.Name); // Add each robot type to the dropdown. } + // Set the default selected item in the dropdown to the first robot type found in the registry. _robotTypesComboBox.SelectedItem = _algoRegistry.FirstOrDefault(i => i.AlgoKind == AlgoKind.Robot)?.Name; } + // Stop all running robots on the chart when the "Stop All Robots" button is clicked. private void OnStopRobotsButtonClick(ButtonClickEventArgs obj) { foreach (var chartRobot in _chart.Robots) { + // Skip robots that are already stopped or stopping. if (chartRobot.State is (RobotState.Stopped or RobotState.Stopping)) continue; - chartRobot.Stop(); + chartRobot.Stop(); // Stop the robot. } } + // Start all stopped or restarting robots on the chart when the "Start All Robots" button is clicked. private void OnStartRobotsButtonClick(ButtonClickEventArgs obj) { foreach (var chartRobot in _chart.Robots) { + // Skip robots that are already running or restarting. if (chartRobot.State is (RobotState.Running or RobotState.Restarting)) continue; - chartRobot.Start(); + chartRobot.Start(); // Start the robot. } } + // Define a method to create a text block with specific settings. private TextBlock GetTextBlock(string text = null) => new() { Margin = 3, @@ -226,4 +253,4 @@ private void OnStartRobotsButtonClick(ButtonClickEventArgs obj) FontFamily = FontFamily, Text = text }; -} \ No newline at end of file +} diff --git a/Plugins/Commands Sample/Commands Sample/Commands Sample.cs b/Plugins/Commands Sample/Commands Sample/Commands Sample.cs index c726d1a..3aafdc1 100644 --- a/Plugins/Commands Sample/Commands Sample/Commands Sample.cs +++ b/Plugins/Commands Sample/Commands Sample/Commands Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds several commands to chart container toolbar, all SVG icons are stored inside SvgIcons +// The sample adds several commands to chart container toolbar, all SVG icons are stored inside SvgIcons // static class. // // ------------------------------------------------------------------------------------------------- @@ -15,34 +15,39 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class CommandsSample : Plugin { + // This method is triggered when the plugin starts. protected override void OnStart() { - var commandWithoutResultIcon = new SvgIcon(SvgIcons.GrowthIcon); - var commandWithoutResult = Commands.Add(CommandType.ChartContainerToolbar, CommandWithoutResultCallback, commandWithoutResultIcon); - commandWithoutResult.ToolTip = "Without Result"; + var commandWithoutResultIcon = new SvgIcon(SvgIcons.GrowthIcon); // Create a new SvgIcon for the first command using an icon from SvgIcons class. + var commandWithoutResult = Commands.Add(CommandType.ChartContainerToolbar, CommandWithoutResultCallback, commandWithoutResultIcon); // Add a command to the chart container toolbar with an icon and callback. + commandWithoutResult.ToolTip = "Without Result"; // Set the tooltip for the first command. - var commandWithResultIcon = new SvgIcon(SvgIcons.InnovationCreativityIcon); - var commandWithResult = Commands.Add(CommandType.ChartContainerToolbar, CommandWithResultCallback, commandWithResultIcon); - commandWithResult.ToolTip = "With Result"; + var commandWithResultIcon = new SvgIcon(SvgIcons.InnovationCreativityIcon); // Create a new SvgIcon for the second command using an icon from SvgIcons class. + var commandWithResult = Commands.Add(CommandType.ChartContainerToolbar, CommandWithResultCallback, commandWithResultIcon); // Add a command to the chart container toolbar with an icon and callback. + commandWithResult.ToolTip = "With Result"; // Set the tooltip for the second command. - var disabledCommandIcon = new SvgIcon(SvgIcons.MotorPumpColorIcon); - var disabledCommand = Commands.Add(CommandType.ChartContainerToolbar, args => throw new InvalidOperationException("Shouldn't be executed!"), disabledCommandIcon); + var disabledCommandIcon = new SvgIcon(SvgIcons.MotorPumpColorIcon); // Create a new SvgIcon for the disabled command using an icon from SvgIcons class. + var disabledCommand = Commands.Add(CommandType.ChartContainerToolbar, args => throw new InvalidOperationException("Shouldn't be executed!"), disabledCommandIcon); // Add a disabled command to the chart container toolbar that throws an exception if triggered. - disabledCommand.ToolTip = "Disabled Command"; - disabledCommand.IsEnabled = false; + disabledCommand.ToolTip = "Disabled Command"; // Set the tooltip for the disabled command. + disabledCommand.IsEnabled = false; // Disable the command so it cannot be executed. - var drawOnActiveChartCommand = Commands.Add(CommandType.ChartContainerToolbar, DrawOnActiveChart); - drawOnActiveChartCommand.ToolTip = "Draws Text on active chart"; + var drawOnActiveChartCommand = Commands.Add(CommandType.ChartContainerToolbar, DrawOnActiveChart); // Add a command that draws text on the active chart. + drawOnActiveChartCommand.ToolTip = "Draws Text on active chart"; // Set the tooltip for the drawing command. } + // Callback method for the draw command. private void DrawOnActiveChart(CommandArgs obj) { + // Check if the active chart frame is valid and retrieving the chart. if (ChartManager.ActiveFrame is not ChartFrame {Chart: var chart}) - return; + return; // If no valid chart, exit the method. + // Draw static text on the active chart at the center. chart.DrawStaticText( "CommandText", "Command drawing", @@ -51,25 +56,30 @@ private void DrawOnActiveChart(CommandArgs obj) Application.DrawingColor); } + // Callback method for the first command. private void CommandWithoutResultCallback(CommandArgs commandArgs) { + // Check if the context is a valid ChartContainer. if (commandArgs.Context is not ChartContainer chartContainer) - return; + return; // If not a valid chart container, exit the method. + // Showing a message box with details about the chart container. MessageBox.Show( $"Command was executed for chart container {chartContainer.Id} which has {chartContainer.Count} charts and has {chartContainer.Mode} mode.", "Command Without Result"); } + // Callback method for the second command. private CommandResult CommandWithResultCallback(CommandArgs commandArgs) { - var webView = new WebView {Width = 300, Height = 350}; + var webView = new WebView {Width = 300, Height = 350}; // Create a WebView to display a webpage in the command result. - webView.Loaded += OnWebViewLoaded; + webView.Loaded += OnWebViewLoaded; // Subscribe to the WebView Loaded event to handle when the page finishes loading. - return new CommandResult(webView); + return new CommandResult(webView); // Return the WebView as the command result. } - private void OnWebViewLoaded(WebViewLoadedEventArgs obj) => obj.WebView.NavigateAsync("https://ctrader.com/"); + // Event handler for when the WebView is loaded. + private void OnWebViewLoaded(WebViewLoadedEventArgs obj) => obj.WebView.NavigateAsync("https://ctrader.com/"); // Navigate to the cTrader website once the WebView has finished loading. } -} \ No newline at end of file +} diff --git a/Plugins/CoordinatesConversion Sample/CoordinatesConversion Sample/CoordinatesConversion Sample.cs b/Plugins/CoordinatesConversion Sample/CoordinatesConversion Sample/CoordinatesConversion Sample.cs index 21d215d..f6d1ed1 100644 --- a/Plugins/CoordinatesConversion Sample/CoordinatesConversion Sample/CoordinatesConversion Sample.cs +++ b/Plugins/CoordinatesConversion Sample/CoordinatesConversion Sample/CoordinatesConversion Sample.cs @@ -5,10 +5,10 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a custom tab into the TradeWatch panel. The plugin also opens an H1 chart +// The sample adds a custom tab into the Trade Watch panel. The plugin also opens an h1 chart // for EURUSD on start. Whenever the user hovers the mouse cursor over the chart, the TextBlock -// inside the new TradeWatchTab displays HLOC information about the bar over which the cursor is -// currently hovering. This is achieved via the XToBarIndex() method. +// inside the new Trade Watch tab displays HLOC information about the bar over which the cursor is +// currently hovering. This is achieved via the XToBarIndex method. // // ------------------------------------------------------------------------------------------------- @@ -20,20 +20,19 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class CoordinatesConversionSample : Plugin { - // Creating a variable to store the bar index - // and the chart; also declaring the TextBlock + // Creating a variable to store the bar index and the chart; also declaring the TextBlock. private int _hoverIndex; private TextBlock _priceInfoTextBlock; private Chart _eurusdChart; protected override void OnStart() { - // Initialising the TextBlock and setting - // its parameters + // Initialising the TextBlock and setting its parameters. _priceInfoTextBlock = new TextBlock { TextAlignment = TextAlignment.Center, @@ -45,16 +44,15 @@ protected override void OnStart() }; - // Adding a new tab into TradeWatch and - // setting the TextBlock as its child + // Adding a new tab into Trade Watch and setting the TextBlock as its child. var tradeWatchTab = TradeWatch.AddTab("EURUSD Hover Price"); tradeWatchTab.Child = _priceInfoTextBlock; - // Opening a new ChartFrame and storing its Chart + // Opening a new ChartFrame and storing its Chart. var eurusdChartFrame = ChartManager.AddChartFrame("EURUSD", TimeFrame.Hour); _eurusdChart = eurusdChartFrame.Chart; - // Handling mouse movement events + // Handling mouse movement events. _eurusdChart.MouseEnter += EurusdChartOnMouseHover; _eurusdChart.MouseLeave += EurusdChartOnMouseLeave; _eurusdChart.MouseMove += EurusdChartOnMouseHover; @@ -62,12 +60,11 @@ protected override void OnStart() private void EurusdChartOnMouseHover(ChartMouseEventArgs obj) { - // Attaining the Bars for EURUSD and determining - // the bar index over which the mouse cursor is hovering + // Attaining the Bars for EURUSD and determining the bar index over which the mouse cursor is hovering. var bars = MarketData.GetBars(TimeFrame.Hour, "EURUSD"); _hoverIndex = Convert.ToInt32(_eurusdChart.XToBarIndex(obj.MouseX)); - // Updating the text inside the TextBlock + // Updating the text inside the TextBlock. _priceInfoTextBlock.Text = @$"EURUSD Price at {_hoverIndex}: {bars[_hoverIndex].OpenTime} {bars[_hoverIndex].Open} @@ -76,13 +73,11 @@ private void EurusdChartOnMouseHover(ChartMouseEventArgs obj) {bars[_hoverIndex].Low}"; } - // Stop s private void EurusdChartOnMouseLeave(ChartMouseEventArgs obj) { - // Displaying special text when the mouse cursor - // leaves the chart + // Displaying special text when the mouse cursor leaves the chart. _priceInfoTextBlock.Text = "EURUSD Price: Unavavailable"; } } -} \ No newline at end of file +} diff --git a/Plugins/Custom Frame Sample/Custom Frame Sample/Custom Frame Sample.cs b/Plugins/Custom Frame Sample/Custom Frame Sample/Custom Frame Sample.cs index 737caec..a999eaa 100644 --- a/Plugins/Custom Frame Sample/Custom Frame Sample/Custom Frame Sample.cs +++ b/Plugins/Custom Frame Sample/Custom Frame Sample/Custom Frame Sample.cs @@ -5,7 +5,8 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a ASP block that you can use to interact with custom frame API. +// The sample adds Active Symbol Panel (ASP) block that you can use to interact with custom frame API. +// It provides functionality to add, remove, attach and detach custom frames through buttons in an ASP block. // // ------------------------------------------------------------------------------------------------- @@ -14,70 +15,77 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class CustomFrameSample : Plugin { + // This method is executed when the plugin starts. protected override void OnStart() { - var aspBlock = Asp.SymbolTab.AddBlock("Custom Frame Sample"); + var aspBlock = Asp.SymbolTab.AddBlock("Custom Frame Sample"); // Adding a new block to the ASP with the title "Custom Frame Sample". - var panel = new StackPanel(); + var panel = new StackPanel(); // Creating a new StackPanel to hold the buttons for managing custom frames. + // Create and set up the "Add Custom Frame" button. var addCustomFrameButton = new Button {Text = "Add Custom Frame", Margin = 5}; - - addCustomFrameButton.Click += OnAddCustomFrameButtonClick; - - panel.AddChild(addCustomFrameButton); + addCustomFrameButton.Click += OnAddCustomFrameButtonClick; // Add click event handler. + panel.AddChild(addCustomFrameButton); // Add the button to the panel. + // Create and set up the "Remove Custom Frame" button. var removeCustomFrameButton = new Button {Text = "Remove Custom Frame", Margin = 5}; - removeCustomFrameButton.Click += OnRemoveCustomFrameButtonClick; - panel.AddChild(removeCustomFrameButton); + // Create and set up the "Detach Custom Frame" button. var detachCustomFrameButton = new Button {Text = "Detach Custom Frame", Margin = 5}; - - detachCustomFrameButton.Click += OnDetachCustomFrameButtonClick; - + detachCustomFrameButton.Click += OnDetachCustomFrameButtonClick; panel.AddChild(detachCustomFrameButton); - - var attachCustomFrameButton = new Button {Text = "Attach Custom Frame", Margin = 5}; - attachCustomFrameButton.Click += OnAttachCustomFrameButtonClick; - + // Create and set up the "Attach Custom Frame" button. + var attachCustomFrameButton = new Button {Text = "Attach Custom Frame", Margin = 5}; + attachCustomFrameButton.Click += OnAttachCustomFrameButtonClick; panel.AddChild(attachCustomFrameButton); + // Assign the panel with all buttons to the ASP block. aspBlock.Child = panel; } + // This method handles the click event for attaching a custom frame. private void OnAttachCustomFrameButtonClick(ButtonClickEventArgs obj) { + // Search for a detached custom frame and attach it if found. if (ChartManager.OfType().FirstOrDefault(c => !c.IsAttached) is not {} customFrame) return; - customFrame.Attach(); + customFrame.Attach(); // Attach the found custom frame. } + // This method handles the click event for detaching a custom frame. private void OnDetachCustomFrameButtonClick(ButtonClickEventArgs obj) { + // Search for an attached custom frame and detach it if found. if (ChartManager.OfType().FirstOrDefault(c => c.IsAttached) is not {} customFrame) return; - customFrame.Detach(); + customFrame.Detach(); // Detach the found custom frame. } + // This method handles the click event for removing a custom frame. private void OnRemoveCustomFrameButtonClick(ButtonClickEventArgs obj) { + // Search for a custom frame and remov it if found. if (ChartManager.OfType().FirstOrDefault() is not {} customFrame) return; - ChartManager.RemoveFrame(customFrame.Id); + ChartManager.RemoveFrame(customFrame.Id); // Remove the custom frame from the chart. } + // This method handles the click event for adding a custom frame. private void OnAddCustomFrameButtonClick(ButtonClickEventArgs obj) { - var customFrame = ChartManager.AddCustomFrame("Custom Frame"); + var customFrame = ChartManager.AddCustomFrame("Custom Frame"); // Add a new custom frame to the chart. + // Create a text block and assign it as the child of the custom frame. customFrame.Child = new TextBlock { Text = $"Custom Frame {customFrame.Id} Child Control", @@ -87,4 +95,4 @@ private void OnAddCustomFrameButtonClick(ButtonClickEventArgs obj) }; } } -} \ No newline at end of file +} diff --git a/Plugins/Custom Toolbar Button/Custom Toolbar Button/Custom Toolbar Button.cs b/Plugins/Custom Toolbar Button/Custom Toolbar Button/Custom Toolbar Button.cs index 10e3116..7f213e7 100644 --- a/Plugins/Custom Toolbar Button/Custom Toolbar Button/Custom Toolbar Button.cs +++ b/Plugins/Custom Toolbar Button/Custom Toolbar Button/Custom Toolbar Button.cs @@ -2,11 +2,11 @@ // // This code is a cTrader Algo API example. // -// The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. +// The code is provided as a sample only and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. // -// This example plugin adds a new button with a pop-up menu to the Chart Toolbar, featuring a 'Close All Positions' button that closes open positions when clicked. -// -// For a detailed tutorial on creating this plugin, watch the video at: [to:do] +// The sample adds a new button with a pop-up menu to the chart toolbar, featuring +// a 'Close All Positions' button that closes open positions when clicked. // // ------------------------------------------------------------------------------------------------- @@ -18,58 +18,69 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class CustomToolbarButton : Plugin { + // This method is executed when the plugin starts. protected override void OnStart() { var icon = new SvgIcon(@""); + "); // Define an icon to be used in the toolbar. + // Add a command to the chart toolbar to open positions. var command = Commands.Add(CommandType.ChartContainerToolbar, OpenPositions, icon); command.ToolTip = "Open Positions"; + // Add another command for the 'Close All Positions' functionality. Commands.Add(CommandType.ChartContainerToolbar, CloseAllPositions, icon); } + // This method creates a pop-up menu containing a 'Close All Positions' button to close all open positions. private CommandResult CloseAllPositions (CommandArgs args) { + // Create a button style for uniform appearance. var buttonStyle = new Style(); + buttonStyle.Set(ControlProperty.Margin, new Thickness(0, 5, 0, 0)); // Set button margins. + buttonStyle.Set(ControlProperty.Width, 150); // Set button width. - buttonStyle.Set(ControlProperty.Margin, new Thickness(0, 5, 0, 0)); - buttonStyle.Set(ControlProperty.Width, 150); - + // Define the 'Close All Positions' button. var closePositionsButton = new Button { Text = "Close All Positions", Style = buttonStyle }; + // Handle button click to close all open positions. closePositionsButton.Click += args => { + // Iterate through all positions. foreach (var position in Positions) { - position.Close(); + position.Close(); // Close each position. } }; + // Create a stack panel to contain the button. var stackPanel = new StackPanel(); - stackPanel.AddChild(closePositionsButton); + stackPanel.AddChild(closePositionsButton); // Add the button to the panel. + // Return the panel as the result for the command. return new CommandResult(stackPanel); } + // This method opens predefined buy positions for selected currency pairs. private void OpenPositions(CommandArgs args) { - ExecuteMarketOrder(TradeType.Buy, "EURUSD", 1000); - ExecuteMarketOrder(TradeType.Buy, "USDJPY", 1000); - ExecuteMarketOrder(TradeType.Buy, "EURGBP", 1000); + ExecuteMarketOrder(TradeType.Buy, "EURUSD", 1000); // Open a buy position for EUR/USD with a volume of 1000. + ExecuteMarketOrder(TradeType.Buy, "USDJPY", 1000); // Open a buy position for USD/JPY with a volume of 1000. + ExecuteMarketOrder(TradeType.Buy, "EURGBP", 1000); // Open a buy position for EUR/GBP with a volume of 1000. } protected override void OnStop() { - // Handle Plugin stop here + // Handle Plugin stop here. } } -} \ No newline at end of file +} diff --git a/Plugins/Custom Window Plugin/Custom Window Plugin/Custom Window Plugin.cs b/Plugins/Custom Window Plugin/Custom Window Plugin/Custom Window Plugin.cs index dd45cba..99cfb19 100644 --- a/Plugins/Custom Window Plugin/Custom Window Plugin/Custom Window Plugin.cs +++ b/Plugins/Custom Window Plugin/Custom Window Plugin/Custom Window Plugin.cs @@ -2,15 +2,14 @@ // // This code is a cTrader Algo API example. // -// The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. +// The code is provided as a sample only and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. // -// This example plugin adds a new custom window containing a 'Add Take Profit' button, which adds Take Profit to open positions when clicked. -// -// For a detailed tutorial on creating this plugin, watch the video at: [to:do] +// The sample adds a new custom window containing a 'Add Take Profit' button, +// which adds take profit to open positions when clicked. // // ------------------------------------------------------------------------------------------------- - using System; using cAlgo.API; using cAlgo.API.Collections; @@ -19,15 +18,18 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class CustomWindowPlugin : Plugin { - private Button _buttonAddTakeProfit; - private Window _window; + private Button _buttonAddTakeProfit; // Define button control for adding take profit. + private Window _window; // Define custom window to display the button. + // This method is executed when the plugin starts. protected override void OnStart() { + // Initialise the 'Add Take Profit' button with properties. _buttonAddTakeProfit = new Button { BackgroundColor = Color.SeaGreen, @@ -35,8 +37,10 @@ protected override void OnStart() Text = "Add Take Profit" }; + // Attach the click event handler for the button. _buttonAddTakeProfit.Click += _buttonAddTakeProfit_Click; + // Initialise the custom window with properties. _window = new Window { Height = 150, @@ -44,24 +48,30 @@ protected override void OnStart() Padding = new Thickness(5, 10, 10, 5) }; + // Add the button as the child control of the window. _window.Child = _buttonAddTakeProfit; + + // Display the custom window. _window.Show(); } + // This method handles the button click event. private void _buttonAddTakeProfit_Click(ButtonClickEventArgs args) { + // Loop through all open positions. foreach (var position in Positions) { + // Check if the position has no take profit set. if (position.TakeProfit is null) { - position.ModifyTakeProfitPips(20); + position.ModifyTakeProfitPips(20); // Modify the position to add a take profit of 20 pips. } } } protected override void OnStop() { - // Handle Plugin stop here + // Handle Plugin stop here. } } -} \ No newline at end of file +} diff --git a/Plugins/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs b/Plugins/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs index 9f60057..6d6eec9 100644 --- a/Plugins/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs +++ b/Plugins/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample uses the Chart.DisplaySettings.IndicatorTitles property +// The sample uses the Chart.DisplaySettings.IndicatorTitles property // and prints its value on initialisation and whenever the user changes // the chart display options. This is done by first opening a new chart // for EURUSD and then assigning a custom event handler for the DisplaySettingsChanged @@ -21,27 +21,29 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class IndicatorTitlesSample : Plugin { - // Declaring a new Chart variable + // Declaring a new chart variable. Chart _newChart; + // This method is executed when the plugin starts. protected override void OnStart() { - // Creating a new Chart for EURUSD on plugin start + // Creating a new chart for EURUSD on plugin start. _newChart = ChartManager.AddChartFrame("EURUSD", TimeFrame.Daily).Chart; - // Adding a custom event handler for the DisplaySettingsChanged event + // Adding a custom event handler for the DisplaySettingsChanged event. _newChart.DisplaySettingsChanged += OnDisplaySettingsChanged; Print(_newChart.DisplaySettings.IndicatorTitles); } - // Defining the custom event handler for the DisplaySettingsChanged event + // Defining the custom event handler for the DisplaySettingsChanged event. protected void OnDisplaySettingsChanged(ChartDisplaySettingsEventArgs args) { Print(_newChart.DisplaySettings.IndicatorTitles); } } -} \ No newline at end of file +} diff --git a/Plugins/Interactive WebView/Interactive WebView/Interactive WebView.cs b/Plugins/Interactive WebView/Interactive WebView/Interactive WebView.cs index a0572bd..d8e3906 100644 --- a/Plugins/Interactive WebView/Interactive WebView/Interactive WebView.cs +++ b/Plugins/Interactive WebView/Interactive WebView/Interactive WebView.cs @@ -5,6 +5,10 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The sample adds a custom WebView to the Symbol tab, displaying account information +// such as cTID, account number and broker name. It also includes a button that, when clicked, +// will close all open positions on the account. +// // ------------------------------------------------------------------------------------------------- using System; @@ -15,16 +19,19 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class InteractiveWebView : Plugin { - WebView webView; + WebView webView; // Declare a WebView control to display custom HTML content. + // This method is executed when the plugin starts. protected override void OnStart() { - webView = new WebView(); - webView.WebMessageReceived += webView_WebMessageReceived; + webView = new WebView(); // Initialise the WebView control. + webView.WebMessageReceived += webView_WebMessageReceived; // Attach the event handler for receiving messages from the web content. + // Create a new block on the Symbol tab to hold the WebView. var block = Asp.SymbolTab.AddBlock("Interactive WebView"); block.Index = 1; block.Child = webView; @@ -32,7 +39,10 @@ protected override void OnStart() block.IsExpanded = true; block.IsDetachable = false; + // Attach the event handler for when the WebView has completed navigation. webView.NavigationCompleted += webView_NavigationCompleted; + + // Load custom HTML into the WebView, including the account info and 'Close all positions' button. webView.NavigateToStringAsync(@"
@@ -63,42 +73,51 @@ function updateValues(data){ "); - + // Attach event handler for when the account is switched. Account.Switched += Account_Switched; } + // Event handler for when the WebView finishes loading the content. private void webView_NavigationCompleted(WebViewNavigationCompletedEventArgs obj) { - UpdateAccountInfo(); + UpdateAccountInfo(); // Update the account info once navigation is complete. } + // Event handler for when the account is switched. private void Account_Switched(AccountSwitchedEventArgs obj) { - UpdateAccountInfo(); + UpdateAccountInfo(); // Update the account info whenever the account is switched. } + // Event handler for receiving messages from the WebView content. private void webView_WebMessageReceived(WebViewWebMessageReceivedEventArgs args) { + // Check if the message is the 'close all' message. if (args.Message == @"""close all message""") { foreach (var position in Positions) { - position.Close(); + position.Close(); // Close all open positions. } } } + // Method to update the account info in the WebView. private void UpdateAccountInfo() { + // Create an object to store account information. var data = new { - ctid = Account.UserId, - account = Account.Number, - broker = Account.BrokerName, + ctid = Account.UserId, // cTrader user ID. + account = Account.Number, // Account number. + broker = Account.BrokerName, // Broker name. }; + + // Serialise the account info to JSON. var dataJson = System.Text.Json.JsonSerializer.Serialize(data); + // Execute the JavaScript function in the WebView to update the values. webView.ExecuteScript("updateValues(" + dataJson + ")"); } } -} \ No newline at end of file +} diff --git a/Plugins/My ASP Example/My ASP Example/My ASP Example.cs b/Plugins/My ASP Example/My ASP Example/My ASP Example.cs index 77cf506..b4ecda2 100644 --- a/Plugins/My ASP Example/My ASP Example/My ASP Example.cs +++ b/Plugins/My ASP Example/My ASP Example/My ASP Example.cs @@ -4,7 +4,7 @@ // // The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. // -// This example plugin adds a new section to the Active Symbol Panel (ASP), with styles applied to the plugin controls. +// The sample adds a new section to Active Symbol Panel (ASP), with styles applied to the plugin controls. // // For a detailed tutorial on creating this plugin, watch the video at: https://www.youtube.com/watch?v=WRwhT7jxTNs // @@ -19,30 +19,36 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class MyASPExample : Plugin { - - TextBlock _txtBuyVWAP; - TextBlock _txtSellVWAP; + TextBlock _txtBuyVWAP; // TextBlock to display the Buy VWAP (Volume Weighted Average Price). + TextBlock _txtSellVWAP; // TextBlock to display the Sell VWAP. + + // This method is executed when the plugin starts. protected override void OnStart() { + // Create a new block in the ASP. var block = Asp.SymbolTab.AddBlock("My ASP Example"); block.Index = 2; block.Height = 100; block.IsExpanded = true; + // Create a vertical stack panel to arrange child controls. var panel = new StackPanel { Orientation = Orientation.Vertical }; + // Create a style for the text blocks (used for both Buy and Sell VWAP). var textBoxStyle = new Style(); textBoxStyle.Set(ControlProperty.Width, 200); textBoxStyle.Set(ControlProperty.Margin, 5); textBoxStyle.Set(ControlProperty.FontFamily, "Cambria"); textBoxStyle.Set(ControlProperty.FontSize, 15); + // Create a text block for displaying the Buy VWAP. _txtBuyVWAP = new TextBlock { Text = "Buy Text Block", @@ -50,6 +56,7 @@ protected override void OnStart() ForegroundColor = Color.Green }; + // Create a text block for displaying the Sell VWAP. _txtSellVWAP = new TextBlock { Text = "Sell Text Block", @@ -57,21 +64,27 @@ protected override void OnStart() ForegroundColor = Color.Red }; + // Add these text blocks to the panel. panel.AddChild(_txtBuyVWAP); panel.AddChild(_txtSellVWAP); + // Assign the panel to the block child, which displays the content. block.Child = panel; - var buyPositions = Positions.Where(p => p.TradeType == TradeType.Buy); + // Calculate and display the Buy VWAP. + var buyPositions = Positions.Where(p => p.TradeType == TradeType.Buy); // Get all buy positions. + // Calculate VWAP for buy positions. _txtBuyVWAP.Text = "Buy Positions VWAP: " + Math.Round((buyPositions.Sum(p => p.EntryPrice * p.VolumeInUnits)/ buyPositions.Sum(p => p.VolumeInUnits)), 5); - var sellPositions = Positions.Where(p => p.TradeType == TradeType.Sell); + // Calculate and display the Sell VWAP. + var sellPositions = Positions.Where(p => p.TradeType == TradeType.Sell); // Get all sell positions. + // Calculate VWAP for sell positions. _txtSellVWAP.Text = "Sell Positions VWAP: " + Math.Round((sellPositions.Sum(p => p.EntryPrice * p.VolumeInUnits)/ sellPositions.Sum(p => p.VolumeInUnits)), 5); } protected override void OnStop() { - // Handle Plugin stop here + // Handle Plugin stop here. } } -} \ No newline at end of file +} diff --git a/Plugins/My Custom Frame Example/My Custom Frame Example/My Custom Frame Example.cs b/Plugins/My Custom Frame Example/My Custom Frame Example/My Custom Frame Example.cs index f0a6c2c..856ea33 100644 --- a/Plugins/My Custom Frame Example/My Custom Frame Example/My Custom Frame Example.cs +++ b/Plugins/My Custom Frame Example/My Custom Frame Example/My Custom Frame Example.cs @@ -2,11 +2,10 @@ // // This code is a cTrader Algo API example. // -// The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. +// The code is provided as a sample only and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. // -// This example plugin adds two custom frames to the charts area, displaying two different websites. -// -// For a detailed tutorial on creating this plugin, watch the video at: [to:do] +// The sample adds two custom frames to the charts area, displaying two different websites. // // ------------------------------------------------------------------------------------------------- @@ -18,40 +17,52 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class MyCustomFrameExample : Plugin { - WebView _cTraderWebView = new WebView(); - WebView _cTraderWebViewSite = new WebView(); + WebView _cTraderWebView = new WebView(); // WebView for displaying the cTrader forum website. + WebView _cTraderWebViewSite = new WebView(); // WebView for displaying the Spotware website. + // This method is executed when the plugin starts. protected override void OnStart() { + // Handle the Loaded event when the first WebView has finished loading. _cTraderWebView.Loaded += _cTraderWebView_Loaded; - var webViewFrame = ChartManager.AddCustomFrame("Forum"); - webViewFrame.Child = _cTraderWebView; - webViewFrame.ChartContainer.Mode = ChartMode.Multi; - webViewFrame.Attach(); + + // Create a custom frame named "Forum" and set the WebView as its child. + var webViewFrame = ChartManager.AddCustomFrame("Forum"); // Add a custom frame to the chart container. + webViewFrame.Child = _cTraderWebView; // Set the first WebView as the child of the frame. + webViewFrame.ChartContainer.Mode = ChartMode.Multi; // Set chart container mode to Multi (supports multiple views). + webViewFrame.Attach(); // Attach the custom frame to the chart. + // Handle the Loaded event when the second WebView has finished loading. _cTraderWebViewSite.Loaded += _cTraderWebViewSite_Loaded; + + // Create a custom frame named "Site" and set the second WebView as its child. var webViewFrameSite = ChartManager.AddCustomFrame("Site"); webViewFrameSite.Child = _cTraderWebViewSite; webViewFrameSite.ChartContainer.Mode = ChartMode.Multi; webViewFrameSite.Attach(); } + // Event handler for the first WebView Loaded event. private void _cTraderWebView_Loaded(WebViewLoadedEventArgs args) { + // Navigate to the cTrader forum website once the WebView has finished loading. _cTraderWebView.NavigateAsync("https://www.ctrader.com/forum"); } + // Event handler for the second WebView Loaded event. private void _cTraderWebViewSite_Loaded(WebViewLoadedEventArgs args) { + // Navigate to the Spotware website once the WebView has finished loading. _cTraderWebViewSite.NavigateAsync("https://www.spotware.com"); } protected override void OnStop() { - // Handle Plugin stop here + // Handle Plugin stop here. } } -} \ No newline at end of file +} diff --git a/Plugins/Order by Margin/Order by Margin/Order by Margin.cs b/Plugins/Order by Margin/Order by Margin/Order by Margin.cs index 42e96a2..06fb515 100644 --- a/Plugins/Order by Margin/Order by Margin/Order by Margin.cs +++ b/Plugins/Order by Margin/Order by Margin/Order by Margin.cs @@ -5,6 +5,11 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The sample demonstrates how to create a custom plugin that allows the user to manage trading +// margin by displaying available margin, adjusting the margin to trade and executing buy/sell +// trades based on user input. It also includes buttons for increasing, decreasing and setting +// the maximum margin for trading. +// // ------------------------------------------------------------------------------------------------- using System; @@ -15,62 +20,75 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class OrderByMargin : Plugin { - TextBlock availableMarginTextBlock = new TextBlock(); - TextBlock quantityToTradeTextBlock = new TextBlock(); - ViewModel viewModel = new ViewModel(); - TextBox tradeableMarginTextBox; + TextBlock availableMarginTextBlock = new TextBlock(); // Create a TextBlock control to display available margin information. + TextBlock quantityToTradeTextBlock = new TextBlock(); // Create a TextBlock control to display the quantity to trade. + ViewModel viewModel = new ViewModel(); // Create a ViewModel instance to manage the data and events related to margin and trade quantity. + TextBox tradeableMarginTextBox; // Declare a TextBox control that will be used to display the margin available for trading. + // This method is triggered when the plugin starts. protected override void OnStart() { - viewModel.Changed += viewModel_Changed; + viewModel.Changed += viewModel_Changed; // Event handler for viewModel changes. - AddControls(); + AddControls(); // Call method to add UI controls to the plugin interface. + // Subscribe to position events to update margin when positions are modified. Positions.Opened += Positions_Opened; Positions.Closed += Positions_Closed; Positions.Modified += Positions_Modified; Asp.SymbolTab.SymbolChanged += AspSymbolTab_SymbolChanged; Account.Switched += Account_Switched; - UpdateAvailableMargin(); - SetMaximumMargin(); + UpdateAvailableMargin(); // Update available margin on start. + SetMaximumMargin(); // Set the maximum margin on start. } + // This method handles accounts switching, triggering a recalculation of the maximum margin. private void Account_Switched(AccountSwitchedEventArgs obj) { - SetMaximumMargin(); + SetMaximumMargin(); // Update maximum margin when account is switched. } + // This method handles symbols changing, triggering a recalculation of the maximum margin. private void AspSymbolTab_SymbolChanged(AspSymbolChangedEventArgs obj) { - SetMaximumMargin(); + SetMaximumMargin(); // Update maximum margin when symbol is changed. } + // This method builds the plugin interface with labels, buttons and input fields. It includes margin control buttons and trade buttons. private void AddControls() { + // Create a new block for the plugin interface. var block = Asp.SymbolTab.AddBlock("New Order by Margin"); - + block.IsExpanded = true; block.IsDetachable = false; + block.Index = 1; block.Height = 150; + // Create a stack panel with margins. var rootStackPanel = new StackPanel { Margin = new Thickness(10) }; + // Create and arrange UI elements to display available margin in a horizontal layout. var availableMarginStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; availableMarginStackPanel.AddChild(new TextBlock { Text = "Available Margin: " }); availableMarginStackPanel.AddChild(availableMarginTextBlock); rootStackPanel.AddChild(availableMarginStackPanel); + // Label for margin to trade. rootStackPanel.AddChild(new TextBlock { Text = "Margin to trade:", Margin = new Thickness(0, 10, 0, 0) }); + // Create a grid layout for organizing margin controls, defining columns with specific width settings. var tradeMarginGrid = new Grid { Margin = new Thickness(10) }; tradeMarginGrid.AddColumn().SetWidthInStars(1); tradeMarginGrid.AddColumn().SetWidthToAuto(); tradeMarginGrid.AddColumn().SetWidthToAuto(); tradeMarginGrid.AddColumn().SetWidthToAuto(); + // Add the text box for tradeable margin with styles. tradeableMarginTextBox = new TextBox { IsReadOnly = true, TextAlignment = TextAlignment.Right }; var tradeableMarginTextBoxStyle = new Style(); tradeableMarginTextBoxStyle.Set(ControlProperty.BackgroundColor, Color.FromArgb(26, 26, 26), ControlState.DarkTheme); @@ -79,6 +97,8 @@ private void AddControls() tradeableMarginTextBoxStyle.Set(ControlProperty.ForegroundColor, Color.FromArgb(55, 56, 57), ControlState.LightTheme); tradeableMarginTextBox.Style = tradeableMarginTextBoxStyle; tradeMarginGrid.AddChild(tradeableMarginTextBox, 0, 0); + + // Buttons for increasing, decreasing and setting maximum margin. var decreaseMarginButton = new Button { Text = "-", Margin = new Thickness(5, 0, 5, 0) }; decreaseMarginButton.Click += decreaseMarginButton_Click; tradeMarginGrid.AddChild(decreaseMarginButton, 0, 1); @@ -90,20 +110,24 @@ private void AddControls() tradeMarginGrid.AddChild(maxMarginButton, 0, 3); rootStackPanel.AddChild(tradeMarginGrid); + // Add quantity to trade section. var volumeStackPanel = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center }; volumeStackPanel.AddChild(new TextBlock { Text = "Quantity to trade: " }); volumeStackPanel.AddChild(quantityToTradeTextBlock); volumeStackPanel.AddChild(new TextBlock { Text = " Lots" }); rootStackPanel.AddChild(volumeStackPanel); + // Add trade buttons for Buy and Sell with styles. var tradeButtons = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10), HorizontalAlignment = HorizontalAlignment.Center }; tradeButtons.AddChild(CreateTradeButton("Sell", Styles.CreateSellButtonStyle(), TradeType.Sell)); tradeButtons.AddChild(CreateTradeButton("Buy", Styles.CreateBuyButtonStyle(), TradeType.Buy)); rootStackPanel.AddChild(tradeButtons); + // Add the root stack panel to the block. block.Child = rootStackPanel; } + // Create a trade button for executing either a buy or sell trade with specific styles. private Button CreateTradeButton(string text, Style style, TradeType tradeType) { var tradeButton = new Button @@ -113,41 +137,47 @@ private Button CreateTradeButton(string text, Style style, TradeType tradeType) Height = 25 }; + // Set button click action to execute a market order. tradeButton.Click += args => ExecuteMarketOrderAsync(tradeType, Asp.SymbolTab.Symbol.Name, viewModel.Quantity * Asp.SymbolTab.Symbol.LotSize); return tradeButton; } - + // Event handler for when the "max" margin button is clicked, setting the margin to the maximum possible value. private void maxMarginButton_Click(ButtonClickEventArgs obj) { - SetMaximumMargin(); + SetMaximumMargin(); // Update margin to the maximum available. } + // Event handler for when the "increase" margin button is clicked, increasing the margin based on the available quantity. private void increaseMarginButton_Click(ButtonClickEventArgs obj) { var symbol = Asp.SymbolTab.Symbol; var leverage = Math.Min(symbol.DynamicLeverage[0].Leverage, Account.PreciseLeverage); + // Check if the quantity exceeds maximum allowed volume. if (viewModel.Quantity > symbol.VolumeInUnitsMax / symbol.LotSize) return; - viewModel.Quantity += symbol.VolumeInUnitsMin / symbol.LotSize; - RecalculateMargin(viewModel.Quantity); + viewModel.Quantity += symbol.VolumeInUnitsMin / symbol.LotSize; // Increase quantity. + RecalculateMargin(viewModel.Quantity); // Recalculate margin for updated quantity. } + // Event handler for when the "decrease" margin button is clicked, decreasing the margin based on the available quantity. private void decreaseMarginButton_Click(ButtonClickEventArgs obj) { var symbol = Asp.SymbolTab.Symbol; var leverage = Math.Min(symbol.DynamicLeverage[0].Leverage, Account.PreciseLeverage); + // Ensure quantity does not go below the minimum allowed. if (viewModel.Quantity <= symbol.VolumeInUnitsMin / symbol.LotSize) return; - viewModel.Quantity -= symbol.VolumeInUnitsMin / symbol.LotSize; - RecalculateMargin(viewModel.Quantity); + viewModel.Quantity -= symbol.VolumeInUnitsMin / symbol.LotSize; // Decrease quantity. + RecalculateMargin(viewModel.Quantity); // Recalculate margin for updated quantity. } + // Update the displayed margin-related values whenever the view model is changed. private void viewModel_Changed() { availableMarginTextBlock.Text = Math.Floor(viewModel.AvailableMargin).ToString() + " " + Account.Asset.Name; @@ -155,26 +185,31 @@ private void viewModel_Changed() tradeableMarginTextBox.Text = viewModel.MarginToTrade.ToString(); } + // Event handler for when a position is modified, updating the available margin. private void Positions_Modified(PositionModifiedEventArgs obj) { UpdateAvailableMargin(); } + // Event handler for when a position is closed, updating the available margin. private void Positions_Closed(PositionClosedEventArgs obj) { UpdateAvailableMargin(); } + // Event handler for when a position is opened, updating the available margin. private void Positions_Opened(PositionOpenedEventArgs obj) { UpdateAvailableMargin(); } + // Update the available margin based on the free margin in the account. private void UpdateAvailableMargin() { viewModel.AvailableMargin = Account.FreeMargin; } + // Set the margin to the maximum value based on available free margin and leverage. private void SetMaximumMargin() { var symbol = Asp.SymbolTab.Symbol; @@ -185,6 +220,8 @@ private void SetMaximumMargin() viewModel.Quantity = tradeableVolume / symbol.LotSize; viewModel.MarginToTrade = symbol.BaseAsset.Convert(Account.Asset, tradeableVolume / leverage); } + + // Recalculate the margin required based on the provided quantity. private void RecalculateMargin(double quantity) { var symbol = Asp.SymbolTab.Symbol; @@ -196,18 +233,22 @@ private void RecalculateMargin(double quantity) } } + // A static class containing methods for defining button styles used in the application. public static class Styles { + // Create the style for a "Buy" button with a specific background and hover color. public static Style CreateBuyButtonStyle() { return CreateButtonStyle(Color.FromHex("#009345"), Color.FromHex("#10A651")); } + // Create the style for a "Sell" button with a specific background and hover color. public static Style CreateSellButtonStyle() { return CreateButtonStyle(Color.FromHex("#F05824"), Color.FromHex("#FF6C36")); } + // A helper method to create button styles, defining the background and hover colors, foreground color, width and margin. private static Style CreateButtonStyle(Color color, Color hoverColor) { var style = new Style(DefaultStyles.ButtonStyle); @@ -223,52 +264,52 @@ private static Style CreateButtonStyle(Color color, Color hoverColor) } } - + // ViewModel class that holds the data properties and notifies changes to the UI when the data is updated. class ViewModel { - private double _availableMargin; - public double AvailableMargin + private double _availableMargin; // Private backing field for AvailableMargin. + public double AvailableMargin // Public property for AvailableMargin with a getter and setter. { - get { return _availableMargin; } + get { return _availableMargin; } // Return the current value of _availableMargin. set { - if (value == _availableMargin) + if (value == _availableMargin) // If the new value is the same as the current one, no action is taken. return; - _availableMargin = value; + _availableMargin = value; // Update the private backing field with the new value. - Changed?.Invoke(); + Changed?.Invoke(); // Trigger the Changed event to notify subscribers of the property change. } } - private double _quantity; - public double Quantity + private double _quantity; // Private backing field for Quantity. + public double Quantity // Public property for Quantity with a getter and setter. { - get { return _quantity; } + get { return _quantity; } // Return the current value of _quantity. set { - if (value == _quantity) + if (value == _quantity) // If the new value is the same as the current one, no action is taken. return; - _quantity = value; + _quantity = value; // Update the private backing field with the new value. - Changed?.Invoke(); + Changed?.Invoke(); // Trigger the Changed event to notify subscribers of the property change. } } - private double _marginToTrade; - public double MarginToTrade + private double _marginToTrade; // Private backing field for MarginToTrade. + public double MarginToTrade // Public property for MarginToTrade with a getter and setter. { - get { return _marginToTrade; } + get { return _marginToTrade; } // Return the current value of _marginToTrade. set { - if (value == _marginToTrade) + if (value == _marginToTrade) // If the new value is the same as the current one, no action is taken. return; - _marginToTrade = value; + _marginToTrade = value; // Update the private backing field with the new value. - Changed?.Invoke(); + Changed?.Invoke(); // Trigger the Changed event to notify subscribers of the property change. } } - + // Event that is triggered whenever any of the properties change. public event Action Changed; } -} \ No newline at end of file +} diff --git a/Plugins/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs b/Plugins/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs index 524ffbb..adfcb29 100644 --- a/Plugins/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs +++ b/Plugins/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a new block into the ASP. The block displays a ComboBox in which the user +// The sample adds a new block into the ASP. The block displays a ComboBox in which the user // can select any of their currently open positions. Below the ComboBox, the block displays the // current price of the symbol for which the selected position was opened. // @@ -19,17 +19,19 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class PositionCurrentPriceSample : Plugin { - private TextBlock _currentPriceText; - ComboBox _positionSelectionComboBox; - Position _selectedPosition; - Grid _blockGrid; + private TextBlock _currentPriceText; // Declaring a TextBlock to display the current price. + ComboBox _positionSelectionComboBox; // Declaring a ComboBox for selecting a position. + Position _selectedPosition; // Declaring a variable to hold the selected position. + Grid _blockGrid; // Declaring a grid for layout purposes. + // This method is executed when the plugin starts. protected override void OnStart() { - // Configuring the new TextBlock + // Configuring the new TextBlock for position selection. _currentPriceText = new TextBlock { Text = "Select a position above", @@ -38,60 +40,57 @@ protected override void OnStart() FontWeight = FontWeight.ExtraBold, }; - // Adding a new ComboBox and adding existing positions - // as options + // Adding a new ComboBox for position selection and populating it with existing positions. _positionSelectionComboBox = new ComboBox(); + // Iterating through all positions to add them as items. foreach (var position in Positions) { - _positionSelectionComboBox.AddItem(position.Id.ToString()); + _positionSelectionComboBox.AddItem(position.Id.ToString()); // Adding the position Id to ComboBox. } - // Reacting to the selected position change + // Setting up an event handler that triggers when the selected item changes in the ComboBox. _positionSelectionComboBox.SelectedItemChanged += SelectedPositionChanged; - - - - // Configuring the Grid where the ComboBox and the price TextBlock - // are placed + + // Configuring the grid where the ComboBox and the price TextBlock are placed. _blockGrid = new Grid(2, 1); _blockGrid.AddChild(_positionSelectionComboBox, 0, 0); _blockGrid.AddChild(_currentPriceText, 1, 0); - // Adding a new block into the ASP + // Adding a new block into the ASP. Asp.SymbolTab.AddBlock("Position.CurrentPrice").Child = _blockGrid; - // Starting the timer with 100 milliseconds as the tick + // Starting the timer with 100 milliseconds as the tick. Timer.Start(TimeSpan.FromMilliseconds(100)); } - // Updating the _selectedPosition field by finding a Position object - // with the Id chosen in the ComboBox + // Updating the _selectedPosition field by finding a position object with the Id chosen in the ComboBox. private void SelectedPositionChanged(ComboBoxSelectedItemChangedEventArgs obj) { _selectedPosition = FindPositionById(obj.SelectedItem); } - // Overriding the built-in handler of the Timer.TimerTick event + // Overriding the built-in handler of the Timer.TimerTick event. protected override void OnTimer() { - // Updating the text inside the TextBlock by using Position.CurrentPrice + // Updating the text inside the TextBlock by using Position.CurrentPrice. _currentPriceText.Text = _selectedPosition.CurrentPrice.ToString(); } - // Defining a custom method to find a position by its Id + // Defining a custom method to find a position by its Id. private Position FindPositionById(string positionId) { + // Iterating through all open positions. foreach (var position in Positions) { - if (position.Id.ToString() == positionId) + if (position.Id.ToString() == positionId) // Matching the Id of the position. { - return position; + return position; // Returning the matched position. } } - return null; + return null; // Returning null if no position matches. } } -} \ No newline at end of file +} diff --git a/Plugins/Previous Bar Info/Previous Bar Info/Previous Bar Info.cs b/Plugins/Previous Bar Info/Previous Bar Info/Previous Bar Info.cs index 52d7806..f857748 100644 --- a/Plugins/Previous Bar Info/Previous Bar Info/Previous Bar Info.cs +++ b/Plugins/Previous Bar Info/Previous Bar Info/Previous Bar Info.cs @@ -4,7 +4,7 @@ // // The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. // -// This example plugin adds a new section to Trade Watch, featuring a two-by-two grid that displays information about the last known bar prices. +// The sample adds a new section to Trade Watch, featuring a two-by-two grid that displays information about the last known bar prices. // // For a detailed tutorial on creating this plugin, watch the video at: https://youtu.be/0HB-rdwpMAY // @@ -18,10 +18,11 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class PreviousBarInfo : Plugin { - + // Declare variables for market data (Bars) and UI elements (Grid, TextBlocks) used to display price information. Bars _bars; Grid _grid; TextBlock _lowBlock; @@ -29,17 +30,18 @@ public class PreviousBarInfo : Plugin TextBlock _highBlock; TextBlock _closeBlock; + // This method is executed when the plugin starts. protected override void OnStart() { - var tradeWatchTab = TradeWatch.AddTab("Previous Bar Info"); - tradeWatchTab.IsSelected = true; + var tradeWatchTab = TradeWatch.AddTab("Previous Bar Info"); // Add a new tab to TradeWatch. + tradeWatchTab.IsSelected = true; // Select the new tab by default. - var webView = new WebView(); - tradeWatchTab.Child = webView; + var webView = new WebView(); // Create a WebView object for embedding web content. + tradeWatchTab.Child = webView; // Set the WebView as the child of the TradeWatch tab. - webView.NavigateAsync("https://ctrader.com/"); + webView.NavigateAsync("https://ctrader.com/"); // Navigate to a URL in the WebView. - _grid = new Grid(2, 2) + _grid = new Grid(2, 2) // Create a 2x2 grid for the layout of TextBlocks. { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, @@ -48,50 +50,52 @@ protected override void OnStart() Width = 150, }; - _bars = MarketData.GetBars(TimeFrame.Minute, "USDJPY"); + _bars = MarketData.GetBars(TimeFrame.Minute, "USDJPY"); // Fetch 1-minute bars for the USDJPY symbol. - _lowBlock = new TextBlock + _lowBlock = new TextBlock // Create a TextBlock for displaying the low price of the bar. { Text = "Low:" + _bars.LowPrices.LastValue, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; - _highBlock = new TextBlock + _highBlock = new TextBlock // Create a TextBlock for displaying the high price of the bar. { Text = "High:" + _bars.HighPrices.LastValue, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; - _closeBlock = new TextBlock + _closeBlock = new TextBlock // Create a TextBlock for displaying the close price of the bar. { Text = "Close:" +_bars.ClosePrices.LastValue, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; - _openBlock = new TextBlock + _openBlock = new TextBlock // Create a TextBlock for displaying the open price of the bar. { Text = "Open:" + _bars.OpenPrices.LastValue, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; + // Add the TextBlocks to the grid at their respective positions. _grid.AddChild(_lowBlock, 0, 0); _grid.AddChild(_highBlock, 0, 1); _grid.AddChild(_openBlock, 1, 0); _grid.AddChild(_closeBlock, 1, 1); - tradeWatchTab.Child = _grid; + tradeWatchTab.Child = _grid; // Set the grid as the child of the TradeWatch tab. - _bars.Tick += _bars_Tick; - + _bars.Tick += _bars_Tick; // Attach an event handler to update the price data every tick. } + // Event handler to update the TextBlocks on each new tick. private void _bars_Tick(BarsTickEventArgs obj) { + // Update the text for each TextBlock with the latest price data. _lowBlock.Text = "Low: " +_bars.LowPrices.LastValue.ToString(); _highBlock.Text = "High: " +_bars.HighPrices.LastValue.ToString(); _openBlock.Text = "Open: " +_bars.OpenPrices.LastValue.ToString(); @@ -100,7 +104,7 @@ private void _bars_Tick(BarsTickEventArgs obj) protected override void OnStop() { - // Handle Plugin stop here + // Handle Plugin stop here. } } -} \ No newline at end of file +} diff --git a/Plugins/SmoothMouseMove Sample/SmoothMouseMove Sample/SmoothMouseMove Sample.cs b/Plugins/SmoothMouseMove Sample/SmoothMouseMove Sample/SmoothMouseMove Sample.cs index 98cceef..a2e66e6 100644 --- a/Plugins/SmoothMouseMove Sample/SmoothMouseMove Sample/SmoothMouseMove Sample.cs +++ b/Plugins/SmoothMouseMove Sample/SmoothMouseMove Sample/SmoothMouseMove Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample opens a new chart for GPBUSD on start. When the user hovers the mouse cursor over +// The sample opens a new chart for GPBUSD on start. When the user hovers the mouse cursor over // this chart, the plugin shows a Border containing a TextBlock that demonstrates whether showing // orders on the chart is enabled/disabled. When the user clicks on the chart, the displaying of // orders is enabled/disabled with the text inside the TextBlock being updated automatically. @@ -20,11 +20,11 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class SmoothMouseMoveSample : Plugin { - // Declaring the required controls and - // the variable for storing the Chart + // Declaring the required controls and the variable for storing the chart. private TextBlock _ordersStatusTextBlock; private Border _ordersStatusBorder; private Canvas _canvas; @@ -32,12 +32,10 @@ public class SmoothMouseMoveSample : Plugin protected override void OnStart() { - // Opening a new chart for GBPUSD and - // storing the Chart inside a varaible + // Opening a new chart for GBPUSD and storing the chart inside a varaible. _gpbusdChart = ChartManager.AddChartFrame("GBPUSD", TimeFrame.Minute2).Chart; - // Initialising the Border and - // setting its parameters + // Initialising the border and setting its parameters. _ordersStatusBorder = new Border { IsHitTestVisible = false, CornerRadius = 3, @@ -47,25 +45,23 @@ protected override void OnStart() IsVisible = false, }; - // Initialising the TextBlock and - // settings its initial text + // Initialising the TextBlock and settings its initial text. _ordersStatusTextBlock = new TextBlock { Text = _gpbusdChart.DisplaySettings.Orders.ToString() }; - // Initialising the Canvas and - // placing the TextBlock inside it + // Initialising the canvas and placing the TextBlock inside it. _canvas = new Canvas(); _canvas.AddChild(_ordersStatusBorder); - // Placing the TextBlock inside the Border + // Placing the TextBlock inside the border. _ordersStatusBorder.Child = _ordersStatusTextBlock; - // Adding the Canvas to the Chart + // Adding the canvas to the chart. _gpbusdChart.AddControl(_canvas); - // Handling various mouse events + // Handling various mouse events. _gpbusdChart.MouseUp += GpbusdChartOnMouseUp; _gpbusdChart.MouseEnter += GpbusdChartOnMouseEnter; _gpbusdChart.MouseLeave += GpbusdChartOnMouseLeave; @@ -75,33 +71,30 @@ protected override void OnStart() private void GpbusdChartOnMouseMove(ChartMouseEventArgs obj) { - // Moving the border to follow the mouse cursor + // Moving the border to follow the mouse cursor. _ordersStatusBorder.Top = obj.MouseY; _ordersStatusBorder.Left = obj.MouseX; } private void GpbusdChartOnMouseLeave(ChartMouseEventArgs obj) { - // Hiding the border whenever the - // mouse cursor leaves the chart + // Hiding the border whenever the mouse cursor leaves the chart. _ordersStatusBorder.IsVisible = false; } private void GpbusdChartOnMouseEnter(ChartMouseEventArgs obj) { - // Showing the border whenever the - // mouse cursor enters the chart + // Showing the border whenever the mouse cursor enters the chart. _ordersStatusBorder.IsVisible = true; } private void GpbusdChartOnMouseUp(ChartMouseEventArgs obj) { - // Enabling or disabling the displaying of orders on the chart + // Enabling or disabling the displaying of orders on the chart. _gpbusdChart.DisplaySettings.Orders = !_gpbusdChart.DisplaySettings.Orders; - // Updating the text inside the TextBlock to match - // the current settings + // Updating the text inside the TextBlock to match the current settings. _ordersStatusTextBlock.Text = _gpbusdChart.DisplaySettings.Orders.ToString(); } } -} \ No newline at end of file +} diff --git a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/SymbolStatsControl.cs b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/SymbolStatsControl.cs index 0a3ff85..a256fe9 100644 --- a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/SymbolStatsControl.cs +++ b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/SymbolStatsControl.cs @@ -1,98 +1,116 @@ -using System; +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This code is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// The sample creates a custom control that displays the real-time stats of a selected trading symbol, +// such as the symbol bid, ask, spread, unrealized profits and commission. The control dynamically +// updates the displayed information whenever the symbol ticks. +// +// ------------------------------------------------------------------------------------------------- + +using System; using cAlgo.API; using cAlgo.API.Internals; namespace cAlgo.Plugins; -public class SymbolStatsControl : CustomControl +public class SymbolStatsControl : CustomControl // Declare the custom control class to display symbol stats. { - private const string FontFamily = "Calibri"; - private readonly TextBlock _commissionTextBlock; + private const string FontFamily = "Calibri"; // Define a constant for font family. + private readonly TextBlock _commissionTextBlock; // Declare a TextBlock for displaying commission. - private readonly StackPanel _panel; - private readonly TextBlock _spreadTextBlock; - private readonly TextBlock _symbolNameTextBlock; - private readonly TextBlock _symbolPriceTextBlock; + private readonly StackPanel _panel; // Declare a StackPanel to hold UI controls vertically. + private readonly TextBlock _spreadTextBlock; // Declare a TextBlock to display the spread. + private readonly TextBlock _symbolNameTextBlock; // Declare a TextBlock to display the symbol name. + private readonly TextBlock _symbolPriceTextBlock; // Declare a TextBlock to display the symbol price. - private readonly TextBlock _unrealizedGrossProfitTextBlock; - private readonly TextBlock _unrealizedNetProfitTextBlock; + private readonly TextBlock _unrealizedGrossProfitTextBlock; // Declare a TextBlock to show unrealised gross profit. + private readonly TextBlock _unrealizedNetProfitTextBlock; // Declare a TextBlock to show unrealised net profit. - private Symbol _symbol; + private Symbol _symbol; // Declare a private field to store the symbol. + // This method is used to set up the custom control. public SymbolStatsControl() { - _panel = new StackPanel + _panel = new StackPanel // Create a StackPanel to organise controls vertically. { - Orientation = Orientation.Vertical, + Orientation = Orientation.Vertical, // Set the orientation to vertical. }; - _symbolNameTextBlock = GetTextBlock(); - _symbolPriceTextBlock = GetTextBlock(); + _symbolNameTextBlock = GetTextBlock(); // Initialise the symbol name TextBlock. + _symbolPriceTextBlock = GetTextBlock(); // Initialise the symbol price TextBlock. - _panel.AddChild(WrapInHorizontalPanel(_symbolNameTextBlock, _symbolPriceTextBlock)); + _panel.AddChild(WrapInHorizontalPanel(_symbolNameTextBlock, _symbolPriceTextBlock)); // Wrap and add the name and price text blocks in a horizontal panel. - var grid = new Grid(10, 2); + var grid = new Grid(10, 2); // Create a 10x2 grid to organise the remaining stats. - _spreadTextBlock = GetTextBlock(); + _spreadTextBlock = GetTextBlock(); // Initialise the spread TextBlock. - grid.AddChild(GetTextBlock("Spread"), 0, 0); - grid.AddChild(_spreadTextBlock, 0, 1); + grid.AddChild(GetTextBlock("Spread"), 0, 0); // Add a label for spread to the grid. + grid.AddChild(_spreadTextBlock, 0, 1); // Add the spread value TextBlock to the grid. - _unrealizedNetProfitTextBlock = GetTextBlock(); + _unrealizedNetProfitTextBlock = GetTextBlock(); // Initialise the unrealised net profit TextBlock. - grid.AddChild(GetTextBlock("Unrealized Net Profit"), 1, 0); - grid.AddChild(_unrealizedNetProfitTextBlock, 1, 1); + grid.AddChild(GetTextBlock("Unrealized Net Profit"), 1, 0); // Add a label for unrealised net profit to the grid. + grid.AddChild(_unrealizedNetProfitTextBlock, 1, 1); // Add the unrealised net profit TextBlock to the grid. - _unrealizedGrossProfitTextBlock = GetTextBlock(); + _unrealizedGrossProfitTextBlock = GetTextBlock(); // Initialise the unrealised gross profit TextBlock. - grid.AddChild(GetTextBlock("Unrealized Gross Profit"), 2, 0); - grid.AddChild(_unrealizedGrossProfitTextBlock, 2, 1); + grid.AddChild(GetTextBlock("Unrealized Gross Profit"), 2, 0); // Add a label for unrealised gross profit to the grid. + grid.AddChild(_unrealizedGrossProfitTextBlock, 2, 1); // Add the unrealised gross profit TextBlock to the grid. - _commissionTextBlock = GetTextBlock(); + _commissionTextBlock = GetTextBlock(); // Initialise the commission TextBlock. - grid.AddChild(GetTextBlock("Commission"), 3, 0); - grid.AddChild(_commissionTextBlock, 3, 1); + grid.AddChild(GetTextBlock("Commission"), 3, 0); // Add a label for commission to the grid. + grid.AddChild(_commissionTextBlock, 3, 1); // Add the commission TextBlock to the grid. - _panel.AddChild(grid); + _panel.AddChild(grid); // Add the grid to the panel. - AddChild(_panel); + AddChild(_panel); // Add the entire panel to the custom control. } + // Property to get or set the symbol for this control. public Symbol Symbol { - get => _symbol; + get => _symbol; // Return the current symbol. set { - if (value is null || _symbol == value) - return; + if (value is null || _symbol == value) // Check if the symbol is null or has not changed. + return; // If no change, do nothing. - Update(value); + Update(value); // If the symbol has changed, update the control. } } + // Helper method to create a horizontal panel. private StackPanel WrapInHorizontalPanel(params ControlBase[] controls) { - var panel = new StackPanel + var panel = new StackPanel // Create a new StackPanel for horizontal layout. { - Orientation = Orientation.Horizontal + Orientation = Orientation.Horizontal // Set orientation to horizontal. }; - foreach (var control in controls) + foreach (var control in controls) // Iterate over each control passed. { - if (control.Margin == 0) - control.Margin = 3; + if (control.Margin == 0) // Check if the control has no margin. + control.Margin = 3; // Set a default margin if no margin is specified. - panel.AddChild(control); + panel.AddChild(control); // Add the control to the panel. } - return panel; + return panel; // Return the constructed horizontal panel. } + // Method to update the stats for the new symbol. private void Update(Symbol newSymbol) { - var previousSymbol = _symbol; - _symbol = newSymbol; + var previousSymbol = _symbol; // Store the current symbol to unsubscribe from the tick event. + _symbol = newSymbol; // Update the symbol to the new one. + // Update the text values of the TextBlocks to reflect the new symbol data. _symbolNameTextBlock.Text = $"{newSymbol.Name} ({newSymbol.Description})"; _symbolPriceTextBlock.Text = $"Bid: {newSymbol.Bid}, Ask: {newSymbol.Ask}"; _spreadTextBlock.Text = $"{GetSpreadInPips(newSymbol)} Pips"; @@ -100,22 +118,28 @@ private void Update(Symbol newSymbol) _unrealizedGrossProfitTextBlock.Text = newSymbol.UnrealizedGrossProfit.ToString(); _commissionTextBlock.Text = $"{newSymbol.Commission} {newSymbol.CommissionType}"; - if (previousSymbol is not null) previousSymbol.Tick -= OnSymbolTick; + if (previousSymbol is not null) previousSymbol.Tick -= OnSymbolTick; // Unsubscribe from the previous tick event. - newSymbol.Tick += OnSymbolTick; + newSymbol.Tick += OnSymbolTick; // Subscribe to the new tick event. } + // Event handler for symbol tick events. private void OnSymbolTick(SymbolTickEventArgs obj) { + // Update the displayed symbol data when the symbol ticks. _symbolPriceTextBlock.Text = $"Bid: {obj.Bid}, Ask: {obj.Ask}"; _spreadTextBlock.Text = $"{GetSpreadInPips(obj.Symbol)} Pips"; _unrealizedNetProfitTextBlock.Text = obj.Symbol.UnrealizedNetProfit.ToString(); _unrealizedGrossProfitTextBlock.Text = obj.Symbol.UnrealizedGrossProfit.ToString(); } + // Method to calculate the spread in pips. private double GetSpreadInPips(Symbol symbol) => + + // Calculate the spread in pips based on the spread, digits, pip size and tick size. (symbol.Spread * Math.Pow(10, symbol.Digits)) / (Symbol.PipSize / Symbol.TickSize); + // Helper method to create a TextBlock with common properties. private TextBlock GetTextBlock(string text = null) => new() { Margin = 3, @@ -124,4 +148,4 @@ private double GetSpreadInPips(Symbol symbol) => FontFamily = FontFamily, Text = text }; -} \ No newline at end of file +} diff --git a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeControl.cs b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeControl.cs index 2198165..f24519a 100644 --- a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeControl.cs +++ b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeControl.cs @@ -1,24 +1,40 @@ -using System; +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This code is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// The sample creates a custom control for trading operations. The control provides a panel where +// the user can specify the trade type (buy/sell) and the volume for a trade. When the "Execute" +// button is clicked, it triggers an event with the specified trade details (trade type, volume, symbol). +// +// ------------------------------------------------------------------------------------------------- + +using System; using cAlgo.API; using cAlgo.API.Internals; namespace cAlgo.Plugins; +// Declare a struct to hold trade event data. public readonly record struct TradeEventArgs(int Volume, TradeType TradeType, string SymbolName); +// Declare a class to provide trading controls. public class TradeControl : CustomControl { - private const string FontFamily = "Calibri"; + private const string FontFamily = "Calibri"; // Define a constant for the font family to use in the control. - private readonly Grid _panel; - private readonly ComboBox _tradeTypeComboBox; - private readonly TextBox _volumeTextBox; + private readonly Grid _panel; // Create a panel for organising controls. + private readonly ComboBox _tradeTypeComboBox; // Add a ComboBox for selecting trade type. + private readonly TextBox _volumeTextBox; // Add a TextBox for inputting trade volume. + // Define a method to initialise the custom control. public TradeControl() { - _panel = new Grid(10, 2); + _panel = new Grid(10, 2); // Initialise a grid with specified rows and columns. - _volumeTextBox = new TextBox + _volumeTextBox = new TextBox // Initialise the text box for volume input. { MinWidth = 200, FontFamily = FontFamily, @@ -27,10 +43,10 @@ public TradeControl() Margin = 3 }; - _panel.AddChild(GetTextBlock("Volume"), 0, 0); - _panel.AddChild(_volumeTextBox, 0, 1); + _panel.AddChild(GetTextBlock("Volume"), 0, 0); // Add a label to the grid. + _panel.AddChild(_volumeTextBox, 0, 1); // Add the volume text box to the grid. - _tradeTypeComboBox = new ComboBox + _tradeTypeComboBox = new ComboBox // Initialise the combo box for trade type. { MinWidth = 200, FontFamily = FontFamily, @@ -39,44 +55,48 @@ public TradeControl() Margin = 3 }; - _tradeTypeComboBox.AddItem("Buy"); - _tradeTypeComboBox.AddItem("Sell"); + _tradeTypeComboBox.AddItem("Buy"); // Add the "Buy" option to the combo box. + _tradeTypeComboBox.AddItem("Sell"); // Add the "Sell" option to the combo box. - _tradeTypeComboBox.SelectedItem = "Buy"; + _tradeTypeComboBox.SelectedItem = "Buy"; // Set the default selected item. - var tradeTypeTextBlock = GetTextBlock("Trade Type"); + var tradeTypeTextBlock = GetTextBlock("Trade Type"); // Create a label for trade type. - tradeTypeTextBlock.VerticalAlignment = VerticalAlignment.Center; + tradeTypeTextBlock.VerticalAlignment = VerticalAlignment.Center; // Align the label vertically. - _panel.AddChild(tradeTypeTextBlock, 1, 0); - _panel.AddChild(_tradeTypeComboBox, 1, 1); + _panel.AddChild(tradeTypeTextBlock, 1, 0); // Add the label to the grid. + _panel.AddChild(_tradeTypeComboBox, 1, 1); // Add the combo box to the grid. - var executeButton = new Button {Text = "Execute", FontFamily = FontFamily, BackgroundColor = Color.Red}; + var executeButton = new Button {Text = "Execute", FontFamily = FontFamily, BackgroundColor = Color.Red}; // Create a button for execution. - executeButton.Click += ExecuteButtonOnClick; - _panel.AddChild(executeButton, 2, 0, 1, 2); + executeButton.Click += ExecuteButtonOnClick; // Attach the click event to the button. + _panel.AddChild(executeButton, 2, 0, 1, 2); // Add the button to the grid. - AddChild(_panel); + AddChild(_panel); // Add the panel to the custom control. } + // Define a property to hold the symbol. public Symbol Symbol { get; set; } + // Declare an event for trade execution. public event EventHandler Trade; + // Define a method to handle the button click event. private void ExecuteButtonOnClick(ButtonClickEventArgs obj) { - if (Symbol is null) + if (Symbol is null) // Check if the symbol is null. return; - if (!int.TryParse(_volumeTextBox.Text, out var volume)) + if (!int.TryParse(_volumeTextBox.Text, out var volume)) // Validate the volume input. return; - if (!Enum.TryParse(_tradeTypeComboBox.SelectedItem, out TradeType tradeType)) + if (!Enum.TryParse(_tradeTypeComboBox.SelectedItem, out TradeType tradeType)) // Validate the trade type input. return; - Trade?.Invoke(this, new TradeEventArgs(volume, tradeType, Symbol.Name)); + Trade?.Invoke(this, new TradeEventArgs(volume, tradeType, Symbol.Name)); // Trigger the trade event with the specified details. } + // Define a method to create a text block with specific settings. private TextBlock GetTextBlock(string text = null) => new() { Margin = 3, @@ -85,4 +105,4 @@ private void ExecuteButtonOnClick(ButtonClickEventArgs obj) FontFamily = FontFamily, Text = text }; -} \ No newline at end of file +} diff --git a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeWatch Tab Sample.cs b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeWatch Tab Sample.cs index 96b3e50..69e1eed 100644 --- a/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeWatch Tab Sample.cs +++ b/Plugins/TradeWatch Tab Sample/TradeWatch Tab Sample/TradeWatch Tab Sample.cs @@ -5,7 +5,7 @@ // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// This sample adds a trade watch tab, and shows some of the active symbol stats with a basic trading panel on it. +// The sample adds a Trade Watch tab and shows some of the active symbol stats with a basic trading panel on it. // // ------------------------------------------------------------------------------------------------- @@ -13,45 +13,49 @@ namespace cAlgo.Plugins { + // Declare the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class TradeWatchTabSample : Plugin { - private SymbolStatsControl _symbolStatsControl; - private TradeControl _tradeControl; + private SymbolStatsControl _symbolStatsControl; // Declare a variable for the symbol stats control. + private TradeControl _tradeControl; // Declare a variable for the trade control component. + // This method is executed when the plugin starts. protected override void OnStart() { - var tab = TradeWatch.AddTab("Active Chart Symbol Stats"); + var tab = TradeWatch.AddTab("Active Chart Symbol Stats"); // Add a new tab to the Trade Watch panel with a custom name. - var panel = new StackPanel + var panel = new StackPanel // Create a new stack panel to arrange child components vertically. {Orientation = Orientation.Vertical, HorizontalAlignment = HorizontalAlignment.Center}; - _symbolStatsControl = new SymbolStatsControl {Margin = 10}; - _tradeControl = new TradeControl {Margin = 10}; + _symbolStatsControl = new SymbolStatsControl {Margin = 10}; // Initialise the symbol stats control with a margin of 10. + _tradeControl = new TradeControl {Margin = 10}; // Initialise the trade control with a margin of 10. - panel.AddChild(_symbolStatsControl); - panel.AddChild(_tradeControl); + panel.AddChild(_symbolStatsControl); // Add the symbol stats control to the panel. + panel.AddChild(_tradeControl); // Add the trade control to the panel. - tab.Child = panel; + tab.Child = panel; // Assign the created panel as the child of the newly created tab. - SetSymbolStats(); + SetSymbolStats(); // Call the method to set the symbol stats for the controls. - _tradeControl.Trade += TradeControlOnTrade; - ChartManager.ActiveFrameChanged += _ => SetSymbolStats(); + _tradeControl.Trade += TradeControlOnTrade; // Subscribe to the trade event on the trade control. + ChartManager.ActiveFrameChanged += _ => SetSymbolStats(); // Update symbol stats when the active chart changes. } + // Method handler for the trade event. private void TradeControlOnTrade(object sender, TradeEventArgs e) { - ExecuteMarketOrder(e.TradeType, e.SymbolName, e.Volume); + ExecuteMarketOrder(e.TradeType, e.SymbolName, e.Volume); // Execute a market order based on the trade event details. } + // Method to set the symbol stats on the controls. private void SetSymbolStats() { - if (ChartManager.ActiveFrame is not ChartFrame chartFrame) - return; + if (ChartManager.ActiveFrame is not ChartFrame chartFrame) // Check if the active frame is a valid ChartFrame object. + return; // Return if the active frame is not a valid ChartFrame. - _tradeControl.Symbol = chartFrame.Symbol; - _symbolStatsControl.Symbol = chartFrame.Symbol; + _tradeControl.Symbol = chartFrame.Symbol; // Set the symbol for the trade control. + _symbolStatsControl.Symbol = chartFrame.Symbol; // Set the symbol for the symbol stats control. } } -} \ No newline at end of file +} diff --git a/Plugins/WebSocket Sample/WebSocket Sample/WebSocket Sample.cs b/Plugins/WebSocket Sample/WebSocket Sample/WebSocket Sample.cs index 443ea24..9e8b0c8 100644 --- a/Plugins/WebSocket Sample/WebSocket Sample/WebSocket Sample.cs +++ b/Plugins/WebSocket Sample/WebSocket Sample/WebSocket Sample.cs @@ -22,10 +22,11 @@ namespace cAlgo.Plugins { + // Declaring the class as a plugin without requiring special access permissions. [Plugin(AccessRights = AccessRights.None)] public class WebSocketSample : Plugin { - // Declaring our TextBlock that will display the news contents + // Declaring our TextBlock that will display the news contents. private TextBlock _textBlock = new TextBlock { Text = "Starting...", @@ -35,32 +36,29 @@ public class WebSocketSample : Plugin Padding = new Thickness(5, 5, 5, 5), }; - // _webSocketClientOptions allow us to define several settings - // such as the keep-alive interval of the WebSocket connection + // _webSocketClientOptions allow us to define several settings such as the keep-alive interval of the WebSocket connection. private static WebSocketClientOptions _webSocketClientOptions = new WebSocketClientOptions { KeepAliveInterval = new TimeSpan(0, 1, 30), UseDefaultCredentials = true, }; - // Passing our _webSocketClientOptions to the WebSocketClient - // constructor + // Passing our _webSocketClientOptions to the WebSocketClient constructor. private WebSocketClient _webSocketClient = new WebSocketClient(_webSocketClientOptions); - // This API is entirely fictional + // This API is entirely fictional. private readonly Uri _targetUri = new Uri("ws://amazingnews.com:8000"); protected override void OnStart() { - // Connecting to the API and sending the initial message + // Connecting to the API and sending the initial message. _webSocketClient.Connect(_targetUri); _webSocketClient.Send("Hello"); - // Declaring a custom handler for the TextReceived event + // Declaring a custom handler for the TextReceived event. _webSocketClient.TextReceived += NewsReceived; - // Adding our TextBlock as a child of a custom - // AspBlock + // Adding our TextBlock as a child of a custom AspBlock. var aspBlock = Asp.SymbolTab.AddBlock("News"); aspBlock.IsExpanded = true; aspBlock.Height = 300; @@ -70,19 +68,17 @@ protected override void OnStart() protected override void OnStop() { - // The WebSocketClient must be disposed of in OnStop, - // otherwise it will consume system resources + // The WebSocketClient must be disposed of in OnStop, otherwise it will consume system resources. _webSocketClient.Close(WebSocketClientCloseStatus.NormalClosure); } private void NewsReceived(WebSocketClientTextReceivedEventArgs args) { - // Updading the text inside the TextBlock on every - // piece of news received + // Updading the text inside the TextBlock on every piece of news received. if (args.Text.Length != 0) { _textBlock.Text = args.Text; } } } -} \ No newline at end of file +} diff --git a/Robots/Accelerator Oscillator Sample/Accelerator Oscillator Sample/Accelerator Oscillator Sample.cs b/Robots/Accelerator Oscillator Sample/Accelerator Oscillator Sample/Accelerator Oscillator Sample.cs index 08a1403..012800a 100644 --- a/Robots/Accelerator Oscillator Sample/Accelerator Oscillator Sample/Accelerator Oscillator Sample.cs +++ b/Robots/Accelerator Oscillator Sample/Accelerator Oscillator Sample/Accelerator Oscillator Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The Accelerator Oscillator Sample cBot creates a buy order when the Accelerator Oscillator +// crosses above zero, indicating positive momentum, and a sell order when it crosses below zero. +// Orders are closed by the opposite signal or a stop loss/take profit based on the set parameters. +// Only one buy or sell order is allowed at any time. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,60 +17,75 @@ namespace cAlgo.Robots { - + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AcceleratorOscillatorSample : Robot { - private double _volumeInUnits; - - private AcceleratorOscillator _acceleratorOscillator; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. + + private AcceleratorOscillator _acceleratorOscillator; // Store the Accelerator Oscillator indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, with a default of 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AcceleratorOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders opened by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Accelerator Oscillator to track momentum and generate signals. _acceleratorOscillator = Indicators.AcceleratorOscillator(); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check existing positions and manage them based on the Accelerator Oscillator's signals. foreach (var position in BotPositions) { + // Close buy positions if the oscillator shows a downward signal. + // Close sell positions if the oscillator shows an upward signal. if ((position.TradeType == TradeType.Buy && _acceleratorOscillator.Result.Last(0) < _acceleratorOscillator.Result.Last(1)) || (position.TradeType == TradeType.Sell && _acceleratorOscillator.Result.Last(0) > _acceleratorOscillator.Result.Last(1))) { - ClosePosition(position); + ClosePosition(position); // Close the position when the opposite signal appears. } } + // Evaluate conditions to open new positions based on zero-crossing of the oscillator. + + // If oscillator crosses above zero, a buy signal is generated. if (_acceleratorOscillator.Result.Last(0) > 0 && _acceleratorOscillator.Result.Last(1) <= 0) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If oscillator crosses below zero, a sell signal is generated. else if (_acceleratorOscillator.Result.Last(0) < 0 && _acceleratorOscillator.Result.Last(1) >= 0) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } } -} \ No newline at end of file +} diff --git a/Robots/Accumulative Swing Index Sample/Accumulative Swing Index Sample/Accumulative Swing Index Sample.cs b/Robots/Accumulative Swing Index Sample/Accumulative Swing Index Sample/Accumulative Swing Index Sample.cs index 19cf9ff..8f6ae40 100644 --- a/Robots/Accumulative Swing Index Sample/Accumulative Swing Index Sample/Accumulative Swing Index Sample.cs +++ b/Robots/Accumulative Swing Index Sample/Accumulative Swing Index Sample/Accumulative Swing Index Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The Accumulative Swing Index Sample cBot uses the Accumulative Swing Index (ASI) indicator to generate +// buy signals when it crosses above zero and sell signals when it crosses below zero. Positions are closed +// when an opposite signal is generated or by reaching the stop loss/take profit limits. Only one buy or +// sell position is maintained at any given time. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,62 +17,78 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AccumulativeSwingIndexSample : Robot { - private double _volumeInUnits; - - private AccumulativeSwingIndex _accumulativeSwingIndex; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. + + private AccumulativeSwingIndex _accumulativeSwingIndex; // Store the Accumulative Swing Index indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AccumulativeSwingIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Limit Move Value", DefaultValue = 12, Group = "Accumulative Swing Index", MinValue = 0)] - public int LimitMoveValue { get; set; } + public int LimitMoveValue { get; set; } // ASI limit move value, used to determine the ASI sensitivity. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Accumulative Swing Index with the given limit move value. _accumulativeSwingIndex = Indicators.AccumulativeSwingIndex(LimitMoveValue); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check existing positions and manage them based on the ASI indicator signals. foreach (var position in BotPositions) { + // Close Buy positions if the ASI shows a downward signal. + // Close Sell positions if the ASI shows an upward signal. if ((position.TradeType == TradeType.Buy && _accumulativeSwingIndex.Result.Last(0) < _accumulativeSwingIndex.Result.Last(1)) || (position.TradeType == TradeType.Sell && _accumulativeSwingIndex.Result.Last(0) > _accumulativeSwingIndex.Result.Last(1))) { - ClosePosition(position); + ClosePosition(position); // Close the position when the opposite signal appears. } } + // Evaluate conditions to open new positions based on zero-crossing of the ASI. + + // If ASI crosses above zero, a buy signal is generated. if (_accumulativeSwingIndex.Result.Last(0) > 0 && _accumulativeSwingIndex.Result.Last(1) <= 0) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If ASI crosses below zero, a sell signal is generated. else if (_accumulativeSwingIndex.Result.Last(0) < 0 && _accumulativeSwingIndex.Result.Last(1) >= 0) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } } -} \ No newline at end of file +} diff --git a/Robots/Add Indicator Sample/Add Indicator Sample/Add Indicator Sample.cs b/Robots/Add Indicator Sample/Add Indicator Sample/Add Indicator Sample.cs index 92265c5..c43b87f 100644 --- a/Robots/Add Indicator Sample/Add Indicator Sample/Add Indicator Sample.cs +++ b/Robots/Add Indicator Sample/Add Indicator Sample/Add Indicator Sample.cs @@ -3,8 +3,10 @@ // This code is a cTrader Algo API example. // // The code is provided as a sample only and does not guarantee any particular outcome or profit of any kind. Use it at your own risk. -// -// This sample cBot adds two moving averages for trading to a chart. +// +// This sample cBot adds two moving averages for trading to a chart. The cBot opens a buy position +// when the fast moving average crosses above the slow moving average, and a sell position when the fast +// moving average crosses below the slow moving average. Only one buy or sell position is open at a time. // // For a detailed tutorial on creating this cBot, see this video: https://www.youtube.com/watch?v=DUzdEt30OSE // @@ -16,78 +18,98 @@ namespace cAlgo { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class SampleTrendcBot : Robot { + // Define input parameters for the cBot. [Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)] - public double Quantity { get; set; } + public double Quantity { get; set; } // Trade quantity in lots. [Parameter("MA Type", Group = "Moving Average")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Type of moving average (e.g., Simple, Exponential). [Parameter("Source", Group = "Moving Average")] - public DataSeries SourceSeries { get; set; } + public DataSeries SourceSeries { get; set; } // Data source for moving averages. [Parameter("Slow Periods", Group = "Moving Average", DefaultValue = 10)] - public int SlowPeriods { get; set; } + public int SlowPeriods { get; set; } // Periods for the slow moving average. [Parameter("Fast Periods", Group = "Moving Average", DefaultValue = 5)] - public int FastPeriods { get; set; } + public int FastPeriods { get; set; } // Periods for the fast moving average. - private MovingAverage slowMa; - private MovingAverage fastMa; - private const string label = "Sample Trend cBot"; + // Private fields for the slow and fast moving averages and labels for identifying trades. + private MovingAverage slowMa; // Slow moving average. + private MovingAverage fastMa; // Fast moving average. + private const string label = "Sample Trend cBot"; // Label for tracking cBot positions. + // Fields for visual chart indicators. ChartIndicator _indicator1; ChartIndicator _indicator2; + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Initialise moving averages with specified source, periods and type. fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType); slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType); + // Add the moving averages to the chart as indicators. _indicator1 = Chart.Indicators.Add("Simple Moving Average", SourceSeries, FastPeriods, MAType); _indicator2 = Chart.Indicators.Add("Simple Moving Average", SourceSeries, SlowPeriods, MAType); + // Customise the appearance of the fast moving average indicator line. _indicator1.Lines[0].Color = Color.Red; _indicator1.Lines[0].Thickness = 3; } + // This method is called every time a bar closes. protected override void OnBarClosed() { + // Remove the chart indicators each time a bar closes. Chart.Indicators.Remove(_indicator1); Chart.Indicators.Remove(_indicator2); } + // This method is called on every tick and is used for trade execution logic. protected override void OnTick() { + // Find existing long and short positions for the symbol with the specified label. var longPosition = Positions.Find(label, SymbolName, TradeType.Buy); var shortPosition = Positions.Find(label, SymbolName, TradeType.Sell); + // Retrieve current and previous values for the slow and fast moving averages. var currentSlowMa = slowMa.Result.Last(0); var currentFastMa = fastMa.Result.Last(0); var previousSlowMa = slowMa.Result.Last(1); var previousFastMa = fastMa.Result.Last(1); + // Trade logic based on moving average crossovers. + + // Buy condition - when the slow MA crosses below the fast MA and no long position exists. if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null) { if (shortPosition != null) - ClosePosition(shortPosition); + ClosePosition(shortPosition); // Close any open short position. - ExecuteMarketOrder(TradeType.Buy, SymbolName, VolumeInUnits, label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, VolumeInUnits, label); // Open a new market order to buy. } + + // Sell condition - when the slow MA crosses above the fast MA and no short position exists. else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null) { if (longPosition != null) - ClosePosition(longPosition); + ClosePosition(longPosition); // Close any open long position. - ExecuteMarketOrder(TradeType.Sell, SymbolName, VolumeInUnits, label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, VolumeInUnits, label); // Open a new market order to sell. } } + // Property to calculate and retrieve volume in units based on the specified volume in lots. private double VolumeInUnits { + // Convert the trade quantity in lots to volume in units. get { return Symbol.QuantityToVolumeInUnits(Quantity); } } } -} \ No newline at end of file +} diff --git a/Robots/AddToChart Sample/AddToChart Sample/AddToChart Sample.cs b/Robots/AddToChart Sample/AddToChart Sample/AddToChart Sample.cs index f427a75..71f818b 100644 --- a/Robots/AddToChart Sample/AddToChart Sample/AddToChart Sample.cs +++ b/Robots/AddToChart Sample/AddToChart Sample/AddToChart Sample.cs @@ -4,10 +4,10 @@ // // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. -// -// This sample uses the AddToChart() method to ensure that all indicators used by the cBot -// , namely the MACD Crossover and the RSI, are added to the chart on cBot start. The cBot uses -// both these indicators to guide its trading decisions. Instead of using the AddToChart() method, +// +// This sample uses the AddToChart method to ensure that all indicators used by the cBot, +// namely the MACD Crossover and the RSI, are added to the chart on cBot start. The cBot uses +// both these indicators to guide its trading decisions. Instead of using the AddToChart method, // the sample could have set the AddIndicators property to 'true'. // // ------------------------------------------------------------------------------------------------- @@ -23,38 +23,48 @@ namespace cAlgo.Robots { - // If we set AddIndicators to 'true', we do not have to - // use the AddToChart() method + // Define the cBot attributes. + // If we set AddIndicators to 'true', we do not have to use the AddToChart() method. // [Robot(AccessRights = AccessRights.None, AddIndicators = true)] - [Robot(AccessRights = AccessRights.None)] + public class AddToChartSample : Robot { - + + // Fields for the MACD and RSI indicators used in the cBot trading logic. MacdCrossOver _macd; RelativeStrengthIndex _rsi; + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { - // Initialising our indicators + // Initialise the MACD indicator with parameters for the fast, slow and signal line periods. _macd = Indicators.MacdCrossOver(26, 19, 9); + + // Initialise the RSI indicator with a period of 9, using close prices as the data source. _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 9); - // Adding both our indicators to the chart + // Add both indicators to the chart. _rsi.AddToChart(); _macd.AddToChart(); } + // This method is called every time a bar closes and is used for trade execution logic. protected override void OnBarClosed() { - // Using indicator outputs to execute trading operations + // Trading logic based on indicator values. + + // If MACD histogram is positive and RSI is below or equal to 30, open a buy order. if (_macd.Histogram.LastValue > 0 && _rsi.Result.LastValue <= 30) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000); - } else if (_macd.Histogram.LastValue < 0 && _rsi.Result.LastValue >= 70) + ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000); // Open a market order to buy with a volume of 10,000 units. + } + + // If MACD histogram is negative and RSI is above or equal to 70, open a sell order. + else if (_macd.Histogram.LastValue < 0 && _rsi.Result.LastValue >= 70) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000); + ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000); // Open a market order to sell order with a volume of 10,000 units. } } } -} \ No newline at end of file +} diff --git a/Robots/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs b/Robots/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs index 6a4930b..e5f35b6 100644 --- a/Robots/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs +++ b/Robots/AlgoRegistry Sample/AlgoRegistry Sample/AlgoRegistry Sample.cs @@ -4,7 +4,7 @@ // // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. -// +// // On start, this sample displays a detached window containing a ComboBox and a TextBlock. // Via the AlgoRegistry, the ComboBox is populated with the names of all cBots installed // on the user's machine. When a cBot is selected in the ComboBox, the TextBlock starts @@ -20,26 +20,27 @@ namespace cAlgo.Robots { + // Define the cBot with access rights and the option to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class AlgoRegistrySample : Robot { - // Declaring the required controls and storing - // the name of the cBot selected in the ComboBox + // Declare the required controls and store the name of the cBot selected in the ComboBox. private Window _cBotManagementWindow; private Grid _controlsGrid; private ComboBox _cBotSelectionComboBox; private TextBlock _parametersInfoBlock; private string _selectedCBotName; + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { - // Initialising the Grid + // Initialise a 2x1 Grid layout for arranging ComboBox and TextBlock. _controlsGrid = new Grid(2, 1); - // Initialising the ComboBox and populating it - // with the names of all installed cBots + // Initialise the ComboBox and populate it with the names of all installed cBots. _cBotSelectionComboBox = new ComboBox(); + // Loop through all algorithms, adding cBots only to ComboBox. foreach (var algo in AlgoRegistry) { if (algo.AlgoKind == AlgoKind.Robot) @@ -48,22 +49,21 @@ protected override void OnStart() } } - // Handling the SelectedItemChanged event + // Set up an event handler for ComboBox selection change. _cBotSelectionComboBox.SelectedItemChanged += CBotSelectionComboBoxOnSelectedItemChanged; - // Initialising the TextBlock + // Initialise the TextBlock for displaying selected cBot parameters. _parametersInfoBlock = new TextBlock { LineStackingStrategy = LineStackingStrategy.MaxHeight, TextWrapping = TextWrapping.Wrap, }; - // Adding other controls to the Grid + // Add other controls to Grid layout. _controlsGrid.AddChild(_cBotSelectionComboBox, 0, 0); _controlsGrid.AddChild(_parametersInfoBlock, 1, 0); - // Initialising the Window and adding the Grid - // as a child control + // Initialise the Window, add the Grid as a child and display it. _cBotManagementWindow = new Window { Height = 300, @@ -75,23 +75,22 @@ protected override void OnStart() _cBotManagementWindow.Show(); } + // Event handler to update TextBlock with selected cBot parameters. private void CBotSelectionComboBoxOnSelectedItemChanged(ComboBoxSelectedItemChangedEventArgs obj) { - // Storing the name of the selected cBot - // and changing the text inside the TextBlock - _selectedCBotName = obj.SelectedItem; - _parametersInfoBlock.Text = GenerateParametersInfo(); + _selectedCBotName = obj.SelectedItem; // Store the name of the selected cBot. + _parametersInfoBlock.Text = GenerateParametersInfo(); // Update the text inside the TextBlock. } + // Generate a string containing parameter names and default values of the selected cBot. private string GenerateParametersInfo() { string result = ""; - // Finding the currently selected cBot by its name + // Find the currently selected cBot by its name. var selectedCBot = AlgoRegistry.Get(_selectedCBotName, AlgoKind.Robot) as RobotType; - // Generating strings containing information - // about the parameters of the selected cBot + // Generate strings containing information about the parameters of the selected cBot. foreach (var parameter in selectedCBot.Parameters) { result += $"Param name: {parameter.Name} Param default value: {parameter.DefaultValue}\n"; @@ -101,4 +100,4 @@ private string GenerateParametersInfo() } } -} \ No newline at end of file +} diff --git a/Robots/Alligator Sample/Alligator Sample/Alligator Sample.cs b/Robots/Alligator Sample/Alligator Sample/Alligator Sample.cs index 9ddfc29..0720937 100644 --- a/Robots/Alligator Sample/Alligator Sample/Alligator Sample.cs +++ b/Robots/Alligator Sample/Alligator Sample/Alligator Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Alligator indicator to make automated trading decisions based on price trends. +// It enters a buy or sell position when the Alligator’s Lips and Teeth lines cross, indicating +// potential trend changes. The cBot will also close any open positions of the opposite type to +// prevent conflicting trades. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,83 +17,95 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AlligatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private Alligator _alligator; + private Alligator _alligator; // Store the Alligator indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, with a default of 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AlligatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Jaws Periods", DefaultValue = 13, Group = "Alligator", MinValue = 1)] - public int JawsPeriods { get; set; } + public int JawsPeriods { get; set; } // Number of periods for the Jaws line, with a default of 13 periods. [Parameter("Jaws Shift", DefaultValue = 18, Group = "Alligator", MinValue = 0, MaxValue = 1000)] - public int JawsShift { get; set; } + public int JawsShift { get; set; } // Shift (offset) for the Jaws line, with a default of 18 bars. [Parameter("Teeth Periods", DefaultValue = 8, Group = "Alligator", MinValue = 1)] - public int TeethPeriods { get; set; } + public int TeethPeriods { get; set; } // Number of periods for calculating the Teeth line, with a default of 8 periods. [Parameter("Teeth Shift", DefaultValue = 5, Group = "Alligator", MinValue = 0, MaxValue = 1000)] - public int TeethShift { get; set; } + public int TeethShift { get; set; } // Shift (offset) for the Teeth line, with a default of 5 bars. [Parameter("Lips Periods", DefaultValue = 5, Group = "Alligator", MinValue = 1)] - public int LipsPeriods { get; set; } + public int LipsPeriods { get; set; } // Number of periods for calculating the Lips line, with a default of 5 periods. [Parameter("Lips Shift", DefaultValue = 3, Group = "Alligator", MinValue = 0, MaxValue = 1000)] - public int LipsShift { get; set; } - + public int LipsShift { get; set; } // Shift (offset) for the Lips line, with a default of 3 bars. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Alligator indicator with the configured parameters. _alligator = Indicators.Alligator(JawsPeriods, JawsShift, TeethPeriods, TeethShift, LipsPeriods, LipsShift); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the Lips line has crossed above the Teeth line (indicating a possible buy signal). if (_alligator.Lips.Last(0) > _alligator.Teeth.Last(0) && _alligator.Lips.Last(1) <= _alligator.Teeth.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions before buying. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the Lips line has crossed below the Teeth line (indicating a possible sell signal). else if (_alligator.Lips.Last(0) < _alligator.Teeth.Last(0) && _alligator.Lips.Last(1) >= _alligator.Teeth.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions before selling. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Aroon Sample/Aroon Sample/Aroon Sample.cs b/Robots/Aroon Sample/Aroon Sample/Aroon Sample.cs index 6b98738..7dec330 100644 --- a/Robots/Aroon Sample/Aroon Sample/Aroon Sample.cs +++ b/Robots/Aroon Sample/Aroon Sample/Aroon Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Aroon indicator to trade trend reversals. It opens a buy position when the Aroon +// Up line crosses above the Aroon Down line and a sell position when the Aroon Down line crosses above +// the Aroon Up line. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,68 +16,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AroonSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private Aroon _accumulativeSwingIndex; + private Aroon _accumulativeSwingIndex; // Store the Aroon indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AroonSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Periods", DefaultValue = 25, Group = "Aroon", MinValue = 2)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods, with a default of 25 periods. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Aroon indicator with the specified period. _accumulativeSwingIndex = Indicators.Aroon(Periods); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the Aroon Up line crosses above the Aroon Down line, execute a buy trade. if (_accumulativeSwingIndex.Up.Last(0) > _accumulativeSwingIndex.Down.Last(0) && _accumulativeSwingIndex.Up.Last(1) < _accumulativeSwingIndex.Down.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the Aroon Down line crosses above the Aroon Up line, execute a sell trade. else if (_accumulativeSwingIndex.Up.Last(0) < _accumulativeSwingIndex.Down.Last(0) && _accumulativeSwingIndex.Up.Last(1) > _accumulativeSwingIndex.Down.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample.cs b/Robots/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample.cs index ad7f4de..21e4c6b 100644 --- a/Robots/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample.cs +++ b/Robots/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample/Average Directional Movement Index Rating Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The Average Directional Movement Index Rating (ADXR) Sample cBot opens buy or sell trades +// based on trend strength. When ADXR exceeds a set level, a buy order is placed if DI+ crosses +// above DI-, and a sell if DI- crosses above DI+. The cBot manages risk with stop-loss and +// take-profit settings and closes opposite positions before opening new ones. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,73 +17,88 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AverageDirectionalMovementIndexRatingSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating; + private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating; // Store the ADXR indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AverageDirectionalMovementIndexRatingSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders opened by this cBot. [Parameter("Periods", DefaultValue = 14, Group = "Average Directional Movement Index Ratin")] - public int Periods { get; set; } + public int Periods { get; set; } // Periods setting for the ADXR indicator, defaulting to 14. [Parameter("ADXR Level", DefaultValue = 25, Group = "Average Directional Movement Index Ratin")] - public int ADXRLevel { get; set; } - + public int ADXRLevel { get; set; } // ADXR threshold level for determining if trend is strong enough, defaulting to 25. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the ADXR indicator with specified periods. _averageDirectionalMovementIndexRating = Indicators.AverageDirectionalMovementIndexRating(20); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If ADXR level is below threshold, do not take any trades, indicating weak trend. if (_averageDirectionalMovementIndexRating.ADXR.Last(0) < ADXRLevel) return; + // Check conditions to open a buy or sell position based on DI+ and DI- line crossover. + + // Buy when DI+ crosses above DI-. if (_averageDirectionalMovementIndexRating.DIPlus.Last(0) > _averageDirectionalMovementIndexRating.DIMinus.Last(0) && _averageDirectionalMovementIndexRating.DIPlus.Last(1) <= _averageDirectionalMovementIndexRating.DIMinus.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Sell when DI+ crosses below DI-. else if (_averageDirectionalMovementIndexRating.DIPlus.Last(0) < _averageDirectionalMovementIndexRating.DIMinus.Last(0) && _averageDirectionalMovementIndexRating.DIPlus.Last(1) >= _averageDirectionalMovementIndexRating.DIMinus.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Average True Range Sample/Average True Range Sample/Average True Range Sample.cs b/Robots/Average True Range Sample/Average True Range Sample/Average True Range Sample.cs index ace4bbf..c57bb56 100644 --- a/Robots/Average True Range Sample/Average True Range Sample/Average True Range Sample.cs +++ b/Robots/Average True Range Sample/Average True Range Sample/Average True Range Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Average True Range (ATR) indicator for volatility-based trade management. +// A buy position opens on a bullish candlestick reversal, while a sell opens on a bearish reversal. +// ATR-derived stop-loss and take-profit levels are dynamically set based on volatility. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,75 +17,91 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AverageTrueRangeSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and calculated volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private AverageTrueRange _averageTrueRange; + private AverageTrueRange _averageTrueRange; // Store the ATR indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Label", DefaultValue = "AverageTrueRangeSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter(DefaultValue = 14, Group = "Average True Range", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // ATR calculation period, defaulting to 14. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Average True Range")] - public MovingAverageType MAType { get; set; } - + public MovingAverageType MAType { get; set; } // Moving average type for the ATR, defaulting to Simple. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the ATR indicator with the specified period and moving average type. _averageTrueRange = Indicators.AverageTrueRange(Periods, MAType); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if a bullish candlestick reversal has occurred. if (Bars.ClosePrices.Last(0) > Bars.OpenPrices.Last(0) && Bars.ClosePrices.Last(1) < Bars.OpenPrices.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteOrder(TradeType.Buy); + ExecuteOrder(TradeType.Buy); // Open a new buy order. } + + // Check if a bearish candlestick reversal has occurred. else if (Bars.ClosePrices.Last(0) < Bars.OpenPrices.Last(0) && Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteOrder(TradeType.Sell); + ExecuteOrder(TradeType.Sell); // Open a new sell order. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } + // This method executes a market order based on trade type, with ATR-based stop loss and take profit. private void ExecuteOrder(TradeType tradeType) { + // Calculate the ATR in pips, considering symbol precision and tick size. var atrInPips = _averageTrueRange.Result.Last(0) * (Symbol.TickSize / Symbol.PipSize * Math.Pow(10, Symbol.Digits)); + // Set the stop-loss at twice the ATR and take-profit at four times the ATR. var stopLossInPips = atrInPips * 2; var takeProfitInPips = stopLossInPips * 2; + // Execute a market order with the calculated stop-loss and take-profit. ExecuteMarketOrder(tradeType, SymbolName, _volumeInUnits, Label, stopLossInPips, takeProfitInPips); } } -} \ No newline at end of file +} diff --git a/Robots/Awesome Oscillator Sample/Awesome Oscillator Sample/Awesome Oscillator Sample.cs b/Robots/Awesome Oscillator Sample/Awesome Oscillator Sample/Awesome Oscillator Sample.cs index 4a4cc0c..8e3aad4 100644 --- a/Robots/Awesome Oscillator Sample/Awesome Oscillator Sample/Awesome Oscillator Sample.cs +++ b/Robots/Awesome Oscillator Sample/Awesome Oscillator Sample/Awesome Oscillator Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Awesome Oscillator (AO) to identify momentum and trend direction. +// The cBot opens a buy position when the AO crosses above zero, indicating a potential +// upward momentum shift. It opens a sell position when the AO crosses below zero, +// suggesting a potential downward momentum shift. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,59 +17,72 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class AwesomeOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private AwesomeOscillator _awesomeOscillator; + private AwesomeOscillator _awesomeOscillator; // Store the AO indicator. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "AwesomeOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the AO indicator with the specified period and moving average type. _awesomeOscillator = Indicators.AwesomeOscillator(); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Loop through all positions opened by this cBot to check if they meet close conditions. foreach (var position in BotPositions) { + // If there's a buy position and AO shows a downtrend (crosses below previous value) or + // a sell position and AO shows an uptrend (crosses above previous value), close the position. if ((position.TradeType == TradeType.Buy && _awesomeOscillator.Result.Last(0) < _awesomeOscillator.Result.Last(1)) || (position.TradeType == TradeType.Sell && _awesomeOscillator.Result.Last(0) > _awesomeOscillator.Result.Last(1))) { - ClosePosition(position); + ClosePosition(position); // Close the position. } } + // Check for AO crossing above zero (bullish signal), triggering a buy order. if (_awesomeOscillator.Result.Last(0) > 0 && _awesomeOscillator.Result.Last(1) <= 0) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check for AO crossing below zero (bearish signal), triggering a sell order. else if (_awesomeOscillator.Result.Last(0) < 0 && _awesomeOscillator.Result.Last(1) >= 0) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } } -} \ No newline at end of file +} diff --git a/Robots/BarClosed Example/BarClosed Example/BarClosed Example.cs b/Robots/BarClosed Example/BarClosed Example/BarClosed Example.cs index 45309b4..fcbf3d1 100644 --- a/Robots/BarClosed Example/BarClosed Example/BarClosed Example.cs +++ b/Robots/BarClosed Example/BarClosed Example/BarClosed Example.cs @@ -1,3 +1,15 @@ +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This cBot is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// This cBot checks if the closing price of the last bar is more than 0.5% above its low. If true, +// it closes all open positions and opens a buy position with a 50 pip stop loss. +// +// ------------------------------------------------------------------------------------------------- + using System; using System.Collections.Generic; using System.Linq; @@ -9,20 +21,27 @@ namespace cAlgo.Robots { + // Define the cBot class with no specific access rights. [Robot(AccessRights = AccessRights.None)] public class BarClosedExample : Robot { + // This method is triggered when a bar is closed. protected override void OnBarClosed() { + // Calculate the percentage difference between the closing price and the low price of the last bar. var lowCloseDifference = ((Bars.LastBar.Close - Bars.LastBar.Low) / Bars.LastBar.Close) * 100; + + // Check if the percentage difference is greater than 0.5% (i.e., the bar closed significantly above its low). if (lowCloseDifference > 0.5) { + // If the condition is met, close all open positions. foreach (var position in Positions) { - position.Close(); + position.Close(); // Close the position. } - ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, null, 50); + ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, null, 50); // Place a new buy market order with a volume of 10,000 units and a stop loss of 50 pips. + } } } -} \ No newline at end of file +} diff --git a/Robots/BarOpened Example/BarOpened Example/BarOpened Example.cs b/Robots/BarOpened Example/BarOpened Example/BarOpened Example.cs index 4afc217..07b578f 100644 --- a/Robots/BarOpened Example/BarOpened Example/BarOpened Example.cs +++ b/Robots/BarOpened Example/BarOpened Example/BarOpened Example.cs @@ -1,3 +1,16 @@ +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This cBot is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// This cBot evaluates the price difference between the opening prices of the current and previous bars. +// If the price difference is greater than 1%, it opens a buy order. If the difference is less than -1%, +// it opens a sell order. Otherwise, it closes all open positions. +// +// ------------------------------------------------------------------------------------------------- + using System; using System.Collections.Generic; using System.Linq; @@ -9,29 +22,39 @@ namespace cAlgo.Robots { + // Define the cBot class with no specific access rights. [Robot(AccessRights = AccessRights.None)] public class BarOpenedExample : Robot { + // This method is triggered when a new bar is created. protected override void OnBar() { + // Get the previous bar's data (the bar before the most recent one). var previousBar = Bars[Bars.Count - 2]; + + // Calculate the percentage difference between the current and previous bar's opening price. var priceDifference = ((Bars.LastBar.Open - previousBar.Open) / previousBar.Open) * 100; + // If price difference is greater than 1%, place a buy order. if (priceDifference > 1) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000); + ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000); // Place a new buy market order with a volume of 10,000 units. } + + // If price difference is less than -1%, execute a sell order. else if (priceDifference < -1) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000); + ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000); // Place a new sell market order with a volume of 10,000 units. } + + // If the price difference is between -1% and 1%, close all open positions. else { foreach (var position in Positions) { - position.Close(); + position.Close(); // Close the position. } } } } -} \ No newline at end of file +} diff --git a/Robots/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample.cs b/Robots/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample.cs index e7d2e92..c16c86e 100644 --- a/Robots/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample.cs +++ b/Robots/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample/BarsHistoryLoadedEventArgs Sample.cs @@ -1,4 +1,4 @@ -using cAlgo.API; +using cAlgo.API; namespace cAlgo.Robots { @@ -24,4 +24,4 @@ private void Bars_HistoryLoaded(BarsHistoryLoadedEventArgs obj) Print("Loaded Bars Count: {0}", obj.Count); } } -} \ No newline at end of file +} diff --git a/Robots/Bollinger Bands Sample/Bollinger Bands Sample/Bollinger Bands Sample.cs b/Robots/Bollinger Bands Sample/Bollinger Bands Sample/Bollinger Bands Sample.cs index 0d4fa79..3da66cf 100644 --- a/Robots/Bollinger Bands Sample/Bollinger Bands Sample/Bollinger Bands Sample.cs +++ b/Robots/Bollinger Bands Sample/Bollinger Bands Sample/Bollinger Bands Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses Bollinger Bands to identify potential overbought or oversold conditions. +// When the price closes below the lower band, it opens a buy order, and when it closes above the upper band, it opens a sell order. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,74 +15,84 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class BollingerBandsSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store trade volume in units calculated based on the specified lot size. - private BollingerBands _bollingerBands; + private BollingerBands _bollingerBands; // Store the Bollinger Bands indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Label", DefaultValue = "BollingerBandsSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Bollinger Bands")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data series used as the source for Bollinger Bands calculation. [Parameter(DefaultValue = 20, Group = "Bollinger Bands", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Period for calculating the Bollinger Bands, default is 20. [Parameter("Standard Dev", DefaultValue = 2.0, Group = "Bollinger Bands", MinValue = 0.0001, MaxValue = 10)] - public double StandardDeviations { get; set; } + public double StandardDeviations { get; set; } // Standard deviation multiplier for the bands, default is 2. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Bollinger Bands")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Type of moving average used in Bollinger Bands, default is Simple. [Parameter("Shift", DefaultValue = 0, Group = "Bollinger Bands", MinValue = -1000, MaxValue = 1000)] - public int Shift { get; set; } - + public int Shift { get; set; } // Shift of Bollinger Bands, default is 0. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Bollinger Bands indicator with specified parameters. _bollingerBands = Indicators.BollingerBands(Source, Periods, StandardDeviations, MAType); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the price has crossed below the lower Bollinger Band. if (Bars.LowPrices.Last(0) <= _bollingerBands.Bottom.Last(0) && Bars.LowPrices.Last(1) > _bollingerBands.Bottom.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); // Open a new buy market order. } else if (Bars.HighPrices.Last(0) >= _bollingerBands.Top.Last(0) && Bars.HighPrices.Last(1) < _bollingerBands.Top.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); // Open a new sell market order. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Center Of Gravity Sample/Center Of Gravity Sample/Center Of Gravity Sample.cs b/Robots/Center Of Gravity Sample/Center Of Gravity Sample/Center Of Gravity Sample.cs index 0395aa7..2ad2e4f 100644 --- a/Robots/Center Of Gravity Sample/Center Of Gravity Sample/Center Of Gravity Sample.cs +++ b/Robots/Center Of Gravity Sample/Center Of Gravity Sample/Center Of Gravity Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Center of Gravity (CoG) indicator to identify potential buy and sell signals +// based on crossover points between the CoG Result and Lag lines. It enters buy or sell trades +// when crossover conditions are met and manages open positions with specified stop-loss and +// take-profit settings. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,70 +18,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class CenterOfGravitySample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private CenterOfGravity _centerOfGravity; + private CenterOfGravity _centerOfGravity; // Store the Center of Gravity indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "CenterOfGravitySample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter(DefaultValue = 10, Group = "Center Of Gravity", MinValue = 1)] - public int Length { get; set; } - - - + public int Length { get; set; } // Length parameter for calculating the Center of Gravity, default is 10. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Center of Gravity indicator with the specified length. _centerOfGravity = Indicators.CenterOfGravity(Length); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the Center of Gravity Result line has crossed above the Lag line. if (_centerOfGravity.Result.Last(0) > _centerOfGravity.Lag.Last(0) && _centerOfGravity.Result.Last(1) <= _centerOfGravity.Lag.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // Check if the Center of Gravity Result line has crossed below the Lag line else if (_centerOfGravity.Result.Last(0) < _centerOfGravity.Lag.Last(0) && _centerOfGravity.Result.Last(1) >= _centerOfGravity.Lag.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Chaikin Money Flow Sample/Chaikin Money Flow Sample/Chaikin Money Flow Sample.cs b/Robots/Chaikin Money Flow Sample/Chaikin Money Flow Sample/Chaikin Money Flow Sample.cs index 216ce65..43b517f 100644 --- a/Robots/Chaikin Money Flow Sample/Chaikin Money Flow Sample/Chaikin Money Flow Sample.cs +++ b/Robots/Chaikin Money Flow Sample/Chaikin Money Flow Sample/Chaikin Money Flow Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Chaikin Money Flow (CMF) indicator to identify bullish and bearish signals. +// It enters buy or sell trades when the CMF crosses the zero line, indicating a potential change +// in buying or selling pressure, and uses stop-loss and take-profit settings to manage risk. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,67 +16,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class ChaikinMoneyFlowSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private ChaikinMoneyFlow _chaikinMoneyFlow; + private ChaikinMoneyFlow _chaikinMoneyFlow; // Store the Chaikin Money Flow indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "ChaikinMoneyFlowSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter(DefaultValue = 14, Group = "Chaikin Money Flow", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Period length for calculating the CMF, default is 14. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Chaikin Money Flow indicator with the specified period. _chaikinMoneyFlow = Indicators.ChaikinMoneyFlow(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the CMF has crossed above zero, indicating potential buying pressure. if (_chaikinMoneyFlow.Result.Last(0) > 0 && _chaikinMoneyFlow.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // Check if the CMF has crossed below zero, indicating potential selling pressure. else if (_chaikinMoneyFlow.Result.Last(0) < 0 && _chaikinMoneyFlow.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Chaikin Volatility Sample/Chaikin Volatility Sample/Chaikin Volatility Sample.cs b/Robots/Chaikin Volatility Sample/Chaikin Volatility Sample/Chaikin Volatility Sample.cs index 0e5dd52..69b282b 100644 --- a/Robots/Chaikin Volatility Sample/Chaikin Volatility Sample/Chaikin Volatility Sample.cs +++ b/Robots/Chaikin Volatility Sample/Chaikin Volatility Sample/Chaikin Volatility Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Chaikin Volatility indicator to detect significant volatility levels and +// confirms trade entries using a moving average. It enters buy or sell trades based on price +// crossover with the moving average, combined with high volatility signals. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,85 +16,99 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class ChaikinVolatilitySample : Robot { - private double _volumeInUnits; + // Private fields to store trade volume and indicators. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private ChaikinVolatility _chaikinVolatility; + private ChaikinVolatility _chaikinVolatility; // Chaikin Volatility indicator to detect market volatility. - private MovingAverage _movingAverage; + private MovingAverage _movingAverage; // Moving Average for trade entry confirmation. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "ChaikinVolatilitySample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders opened by this bot. [Parameter(DefaultValue = 14, Group = "Chaikin Volatility", MinValue = 1)] - public int ChaikinPeriods { get; set; } + public int ChaikinPeriods { get; set; } // Periods for Chaikin Volatility calculation, defaulting to 14. [Parameter("Rate of Change", DefaultValue = 10, Group = "Chaikin Volatility", MinValue = 0)] - public int RateOfChange { get; set; } + public int RateOfChange { get; set; } // Rate of change for Chaikin Volatility, defaulting to 10. [Parameter("MA Type Chaikin", Group = "Chaikin Volatility")] - public MovingAverageType MATypeChaikin { get; set; } + public MovingAverageType MATypeChaikin { get; set; } // Type of moving average for Chaikin Volatility. [Parameter(DefaultValue = 14, Group = "Moving Average", MinValue = 1)] - public int SmaPeriods { get; set; } + public int SmaPeriods { get; set; } // Periods for the moving average used in trade confirmation, defaulting to 14. [Parameter("MA Type", Group = "Moving Average")] - public MovingAverageType MAType { get; set; } - + public MovingAverageType MAType { get; set; } // Type of moving average for trade confirmation. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Chaikin Volatility indicator with the specified parameters. _chaikinVolatility = Indicators.ChaikinVolatility(ChaikinPeriods, RateOfChange, MATypeChaikin); + // Initialise the Moving Average indicator with the specified parameters. _movingAverage = Indicators.MovingAverage(Bars.ClosePrices, SmaPeriods, MAType); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Execute trades only when volatility is high (Chaikin Volatility > 0). if (_chaikinVolatility.Result.Last(0) > 0) { + // Buy signal: price crosses above moving average. if (Bars.ClosePrices.Last(0) > _movingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) < _movingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // Sell signal: price crosses below moving average. else if (Bars.ClosePrices.Last(0) < _movingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) > _movingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + + // Close all positions when volatility condition is not met. else { - ClosePositions(); + ClosePositions(); // Close all positions. } } + // This method closes all open positions that were created by this bot. private void ClosePositions() { foreach (var position in BotPositions) { - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/ChartId Sample/ChartId Sample/ChartId Sample.cs b/Robots/ChartId Sample/ChartId Sample/ChartId Sample.cs index 721ad7f..42320da 100644 --- a/Robots/ChartId Sample/ChartId Sample/ChartId Sample.cs +++ b/Robots/ChartId Sample/ChartId Sample/ChartId Sample.cs @@ -4,7 +4,7 @@ // // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. -// +// // This sample accesses the Chart.Id property of the chart to which it is attached. // When the BarClosed event is triggered, the cBot places a new market order and prints data // to the log. @@ -22,16 +22,20 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class ChartIdSample : Robot { + // A list to store log entries for order placement details. private List _operationsCache = new List(); + // This method is triggered every time a bar (candlestick) closes. protected override void OnBarClosed() { + // Place a buy market order of 10,000 units and log the order and the chart details. ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000); Print($"{DateTime.Now.ToShortTimeString()}: Order Placed on Chart {Chart.Id}"); } } -} \ No newline at end of file +} diff --git a/Robots/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs b/Robots/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs index 4d1fa0d..96ecc53 100644 --- a/Robots/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs +++ b/Robots/ChartIndicators Sample/ChartIndicators Sample/ChartIndicators Sample.cs @@ -4,7 +4,7 @@ // // This code is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. -// +// // This sample displays a custom detached window there the user is able to select // an indicator from among the indicators attached to the instance chart. When an // indicator is selected, the user can press on a button to remove it from the chart @@ -92,4 +92,4 @@ private void OnClick(ButtonClickEventArgs obj) ChartIndicators.Remove(_selectedIndicator); } } -} \ No newline at end of file +} diff --git a/Robots/Close All On Market Close Sample/Close All On Market Close Sample/Close All On Market Close Sample.cs b/Robots/Close All On Market Close Sample/Close All On Market Close Sample/Close All On Market Close Sample.cs index e49c4dd..4b381d0 100644 --- a/Robots/Close All On Market Close Sample/Close All On Market Close Sample/Close All On Market Close Sample.cs +++ b/Robots/Close All On Market Close Sample/Close All On Market Close Sample/Close All On Market Close Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot automatically closes all open positions shortly before the market closes, based on +// the specified time buffer. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,16 +16,19 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class CloseAllOnMarketCloseSample : Robot { - private TimeSpan _closeBeforeTime; + private TimeSpan _closeBeforeTime; // Store the parsed time span to close positions before market close. [Parameter("Close Before", DefaultValue = "00:05:00")] - public string CloseBeforeTime { get; set; } + public string CloseBeforeTime { get; set; } // Buffer time before market close for closing positions. + // This method is called when the bot starts. protected override void OnStart() { + // Parses the CloseBeforeTime parameter; stops the bot if parsing fails. if (!TimeSpan.TryParse(CloseBeforeTime, CultureInfo.InvariantCulture, out _closeBeforeTime)) { Print("You have provided invalid value for Close Before parameter"); @@ -30,19 +36,22 @@ protected override void OnStart() Stop(); } - Timer.Start(1); + Timer.Start(1); // Starts a timer to check every second for the market closing time. } + // This method is triggered by the Timer at regular intervals. protected override void OnTimer() { - var timeTillClose = Symbol.MarketHours.TimeTillClose(); + var timeTillClose = Symbol.MarketHours.TimeTillClose(); // Retrieves time left until market close. + // If the market is closed or the time till close is greater than the buffer, exit the method. if (!Symbol.MarketHours.IsOpened() || timeTillClose > _closeBeforeTime) return; + // Loops through all open positions and closes each one. foreach (var position in Positions) { - ClosePosition(position); + ClosePosition(position); // Closes the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Commodity Channel Index Sample/Commodity Channel Index Sample/Commodity Channel Index Sample.cs b/Robots/Commodity Channel Index Sample/Commodity Channel Index Sample/Commodity Channel Index Sample.cs index 6b57c15..bf93b48 100644 --- a/Robots/Commodity Channel Index Sample/Commodity Channel Index Sample/Commodity Channel Index Sample.cs +++ b/Robots/Commodity Channel Index Sample/Commodity Channel Index Sample/Commodity Channel Index Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample demonstrates the use of the Commodity Channel Index (CCI) to execute trades +// when the CCI crosses over specific threshold values (up and down levels). +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,74 +15,84 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class CommodityChannelIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private CommodityChannelIndex _commodityChannelIndex; + private CommodityChannelIndex _commodityChannelIndex; // Store the Commodity Channel Index indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "CommodityChannelIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter(DefaultValue = 20, Group = "Commodity Channel Index", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Periods for the CCI calculation, with a default of 20 periods. [Parameter("Down level", DefaultValue = -100, Group = "Commodity Channel Index")] - public int DownValue { get; set; } + public int DownValue { get; set; } // The down level threshold for the CCI, defaulting to -100. [Parameter("Up level", DefaultValue = 100, Group = "Commodity Channel Index")] - public int UpValue { get; set; } - + public int UpValue { get; set; } // The up level threshold for the CCI, defaulting to 100. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified lot size to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Commodity Channel Index indicator with the specified period. _commodityChannelIndex = Indicators.CommodityChannelIndex(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the CCI crosses above the up level, close any sell positions and place a buy order. if (_commodityChannelIndex.Result.Last(0) > UpValue && _commodityChannelIndex.Result.Last(1) <= UpValue) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } else if (_commodityChannelIndex.Result.Last(0) < DownValue && _commodityChannelIndex.Result.Last(1) >= DownValue) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Compilation Robot/Compilation Robot/Compilation Robot.cs b/Robots/Compilation Robot/Compilation Robot/Compilation Robot.cs index 6076972..b6a6857 100644 --- a/Robots/Compilation Robot/Compilation Robot/Compilation Robot.cs +++ b/Robots/Compilation Robot/Compilation Robot/Compilation Robot.cs @@ -19,19 +19,25 @@ namespace cAlgo.Robots { + // Define the cBot attributes, including AccessRights. [Robot(AccessRights = AccessRights.FullAccess)] public class CompilationRobot : Robot { + // This method is called when the bot starts. protected override void OnStart() { + // Initialise compilation options with custom settings for the algo file. CompilationOptions options = new CompilationOptions { - IncludeSourceCode = true, - OutputAlgoFilePath = @"C:\Users\{preferred path}\NameOfAlgo.algo" + IncludeSourceCode = true, // Set to include the source code in the compiled output. + OutputAlgoFilePath = @"C:\Users\{preferred path}\NameOfAlgo.algo" // Specify the path for saving the compiled algo file. }; + // Compile the specified .csproj file with the defined options. CompilationResult resultSync = Compiler.Compile(@"C:\Users\{path to project}\NameOfCbot.csproj", options); + + // Output compilation success or failure to the log. Print(resultSync.Succeeded); } } diff --git a/Robots/Custom Fitness Functions/Custom Fitness Functions/Custom Fitness Functions.cs b/Robots/Custom Fitness Functions/Custom Fitness Functions/Custom Fitness Functions.cs index 649397b..42bd280 100644 --- a/Robots/Custom Fitness Functions/Custom Fitness Functions/Custom Fitness Functions.cs +++ b/Robots/Custom Fitness Functions/Custom Fitness Functions/Custom Fitness Functions.cs @@ -5,12 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // -// All changes to this file might be lost on the next application update. -// If you are going to modify this file please make a copy using the "Duplicate" command. -// // This example is based on the "Sample Trend cBot". The "Sample Trend cBot" will buy when fast period moving average crosses the slow period moving average and sell when // the fast period moving average crosses the slow period moving average. The orders are closed when an opposite signal -// is generated. There can only by one Buy or Sell order at any time. The bot also includes a custom fitness function for optimisation. +// is generated. There can only by one buy or sell order at any time. The bot also includes a custom fitness function for optimisation. // // ------------------------------------------------------------------------------------------------- @@ -21,75 +18,85 @@ namespace cAlgo { + // Define the cBot's configuration, including time zone and access rights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class CustomFitnessFunctions : Robot { + // Define input parameters for the cBot. [Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)] - public double Quantity { get; set; } + public double Quantity { get; set; } // Trade volume in lots, with a default of 0.01 lots. [Parameter("MA Type", Group = "Moving Average")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Type of moving average to use (e.g., SMA, EMA). [Parameter("Source", Group = "Moving Average")] - public DataSeries SourceSeries { get; set; } + public DataSeries SourceSeries { get; set; } // Data series to calculate the moving average on. [Parameter("Slow Periods", Group = "Moving Average", DefaultValue = 10)] - public int SlowPeriods { get; set; } + public int SlowPeriods { get; set; } // Number of periods for the slow moving average, with a default of 10 periods. [Parameter("Fast Periods", Group = "Moving Average", DefaultValue = 5)] - public int FastPeriods { get; set; } + public int FastPeriods { get; set; } // Number of periods for the fast moving average, with a default of 5 periods. - private MovingAverage slowMa; - private MovingAverage fastMa; - private const string label = "Sample Trend cBot"; + private MovingAverage slowMa; // Slow moving average instance. + private MovingAverage fastMa; // Fast moving average instance. + private const string label = "Sample Trend cBot"; // Label for identifying positions by the bot. + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { - fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType); - slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType); + fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType); // Initialise fast moving average. + slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType); // Initialise slow moving average. } + // This method is called on each tick update. protected override void OnTick() { - var longPosition = Positions.Find(label, SymbolName, TradeType.Buy); - var shortPosition = Positions.Find(label, SymbolName, TradeType.Sell); + var longPosition = Positions.Find(label, SymbolName, TradeType.Buy); // Check for existing buy position. + var shortPosition = Positions.Find(label, SymbolName, TradeType.Sell); // Check for existing sell position. - var currentSlowMa = slowMa.Result.Last(0); - var currentFastMa = fastMa.Result.Last(0); - var previousSlowMa = slowMa.Result.Last(1); - var previousFastMa = fastMa.Result.Last(1); + var currentSlowMa = slowMa.Result.Last(0); // Current value of slow moving average. + var currentFastMa = fastMa.Result.Last(0); // Current value of fast moving average. + var previousSlowMa = slowMa.Result.Last(1); // Previous value of slow moving average. + var previousFastMa = fastMa.Result.Last(1); // Previous value of fast moving average. + // Buy condition: fast MA crosses above slow MA; close any existing sell position. if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null) { if (shortPosition != null) - ClosePosition(shortPosition); + ClosePosition(shortPosition); // Close any existing sell position. - ExecuteMarketOrder(TradeType.Buy, SymbolName, VolumeInUnits, label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, VolumeInUnits, label); // Open a new buy market order. } + + // Sell condition: fast MA crosses below slow MA; close any existing buy position. else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null) { if (longPosition != null) - ClosePosition(longPosition); + ClosePosition(longPosition); // Close any existing buy position. - ExecuteMarketOrder(TradeType.Sell, SymbolName, VolumeInUnits, label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, VolumeInUnits, label); // Open a new sell market order. } } + // Calculate trading volume in units based on the specified lot quantity. private double VolumeInUnits { get { return Symbol.QuantityToVolumeInUnits(Quantity); } } + // Custom fitness function for optimizing the cBot's performance. protected override double GetFitness(GetFitnessArgs args) { + // Checks trade count and drawdown percentage to calculate a custom fitness score. if (args.TotalTrades > 20 && args.MaxEquityDrawdownPercentages < 50) { return Math.Pow(args.WinningTrades + 1, 2) / (args.LosingTrades + 1); } else { - return double.MinValue; + return double.MinValue; // Penalize cases that don't meet the criteria. } } } -} \ No newline at end of file +} diff --git a/Robots/CustomHandlers Example/CustomHandlers Example/CustomHandlers Example.cs b/Robots/CustomHandlers Example/CustomHandlers Example/CustomHandlers Example.cs index 7e4554b..e93106d 100644 --- a/Robots/CustomHandlers Example/CustomHandlers Example/CustomHandlers Example.cs +++ b/Robots/CustomHandlers Example/CustomHandlers Example/CustomHandlers Example.cs @@ -1,3 +1,16 @@ +// ------------------------------------------------------------------------------------------------- +// +// This code is a cTrader Algo API example. +// +// This cBot is intended to be used as a sample and does not guarantee any particular outcome or +// profit of any kind. Use it at your own risk. +// +// This sample cBot listens to bar opening events and performs trade operations based on +// simple bullish and bearish reversal patterns. +// +// ------------------------------------------------------------------------------------------------- + + using System; using System.Collections.Generic; using System.Linq; @@ -9,30 +22,35 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as access rights. [Robot(AccessRights = AccessRights.None)] public class CustomHandlersExample : Robot { + // This method is called once at the start of the cBot's execution. protected override void OnStart() { - Bars.BarOpened += BullishReversal; - Bars.BarOpened += BearishReversal; + Bars.BarOpened += BullishReversal; // Add event handler for detecting bullish reversals. + Bars.BarOpened += BearishReversal; // Adds event handler for detecting bearish reversals. } - + // Handler method to check and execute trades for a bullish reversal. private void BullishReversal(BarOpenedEventArgs args) { + // Checks for a bullish reversal condition based on previous bar closes. if (Bars.LastBar.Open > Bars.Last(1).Close && Bars.LastBar.Open > Bars.Last(2).Close) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, 10, 50); + ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, null, 10, 50); // Places a buy market order if the bullish reversal condition is met. } } - + + // Handler method to check and execute trades for a bearish reversal. private void BearishReversal(BarOpenedEventArgs args) { + // Checks for a bearish reversal condition based on previous bar closes. if (Bars.LastBar.Open < Bars.Last(1).Close && Bars.LastBar.Open < Bars.Last(2).Close) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000, null, 10, 50); + ExecuteMarketOrder(TradeType.Sell, SymbolName, 10000, null, 10, 50); // Places a sell market order if the bearish reversal condition is met. } } diff --git a/Robots/Cyber Cycle Sample/Cyber Cycle Sample/Cyber Cycle Sample.cs b/Robots/Cyber Cycle Sample/Cyber Cycle Sample/Cyber Cycle Sample.cs index 33aa3c5..1279fc2 100644 --- a/Robots/Cyber Cycle Sample/Cyber Cycle Sample/Cyber Cycle Sample.cs +++ b/Robots/Cyber Cycle Sample/Cyber Cycle Sample/Cyber Cycle Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample cBot uses the Cyber Cycle indicator to identify buy and sell opportunities +// when the Cycle and Trigger lines cross. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,68 +16,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class CyberCycleSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private CyberCycle _cyberCycle; + private CyberCycle _cyberCycle; // Store the Cyber Cycle indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "CyberCycleSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Alpha", DefaultValue = 0.07, Group = "Cyber Cycle", MinValue = 0.01, MaxValue = 100, Step = 0.01)] - public double Alpha { get; set; } - + public double Alpha { get; set; } // Sets the Alpha parameter for the Cyber Cycle indicator. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Cyber Cycle indicator with the specified Alpha parameter. _cyberCycle = Indicators.CyberCycle(Alpha); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Buy if the Cycle line crosses above the Trigger line. if (_cyberCycle.Cycle.Last(0) > _cyberCycle.Trigger.Last(0) && _cyberCycle.Cycle.Last(1) <= _cyberCycle.Trigger.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Closes any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // Sell if the Cycle line crosses below the Trigger line. else if (_cyberCycle.Cycle.Last(0) < _cyberCycle.Trigger.Last(0) && _cyberCycle.Cycle.Last(1) >= _cyberCycle.Trigger.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Closes any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample.cs b/Robots/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample.cs index 19b8975..7a7d276 100644 --- a/Robots/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample.cs +++ b/Robots/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample/Detrended Price Oscillator Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilizes the Detrended Price Oscillator (DPO) to identify buy and sell signals +// based on oscillator crossovers with the zero line. When the DPO crosses above zero, the bot +// closes any existing sell positions and opens a buy order. Conversely, when the DPO crosses +// below zero, it closes any existing buy positions and opens a sell order. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,70 +17,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class DetrendedPriceOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private DetrendedPriceOscillator _detrendedPriceOscillator; + private DetrendedPriceOscillator _detrendedPriceOscillator; // Store the DPO indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, default of 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, default of 10 pips. [Parameter("Label", DefaultValue = "DetrendedPriceOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 21, Group = "Detrended Price Oscillator", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods, default of 21 periods. [Parameter("MA Type", Group = "Detrended Price Oscillator")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Type of moving average for the DPO calculation. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the DPO indicator with the specified parameters. _detrendedPriceOscillator = Indicators.DetrendedPriceOscillator(Bars.ClosePrices, Periods, MAType); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the DPO crosses above zero, execute a buy trade. if (_detrendedPriceOscillator.Result.Last(0) > 0 && _detrendedPriceOscillator.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the DPO crosses below zero, execute a sell trade. else if (_detrendedPriceOscillator.Result.Last(0) < 0 && _detrendedPriceOscillator.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Directional Movement System Sample/Directional Movement System Sample/Directional Movement System Sample.cs b/Robots/Directional Movement System Sample/Directional Movement System Sample/Directional Movement System Sample.cs index 5f4753e..46323c3 100644 --- a/Robots/Directional Movement System Sample/Directional Movement System Sample/Directional Movement System Sample.cs +++ b/Robots/Directional Movement System Sample/Directional Movement System Sample/Directional Movement System Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Directional Movement System (DMS) to trade based on trend strength and direction. +// It opens a buy position when the +DI line crosses above the -DI line and a sell position when the +// -DI line crosses above the +DI line, provided the ADX value is above a specified level. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,72 +16,86 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class DirectionalMovementSystemSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private DirectionalMovementSystem _directionalMovementSystem; + private DirectionalMovementSystem _directionalMovementSystem; // Store the DMS indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, default of 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, default of 10 pips. [Parameter("Label", DefaultValue = "DirectionalMovementSystemSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter(DefaultValue = 14, Group = "Directional Movement System", MinValue = 1, MaxValue = 10000)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods for the DMS calculation, default of 14 periods. [Parameter("ADX Level", DefaultValue = 25, Group = "Directional Movement System")] - public int ADXLevel { get; set; } + public int ADXLevel { get; set; } // ADX level threshold, default is 25. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the DMS indicator with the specified period. _directionalMovementSystem = Indicators.DirectionalMovementSystem(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If ADX is below the specified level, avoid trading. if (_directionalMovementSystem.ADX.Last(0) < ADXLevel) return; + // If +DI crosses above -DI, execute a buy trade. if (_directionalMovementSystem.DIPlus.Last(0) > _directionalMovementSystem.DIMinus.Last(0) && _directionalMovementSystem.DIPlus.Last(1) <= _directionalMovementSystem.DIMinus.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If -DI crosses above +DI, execute a sell trade. else if (_directionalMovementSystem.DIPlus.Last(0) < _directionalMovementSystem.DIMinus.Last(0) && _directionalMovementSystem.DIPlus.Last(1) >= _directionalMovementSystem.DIMinus.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Discord Message Example/Discord Message Example/Discord Message Example.cs b/Robots/Discord Message Example/Discord Message Example/Discord Message Example.cs index d3ecbcc..3b9171c 100644 --- a/Robots/Discord Message Example/Discord Message Example/Discord Message Example.cs +++ b/Robots/Discord Message Example/Discord Message Example/Discord Message Example.cs @@ -20,37 +20,47 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class DiscordMessageExample : Robot { + // Parameters for the Discord bot token and channel ID. [Parameter("Discord Bot Token")] - public string BotToken { get; set; } + public string BotToken { get; set; } // Discord bot token for authentication. [Parameter("Discord Channel ID")] - public string ChannelID { get; set; } + public string ChannelID { get; set; } // Channel ID where the message will be sent. - DiscordSocketClient _discordSocketClient; - IMessageChannel _channel; + // Declare private fields for the Discord client and channel. + DiscordSocketClient _discordSocketClient; // Discord client to interact with Discord API. + IMessageChannel _channel; // The channel where messages will be sent. + // This method is called when the cBot starts. protected override void OnStart() { + // Initialise the Discord client and log in using the bot token. _discordSocketClient = new DiscordSocketClient(); - _discordSocketClient.LoginAsync(TokenType.Bot, BotToken); - _discordSocketClient.StartAsync(); + _discordSocketClient.LoginAsync(TokenType.Bot, BotToken); // Log into Discord using the bot token. + _discordSocketClient.StartAsync(); // Start the Discord client asynchronously. + // Convert the provided channel ID to ulong and get the channel to send messages to. var channelID = Convert.ToUInt64(ChannelID); _channel = _discordSocketClient.GetChannelAsync(channelID).Result as IMessageChannel; + + // Send a message indicating the cBot has started. _channel.SendMessageAsync("Example cBot Started"); } + // This method is called on every tick. protected override void OnTick() { // Handle price updates here } + // This method is called when the cBot stops. protected override void OnStop() { // Handle cBot stop here } } -} \ No newline at end of file +} diff --git a/Robots/Donchian Channel Sample/Donchian Channel Sample/Donchian Channel Sample.cs b/Robots/Donchian Channel Sample/Donchian Channel Sample/Donchian Channel Sample.cs index 5f6ff8e..c901228 100644 --- a/Robots/Donchian Channel Sample/Donchian Channel Sample/Donchian Channel Sample.cs +++ b/Robots/Donchian Channel Sample/Donchian Channel Sample/Donchian Channel Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This example cBot uses the Donchian Channel to identify breakouts. It opens a buy position when the price +// crosses above the upper Donchian Channel band and a sell position when the price crosses below the lower +// Donchian Channel band. It also manages positions by closing opposite trades based on the breakout signals. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,62 +16,74 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class DonchianChannelSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private DonchianChannel _donchianChannel; + private DonchianChannel _donchianChannel; // Store the Donchian Channel indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Label", DefaultValue = "DonchianChannelSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 20, Group = "Donchian Channel", MinValue = 1)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods for the Donchian Channel, defaulting to 20. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Donchian Channel indicator with the specified period. _donchianChannel = Indicators.DonchianChannel(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the price crosses below the lower Donchian Channel, execute a buy trade. if (Bars.LowPrices.Last(0) <= _donchianChannel.Bottom.Last(0) && Bars.LowPrices.Last(1) > _donchianChannel.Bottom.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open Sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); // Open a buy market order with the specified volume. } + + // If the price crosses above the upper Donchian Channel, execute a Sell trade. else if (Bars.HighPrices.Last(0) >= _donchianChannel.Top.Last(0) && Bars.HighPrices.Last(1) < _donchianChannel.Top.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); // Open a sell market order with the specified volume. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Ease Of Movement Sample/Ease Of Movement Sample/Ease Of Movement Sample.cs b/Robots/Ease Of Movement Sample/Ease Of Movement Sample/Ease Of Movement Sample.cs index 47a0d18..8bdc6e1 100644 --- a/Robots/Ease Of Movement Sample/Ease Of Movement Sample/Ease Of Movement Sample.cs +++ b/Robots/Ease Of Movement Sample/Ease Of Movement Sample/Ease Of Movement Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This example cBot uses the Ease of Movement indicator to detect price movement and combine it with a +// Simple Moving Average (SMA) crossover strategy. The bot opens a buy position when the price crosses above +// the SMA and a sell position when the price crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,76 +16,91 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class EaseOfMovementSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private EaseOfMovement _easeOfMovement; + private EaseOfMovement _easeOfMovement; // Store the Ease of Movement indicator. - private MovingAverage _simpleMovingAverage; + private MovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "EaseOfMovementSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 14, Group = "Ease Of Movement", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods for the Ease of Movement, defaulting to 14. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Ease Of Movement")] - public MovingAverageType MAType { get; set; } - + public MovingAverageType MAType { get; set; } // Type of moving average used for the crossover strategy. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the cBot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Ease of Movement indicator with the specified period and MA type. _easeOfMovement = Indicators.EaseOfMovement(Periods, MAType); + // Initialise the Simple Moving Average indicator with a period of 9. _simpleMovingAverage = Indicators.SimpleMovingAverage(Bars.ClosePrices, 9); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the Ease of Movement is above a threshold, check the price crossover. if (_easeOfMovement.Result.Last(0) > (Symbol.TickSize * 0.05)) { + // If the price crosses above the SMA, execute a buy trade. if (Bars.ClosePrices.Last(0) > _simpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) < _simpleMovingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the price crosses below the SMA, execute a sell trade. else if (Bars.ClosePrices.Last(0) < _simpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) > _simpleMovingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss, and take profit. } } + + // If Ease of Movement is low, close all open positions. else { ClosePositions(); } } + // This method closes all positions opened by the bot. private void ClosePositions() { foreach (var position in BotPositions) { - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Error Sample/Error Sample/Error Sample.cs b/Robots/Error Sample/Error Sample/Error Sample.cs index a5b34bd..06c8023 100644 --- a/Robots/Error Sample/Error Sample/Error Sample.cs +++ b/Robots/Error Sample/Error Sample/Error Sample.cs @@ -5,26 +5,32 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// In this example, a market order is placed with a volume of 0, which will result in an error. +// The bot checks if the trade was successful and, if not, prints the error message and stops. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot with the UTC time zone and no access rights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class ErrorSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { - // We use 0 for volume to cause an error + // Attempt to place a market order with a volume of 0, which will result in an error. var tradeResult = ExecuteMarketOrder(TradeType.Buy, SymbolName, 0); + // If the trade is not successful, print the error message and stop the bot. if (!tradeResult.IsSuccessful) { - Print(tradeResult.Error); + Print(tradeResult.Error); // Print the error to the log. - Stop(); + Stop(); // Stop the bot as there was an error. } } } -} \ No newline at end of file +} diff --git a/Robots/Exponential Moving Average Sample/Exponential Moving Average Sample/Exponential Moving Average Sample.cs b/Robots/Exponential Moving Average Sample/Exponential Moving Average Sample/Exponential Moving Average Sample.cs index 35d48c0..a9367fe 100644 --- a/Robots/Exponential Moving Average Sample/Exponential Moving Average Sample/Exponential Moving Average Sample.cs +++ b/Robots/Exponential Moving Average Sample/Exponential Moving Average Sample/Exponential Moving Average Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample cBot trades based on the crossover of two Exponential Moving Averages (EMA). +// When the fast EMA crosses above the slow EMA, it buys. When the fast EMA crosses below the slow EMA, it sells. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,85 +15,102 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class ExponentialMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private ExponentialMovingAverage _fastExponentialMovingAverage; + private ExponentialMovingAverage _fastExponentialMovingAverage; // Store the first (fast) EMA. - private ExponentialMovingAverage _slowExponentialMovingAverage; + private ExponentialMovingAverage _slowExponentialMovingAverage; // Store the slow EMA. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "ExponentialMovingAverageSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. + // Parameters for the fast EMA. [Parameter("Periods", DefaultValue = 9, Group = "Exponential Moving Average 1", MinValue = 0)] - public int PeriodsFirst { get; set; } + public int PeriodsFirst { get; set; } // Number of periods for the fast EMA, default is 9. [Parameter("Source", Group = "Exponential Moving Average 1")] - public DataSeries SourceFirst { get; set; } - + public DataSeries SourceFirst { get; set; } // Data series used for the fast EMA. + // Parameters for the slow EMA. [Parameter("Periods", DefaultValue = 20, Group = "Exponential Moving Average 2", MinValue = 0)] - public int PeriodsSecond { get; set; } + public int PeriodsSecond { get; set; } // Number of periods for the slow EMA, default is 20. [Parameter("Source", Group = "Exponential Moving Average 2")] - public DataSeries SourceSecond { get; set; } + public DataSeries SourceSecond { get; set; } // Data series used for the slow EMA. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast EMA with the specified periods and source. _fastExponentialMovingAverage = Indicators.ExponentialMovingAverage(SourceFirst, PeriodsFirst); + // Set the color of the fast EMA line to blue. _fastExponentialMovingAverage.Result.Line.Color = Color.Blue; + // Initialise the slow EMA with the specified periods and source. _slowExponentialMovingAverage = Indicators.ExponentialMovingAverage(SourceSecond, PeriodsSecond); + // Set the color of the slow EMA line to red. _slowExponentialMovingAverage.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the fast EMA crosses above the slow EMA, execute a buy order. if (_fastExponentialMovingAverage.Result.Last(0) > _slowExponentialMovingAverage.Result.Last(0) && _fastExponentialMovingAverage.Result.Last(1) < _slowExponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the fast EMA crosses below the slow EMA, execute a sell order else if (_fastExponentialMovingAverage.Result.Last(0) < _slowExponentialMovingAverage.Result.Last(0) && _fastExponentialMovingAverage.Result.Last(1) > _slowExponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample.cs b/Robots/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample.cs index 018c001..aa32035 100644 --- a/Robots/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample.cs +++ b/Robots/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample/Fractal Chaos Bands Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample cBot executes trades based on Fractal Chaos Bands. It buys when price breaks above +// the upper band and sells when price falls below the lower band. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,64 +15,77 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class FractalChaosBandsSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private FractalChaosBands _fractalChaosBands; + private FractalChaosBands _fractalChaosBands; // Store the Fractal Chaos Bands indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "FractalChaosBandsSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Fractal Chaos Bands indicator. _fractalChaosBands = Indicators.FractalChaosBands(); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the price breaks above the upper band, execute a buy order. if (Bars.ClosePrices.Last(0) > _fractalChaosBands.High.Last(0) && Bars.ClosePrices.Last(1) <= _fractalChaosBands.High.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the price falls below the lower band, execute a sell order. else if (Bars.ClosePrices.Last(0) < _fractalChaosBands.Low.Last(0) && Bars.ClosePrices.Last(1) >= _fractalChaosBands.Low.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Fractals Sample/Fractals Sample/Fractals Sample.cs b/Robots/Fractals Sample/Fractals Sample/Fractals Sample.cs index 648028f..49680d5 100644 --- a/Robots/Fractals Sample/Fractals Sample/Fractals Sample.cs +++ b/Robots/Fractals Sample/Fractals Sample/Fractals Sample.cs @@ -13,68 +13,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class FractalsSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store the trade volume in units based on specified lot size. - private Fractals _fractals; + private Fractals _fractals; // Store the Fractals indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "FractalsSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 5, Group = "Fractal", MinValue = 5)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods for the Fractals indicator, default is 5. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Fractals indicator with the specified periods. _fractals = Indicators.Fractals(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If a down fractal is detected, execute a buy order. if (!double.IsNaN(_fractals.DownFractal.Last(0))) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If an up fractal is detected, execute a sell order. else if (!double.IsNaN(_fractals.UpFractal.Last(0))) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/GetFitnessArgs Sample/GetFitnessArgs Sample/GetFitnessArgs Sample.cs b/Robots/GetFitnessArgs Sample/GetFitnessArgs Sample/GetFitnessArgs Sample.cs index a7b5555..b68a36c 100644 --- a/Robots/GetFitnessArgs Sample/GetFitnessArgs Sample/GetFitnessArgs Sample.cs +++ b/Robots/GetFitnessArgs Sample/GetFitnessArgs Sample/GetFitnessArgs Sample.cs @@ -5,24 +5,30 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample cBot demonstrates the use of the GetFitness method to evaluate performance metrics. +// The fitness value is calculated based on the win rate. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, including timezone and access rights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class GetFitnessArgsSample : Robot { + // This method is called when the bot starts and is used for initialization, if needed. protected override void OnStart() { } + // This method is used to calculate the fitness value based on trading performance. protected override double GetFitness(GetFitnessArgs args) { - // Here we are using the win rate as fitness - // You can use any other value by combining the values of GetFitnessArgs object properties + // Here we are using the win rate as fitness. + // You can use any other value by combining the values of GetFitnessArgs object properties. return args.WinningTrades / args.TotalTrades; } } -} \ No newline at end of file +} diff --git a/Robots/Grid/Grid/Grid.cs b/Robots/Grid/Grid/Grid.cs index 13e77b2..b147ca0 100644 --- a/Robots/Grid/Grid/Grid.cs +++ b/Robots/Grid/Grid/Grid.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This sample cBot implements a simple grid trading strategy. It opens a series of positions +// based on a fixed pip step size and closes all positions when a predefined profit target is reached. +// // ------------------------------------------------------------------------------------------------- using System; @@ -18,85 +21,109 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as access rights. [Robot(AccessRights = AccessRights.None)] public class Grid : Robot { + // Define input parameters for the cBot. [Parameter("Volume (lots)", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Trade Side")] - public TradeType TradeType { get; set; } + public TradeType TradeType { get; set; } // Direction of trades (Buy or Sell). [Parameter("Step (pips)", DefaultValue = 5, MinValue = 0.1, Step = 0.1)] - public double StepPips { get; set; } + public double StepPips { get; set; } // Distance in pips between grid positions, default is 5. [Parameter("Target Profit", DefaultValue = 20)] - public double TargetProfit { get; set; } + public double TargetProfit { get; set; } // Total net profit target for closing the grid, default is 20. - private bool enoughMoney = true; + private bool enoughMoney = true; // Flag to check if sufficient funds are available. + // This method is called when the bot starts. protected override void OnStart() { + // Open the first grid position if none exist. if (GridPositions.Length == 0) OpenPosition(); } + // This method is called on every tick to manage the grid. protected override void OnTick() { + // Check if the total net profit meets or exceeds the target profit. if (GridPositions.Sum(p => p.NetProfit) >= TargetProfit) { - Print("Target profit is reached. Closing all grid positions"); - CloseGridPositions(); - Print("All grid positions are closed. Stopping cBot"); - Stop(); + Print("Target profit is reached. Closing all grid positions"); // Log that the profit target has been reached and positions will be closed. + CloseGridPositions(); // Close all active positions in the grid. + Print("All grid positions are closed. Stopping cBot"); // Log that all positions are closed and the cBot will stop. + Stop(); // Stop the execution of the cBot. } + + // Open a new position if the distance from the last position exceeds the step size. if (GridPositions.Length > 0 && enoughMoney) { - var lastGridPosition = GridPositions.OrderBy(p => p.Pips).Last(); - var distance = CalculateDistanceInPips(lastGridPosition); + var lastGridPosition = GridPositions.OrderBy(p => p.Pips).Last(); // Find the position farthest from the current price in terms of pips. + var distance = CalculateDistanceInPips(lastGridPosition); // Calculate the distance from the last position to the current price in pips. + // Open a new position if the distance exceeds the defined step size. if (distance >= StepPips) OpenPosition(); } } + // Return all grid positions for the current symbol and trade type. private Position[] GridPositions { get { + // Filter and return positions matching the symbol name and trade type (buy or sell). return Positions .Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType) .ToArray(); } } + // Calculate the distance in pips from a given position to the current price. private double CalculateDistanceInPips(Position position) { + // For a buy position, calculate the distance between entry price and current Ask price. if (position.TradeType == TradeType.Buy) return (position.EntryPrice - Symbol.Ask) / Symbol.PipSize; + // For a sell position, calculate the distance between entry price and current Bid price. else return (Symbol.Bid - position.EntryPrice) / Symbol.PipSize; } + // Open a new position in the grid. private void OpenPosition() { + // Execute a market order for the specified trade type and symbol with the defined volume. var result = ExecuteMarketOrder(TradeType, SymbolName, Symbol.QuantityToVolumeInUnits(VolumeInLots), "Grid"); + + // Check if there is an error due to insufficient funds. if (result.Error == ErrorCode.NoMoney) { + // Set the flag to indicate that no more money is available to open positions. enoughMoney = false; + + // Log that there is not enough money to continue opening positions. Print("Not enough money to open additional positions"); } } + // Closes all positions in the grid. private void CloseGridPositions() { + // Loop until all grid positions are closed. while (GridPositions.Length > 0) { foreach (var position in GridPositions) { + // Close each position in the grid. ClosePosition(position); } } } } -} \ No newline at end of file +} diff --git a/Robots/High Minus Low Sample/High Minus Low Sample/High Minus Low Sample.cs b/Robots/High Minus Low Sample/High Minus Low Sample/High Minus Low Sample.cs index 3c280c2..afc2308 100644 --- a/Robots/High Minus Low Sample/High Minus Low Sample/High Minus Low Sample.cs +++ b/Robots/High Minus Low Sample/High Minus Low Sample/High Minus Low Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the HighMinusLow indicator to place buy or sell orders based on the comparison of +// the last bar's open and close prices. It also has configurable parameters for volume, stop loss, +// and take profit values. The bot closes opposing positions before opening new ones and manages +// trading risk with stop loss and take profit settings. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,66 +17,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class HighMinusLowSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private HighMinusLow _highMinusLow; + private HighMinusLow _highMinusLow; // Store the HighMinusLow indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "HighMinusLowSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialises the HighMinusLow indicator. _highMinusLow = Indicators.HighMinusLow(); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Checks if the HighMinusLow indicator's result is not at its maximum within the last 10 bars. if (_highMinusLow.Result.Last(0) < _highMinusLow.Result.Maximum(10)) return; + // If the last closed bar is bullish, close sell positions and open a buy order. if (Bars.ClosePrices.Last(0) > Bars.OpenPrices.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the last closed bar is bearish, close buy positions and open a sell order. else if (Bars.ClosePrices.Last(0) < Bars.OpenPrices.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Historical Volatility Sample/Historical Volatility Sample/Historical Volatility Sample.cs b/Robots/Historical Volatility Sample/Historical Volatility Sample/Historical Volatility Sample.cs index a080e80..d7927c2 100644 --- a/Robots/Historical Volatility Sample/Historical Volatility Sample/Historical Volatility Sample.cs +++ b/Robots/Historical Volatility Sample/Historical Volatility Sample/Historical Volatility Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Historical Volatility and Simple Moving Average indicators to manage buy and sell +// orders based on market conditions. The bot will open positions when the price crosses the Simple +// Moving Average after volatility reaches a specified threshold. It also uses a historical volatility +// indicator for additional market insight, with configurable stop loss and take profit values. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,77 +17,91 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class HistoricalVolatilitySample : Robot { - private double _volumeInUnits; + // Private fields for storing indicators and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private HistoricalVolatility _historicalVolatility; + private HistoricalVolatility _historicalVolatility; // Store the Historical Volatility indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [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; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "HistoricalVolatilitySample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 20, Group = "Historical Volatility", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods used in the Historical Volatility indicator, with a default of 20 periods. [Parameter("Bar History", DefaultValue = 252, Group = "Historical Volatility")] - public int BarHistory { get; set; } - + public int BarHistory { get; set; } // Number of bars to look back for the Historical Volatility indicator, with a default of 252 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Historical Volatility indicator. _historicalVolatility = Indicators.HistoricalVolatility(Bars.ClosePrices, Periods, BarHistory); + // Initialise the Simple Moving Average indicator. _simpleMovingAverage = Indicators.SimpleMovingAverage(Bars.ClosePrices, 9); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Checks if the Historical Volatility is below its maximum in the last 14 periods. if (_historicalVolatility.Result.Last(0) < _historicalVolatility.Result.Maximum(14)) return; + // If the price crosses above the Simple Moving Average and the previous bar was below the SMA, open a buy order. if (Bars.ClosePrices.Last(0) > _simpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) < _simpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the price crosses below the Simple Moving Average and the previous bar was above the SMA, open a sell order. else if (Bars.ClosePrices.Last(0) < _simpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) > _simpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Hull Moving Average Sample/Hull Moving Average Sample/Hull Moving Average Sample.cs b/Robots/Hull Moving Average Sample/Hull Moving Average Sample/Hull Moving Average Sample.cs index caf3b58..c7fd952 100644 --- a/Robots/Hull Moving Average Sample/Hull Moving Average Sample/Hull Moving Average Sample.cs +++ b/Robots/Hull Moving Average Sample/Hull Moving Average Sample/Hull Moving Average Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses two Hull Moving Averages (fast and slow) to manage buy and sell orders based on +// crossovers. The fast Hull Moving Average (HMA) crosses above the slow HMA to initiate a buy order, +// and vice versa for a sell order. The bot allows setting stop loss and take profit values, and it +// works with the specified volume, fast, and slow periods for the moving averages. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,82 +17,96 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class HullMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private HullMovingAverage _fastHull; + private HullMovingAverage _fastHull; // Store the fast HMA indicator. - private HullMovingAverage _slowHull; + private HullMovingAverage _slowHull; // Store the slow HMA indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "HullMovingAverageSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data series for the fast HMA. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast HMA, with a default of 9 periods. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data series for the slow HMA. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow HMA, with a default of 20 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() - { + { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow Hull Moving Averages. _fastHull = Indicators.HullMovingAverage(FastMaSource, FastMaPeriod); _slowHull = Indicators.HullMovingAverage(SlowMaSource, SlowMaPeriod); + // Set the line colors for the fast and slow HMAs. _fastHull.Result.Line.Color = Color.Blue; _slowHull.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the fast Hull Moving Average crosses above the slow Hull Moving Average, open a buy order. if (_fastHull.Result.HasCrossedAbove(_slowHull.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the fast Hull Moving Average crosses below the slow Hull Moving Average, open a sell order. else if (_fastHull.Result.HasCrossedBelow(_slowHull.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample.cs b/Robots/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample.cs index 46e2b96..1e66c45 100644 --- a/Robots/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample.cs +++ b/Robots/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample/Ichimoku Kinko Hyo Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Ichimoku Kinko Hyo indicator to trade trend reversals. It opens a buy position +// when the Tenkan Sen crosses above the Kijun Sen, and a sell position when the Tenkan Sen crosses +// below the Kijun Sen. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,80 +16,94 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class IchimokuKinkoHyoSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private IchimokuKinkoHyo _ichimokuKinkoHyo; + private IchimokuKinkoHyo _ichimokuKinkoHyo; // Store the Ichimoku Kinko Hyo indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "IchimokuKinkoHyoSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Tenkan Sen Periods", DefaultValue = 9, Group = "IchimokuKinkoHyo", MinValue = 1)] - public int TenkanSenPeriods { get; set; } + public int TenkanSenPeriods { get; set; } // Tenkan Sen period for Ichimoku, default is 9. [Parameter("Kijun Sen Periods", DefaultValue = 26, Group = "IchimokuKinkoHyo", MinValue = 1)] - public int KijunSenPeriods { get; set; } + public int KijunSenPeriods { get; set; } // Kijun Sen period for Ichimoku, default is 26. [Parameter("Senkou Span B Periods", DefaultValue = 52, Group = "IchimokuKinkoHyo", MinValue = 1)] - public int SenkouSpanBPeriods { get; set; } - + public int SenkouSpanBPeriods { get; set; } // Senkou Span B period for Ichimoku, default is 52. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Ichimoku Kinko Hyo indicator with the specified periods. _ichimokuKinkoHyo = Indicators.IchimokuKinkoHyo(TenkanSenPeriods, KijunSenPeriods, SenkouSpanBPeriods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the current close price is above the Senkou Span B (indicating a buy signal). if (Bars.ClosePrices.Last(0) > _ichimokuKinkoHyo.SenkouSpanB.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. + // Check if Tenkan Sen crosses above Kijun Sen (buy signal). if (_ichimokuKinkoHyo.TenkanSen.Last(0) > _ichimokuKinkoHyo.KijunSen.Last(0) && _ichimokuKinkoHyo.TenkanSen.Last(1) <= _ichimokuKinkoHyo.KijunSen.Last(1)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + + // Check if the current close price is below Senkou Span A (indicating a sell signal). else if (Bars.ClosePrices.Last(0) < _ichimokuKinkoHyo.SenkouSpanA.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. + // Check if Tenkan Sen crosses below Kijun Sen (sell signal). if (_ichimokuKinkoHyo.TenkanSen.Last(0) < _ichimokuKinkoHyo.KijunSen.Last(0) && _ichimokuKinkoHyo.TenkanSen.Last(1) >= _ichimokuKinkoHyo.KijunSen.Last(1)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } } + // Method to close positions based on the trade type (buy or sell). private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs b/Robots/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs index 6fc23dd..291a1b8 100644 --- a/Robots/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs +++ b/Robots/IndicatorTitles Sample/IndicatorTitles Sample/IndicatorTitles Sample.cs @@ -19,20 +19,26 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class IndicatorTitlesSample : Robot { + // This method is called when the cBot is initialised. protected override void OnStart() { // Adding a custom event handler for the DisplaySettingsChanged event + // This event is triggered when the user changes the chart display settings. Chart.DisplaySettingsChanged += OnDisplaySettingsChanged; + // Print the initial value of IndicatorTitles when the cBot starts. Print(Chart.DisplaySettings.IndicatorTitles); } + // This method is called whenever the chart's display settings are changed. protected void OnDisplaySettingsChanged(ChartDisplaySettingsEventArgs args) { + // Print the updated value of IndicatorTitles whenever the display settings change. Print(Chart.DisplaySettings.IndicatorTitles); } } -} \ No newline at end of file +} diff --git a/Robots/Keltner Channels Sample/Keltner Channels Sample/Keltner Channels Sample.cs b/Robots/Keltner Channels Sample/Keltner Channels Sample/Keltner Channels Sample.cs index 99d3f8d..254c1f9 100644 --- a/Robots/Keltner Channels Sample/Keltner Channels Sample/Keltner Channels Sample.cs +++ b/Robots/Keltner Channels Sample/Keltner Channels Sample/Keltner Channels Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Keltner Channels indicator to trade breakouts. It opens a buy position when +// the price crosses above the lower band of the channel, and a sell position when the price +// crosses below the upper band. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,75 +16,86 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class KeltnerChannelsSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private KeltnerChannels _keltnerChannels; + private KeltnerChannels _keltnerChannels; // Store the Keltner Channels indicator instance. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, with a default of 0.01 lots. [Parameter("Label", DefaultValue = "KeltnerChannelsSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders opened by this bot. [Parameter("MA Period", DefaultValue = 20, Group = "Keltner Channels", MinValue = 1)] - public int MAPeriod { get; set; } + public int MAPeriod { get; set; } // Moving Average period with default value 20 periods. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Keltner Channels")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Moving Average type with default value Simple. [Parameter("ATR Period", DefaultValue = 10, Group = "Keltner Channels", MinValue = 1)] - public int AtrPeriod { get; set; } + public int AtrPeriod { get; set; } // ATR calculation period with default value 10 periods. [Parameter("ATR MA Type", DefaultValue = MovingAverageType.Simple, Group = "Keltner Channels")] - public MovingAverageType AtrMAType { get; set; } + public MovingAverageType AtrMAType { get; set; } // ATR Moving Average type with default value Simple. [Parameter("Band Distance", DefaultValue = 2.0, MinValue = 0)] - public double BandDistance { get; set; } - - + public double BandDistance { get; set; } // Multiplier for the ATR to calculate channel width with default value 2.0. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified lot size to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Keltner Channels indicator with the specified parameters. _keltnerChannels = Indicators.KeltnerChannels(MAPeriod, MAType, AtrPeriod, AtrMAType, BandDistance); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the price crosses above the lower band indicating a buy signal. if (Bars.LowPrices.Last(0) <= _keltnerChannels.Bottom.Last(0) && Bars.LowPrices.Last(1) > _keltnerChannels.Bottom.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); // Open a buy market order. } + + // Check if the price crosses below the upper band indicating a sell signal. else if (Bars.HighPrices.Last(0) >= _keltnerChannels.Top.Last(0) && Bars.HighPrices.Last(1) < _keltnerChannels.Top.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); // Open a sell market order. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Linear Regression Forecast Sample/Linear Regression Forecast Sample/Linear Regression Forecast Sample.cs b/Robots/Linear Regression Forecast Sample/Linear Regression Forecast Sample/Linear Regression Forecast Sample.cs index 3aa73fc..554eef6 100644 --- a/Robots/Linear Regression Forecast Sample/Linear Regression Forecast Sample/Linear Regression Forecast Sample.cs +++ b/Robots/Linear Regression Forecast Sample/Linear Regression Forecast Sample/Linear Regression Forecast Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Linear Regression Forecast indicator to make trade decisions based on +// price predictions. It opens a buy position when the current price is above the Linear +// Regression Forecast result, and opens a sell position when the price is below it. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,71 +17,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class LinearRegressionForecastSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private LinearRegressionForecast _linearRegressionForecast; + private LinearRegressionForecast _linearRegressionForecast; // Store the Linear Regression Forecast indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "LinearRegressionForecastSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Linear Regression Forecast")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Define the source data for the Linear Regression Forecast. [Parameter("Periods", DefaultValue = 9, Group = "Linear Regression Forecast", MinValue = 0)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods for the Linear Regression Forecast, with a default of 9 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialize the Linear Regression Forecast indicator with the specified period. _linearRegressionForecast = Indicators.LinearRegressionForecast(Source, Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the current price is greater than the Linear Regression Forecast and the price was lower the previous bar, open a buy position. if (Bars.ClosePrices.Last(0) > _linearRegressionForecast.Result.Last(0) && Bars.ClosePrices.Last(1) <= _linearRegressionForecast.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the current price is less than the Linear Regression Forecast and the price was higher the previous bar, open a sell position. else if (Bars.ClosePrices.Last(0) < _linearRegressionForecast.Result.Last(0) && Bars.ClosePrices.Last(1) >= _linearRegressionForecast.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Linear Regression Intercept Sample/Linear Regression Intercept Sample/Linear Regression Intercept Sample.cs b/Robots/Linear Regression Intercept Sample/Linear Regression Intercept Sample/Linear Regression Intercept Sample.cs index fc14eb0..b0c2763 100644 --- a/Robots/Linear Regression Intercept Sample/Linear Regression Intercept Sample/Linear Regression Intercept Sample.cs +++ b/Robots/Linear Regression Intercept Sample/Linear Regression Intercept Sample/Linear Regression Intercept Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Linear Regression Intercept indicator to trade based on trend direction changes. +// It opens a buy position when the current close price crosses above the Linear Regression Intercept, +// and a sell position when the current close price crosses below the Linear Regression Intercept. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,70 +17,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class LinearRegressionInterceptSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private LinearRegressionIntercept _linearRegressionIntercept; + private LinearRegressionIntercept _linearRegressionIntercept; // Store the Linear Regression Intercept indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "LinearRegressionInterceptSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Linear Regression Forecast")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Source data for Linear Regression Intercept. [Parameter("Periods", DefaultValue = 9, Group = "Linear Regression Forecast", MinValue = 0)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods, with a default of 9 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Linear Regression Intercept indicator with the specified period. _linearRegressionIntercept = Indicators.LinearRegressionIntercept(Source, Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the current close price crosses above the Linear Regression Intercept, execute a buy trade. if (Bars.ClosePrices.Last(0) > _linearRegressionIntercept.Result.Last(0) && Bars.ClosePrices.Last(1) <= _linearRegressionIntercept.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the current close price crosses below the Linear Regression Intercept, execute a sell trade. else if (Bars.ClosePrices.Last(0) < _linearRegressionIntercept.Result.Last(0) && Bars.ClosePrices.Last(1) >= _linearRegressionIntercept.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Linear Regression R Squared Sample/Linear Regression R Squared Sample/Linear Regression R Squared Sample.cs b/Robots/Linear Regression R Squared Sample/Linear Regression R Squared Sample/Linear Regression R Squared Sample.cs index dc54fc6..9461a40 100644 --- a/Robots/Linear Regression R Squared Sample/Linear Regression R Squared Sample/Linear Regression R Squared Sample.cs +++ b/Robots/Linear Regression R Squared Sample/Linear Regression R Squared Sample/Linear Regression R Squared Sample.cs @@ -5,6 +5,12 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Linear Regression R-Squared indicator combined with two types of moving averages +// (Simple and Exponential) to trade. It opens a buy position when the price crosses above the Exponential +// Moving Average and the Linear Regression R-Squared is greater than the Simple Moving Average. +// It opens a sell position when the price crosses below the Exponential Moving Average with the same condition +// on the Linear Regression R-Squared. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,96 +19,111 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class LinearRegressionRSquaredSample : Robot { - private double _volumeInUnits; - - private LinearRegressionRSquared _linearRegressionRSquared; + // Private fields for storing indicators and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private SimpleMovingAverage _simpleMovingAverage; - - private ExponentialMovingAverage _exponentialMovingAverage; + private LinearRegressionRSquared _linearRegressionRSquared; // Store the Linear Regression R-Squared indicator. + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average. + private ExponentialMovingAverage _exponentialMovingAverage; // Store the Exponential Moving Average. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "LinearRegressionRSquaredSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Linear Regression")] - public DataSeries SourceLinearRegression { get; set; } + public DataSeries SourceLinearRegression { get; set; } // Source data for the Linear Regression R-Squared indicator. [Parameter("Periods", DefaultValue = 20, Group = "Linear Regression", MinValue = 0)] - public int PeriodsLinearRegression { get; set; } + public int PeriodsLinearRegression { get; set; } // Number of periods for Linear Regression R-Squared, default is 20. [Parameter("Source", Group = "Simple Moving Average")] - public DataSeries SourceSimpleMovingAverage { get; set; } + public DataSeries SourceSimpleMovingAverage { get; set; } // Source data for the Simple Moving Average. [Parameter("Periods", DefaultValue = 10, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } + public int PeriodsSimpleMovingAverage { get; set; } // Number of periods for Simple Moving Average, default is 10. [Parameter("Source", Group = "Exponential Moving Average")] - public DataSeries SourceExponentialMovingAverage { get; set; } + public DataSeries SourceExponentialMovingAverage { get; set; } // Source data for the Exponential Moving Average. [Parameter("Periods", DefaultValue = 20, Group = "Exponential Moving Average", MinValue = 0)] - public int PeriodsExponentialMovingAverage { get; set; } + public int PeriodsExponentialMovingAverage { get; set; } // Number of periods for Exponential Moving Average, default is 20. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Linear Regression R-Squared indicator with the specified period. _linearRegressionRSquared = Indicators.LinearRegressionRSquared(SourceLinearRegression, PeriodsLinearRegression); + // Initialise the Simple Moving Average with the Linear Regression R-Squared results. _simpleMovingAverage = Indicators.SimpleMovingAverage(_linearRegressionRSquared.Result, PeriodsSimpleMovingAverage); + // Initialise the Exponential Moving Average with the specified source and period. _exponentialMovingAverage = Indicators.ExponentialMovingAverage(SourceExponentialMovingAverage, PeriodsExponentialMovingAverage); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the current close price crosses above the Exponential Moving Average, execute a buy trade. if (Bars.ClosePrices.Last(0) > _exponentialMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) <= _exponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. + // Execute Buy if the Linear Regression R-Squared is above the Simple Moving Average. if (_linearRegressionRSquared.Result.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + + // If the current close price crosses below the Exponential Moving Average, execute a sell trade. else if (Bars.ClosePrices.Last(0) < _exponentialMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) >= _exponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. + // Execute Buy if the Linear Regression R-Squared is above the Simple Moving Average. if (_linearRegressionRSquared.Result.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Linear Regression Slope Sample/Linear Regression Slope Sample/Linear Regression Slope Sample.cs b/Robots/Linear Regression Slope Sample/Linear Regression Slope Sample/Linear Regression Slope Sample.cs index 578b523..a4c24b2 100644 --- a/Robots/Linear Regression Slope Sample/Linear Regression Slope Sample/Linear Regression Slope Sample.cs +++ b/Robots/Linear Regression Slope Sample/Linear Regression Slope Sample/Linear Regression Slope Sample.cs @@ -5,6 +5,12 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilizes the Linear Regression Slope indicator along with two types of moving averages +// (Simple and Exponential) to make trade decisions. A buy position is initiated when the price crosses +// above the Exponential Moving Average and the Linear Regression Slope is above the Simple Moving Average. +// A sell position is initiated when the price crosses below the Exponential Moving Average under the same +// condition of the Linear Regression Slope being above the Simple Moving Average. +// // ------------------------------------------------------------------------------------------------- @@ -14,96 +20,111 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class LinearRegressionSlopeSample : Robot { + // Private fields for storing indicators and trade volume. private double _volumeInUnits; - private LinearRegressionSlope _linearRegressionSlope; - - private SimpleMovingAverage _simpleMovingAverage; - - private ExponentialMovingAverage _exponentialMovingAverage; + private LinearRegressionSlope _linearRegressionSlope; // Store the Linear Regression Slope indicator. + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average. + private ExponentialMovingAverage _exponentialMovingAverage; // Store the Exponential Moving Average. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "LinearRegressionSlopeSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Linear Regression")] - public DataSeries SourceLinearRegression { get; set; } + public DataSeries SourceLinearRegression { get; set; } // Source data for the Linear Regression Slope indicator. [Parameter("Periods", DefaultValue = 20, Group = "Linear Regression", MinValue = 0)] - public int PeriodsLinearRegression { get; set; } + public int PeriodsLinearRegression { get; set; } // Number of periods for Linear Regression Slope, default is 20. [Parameter("Source", Group = "Simple Moving Average")] - public DataSeries SourceSimpleMovingAverage { get; set; } + public DataSeries SourceSimpleMovingAverage { get; set; } // Source data for the Simple Moving Average. [Parameter("Periods", DefaultValue = 10, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } + public int PeriodsSimpleMovingAverage { get; set; } // Number of periods for Simple Moving Average, default is 10. [Parameter("Source", Group = "Exponential Moving Average")] - public DataSeries SourceExponentialMovingAverage { get; set; } + public DataSeries SourceExponentialMovingAverage { get; set; } // Source data for the Exponential Moving Average. [Parameter("Periods", DefaultValue = 20, Group = "Exponential Moving Average", MinValue = 0)] - public int PeriodsExponentialMovingAverage { get; set; } + public int PeriodsExponentialMovingAverage { get; set; } // Number of periods for Exponential Moving Average, default is 20. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Linear Regression Slope indicator with the specified period. _linearRegressionSlope = Indicators.LinearRegressionSlope(SourceLinearRegression, PeriodsLinearRegression); + // Initialise the Simple Moving Average with the Linear Regression Slope results. _simpleMovingAverage = Indicators.SimpleMovingAverage(_linearRegressionSlope.Result, PeriodsSimpleMovingAverage); + // Initialise the Exponential Moving Average with the specified source and period. _exponentialMovingAverage = Indicators.ExponentialMovingAverage(SourceExponentialMovingAverage, PeriodsExponentialMovingAverage); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the current close price crosses above the Exponential Moving Average, execute a buy trade. if (Bars.ClosePrices.Last(0) > _exponentialMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) <= _exponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. + // Execute buy if the Linear Regression Slope is above the Simple Moving Average. if (_linearRegressionSlope.Result.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + + // If the current close price crosses below the Exponential Moving Average, execute a sell trade. else if (Bars.ClosePrices.Last(0) < _exponentialMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) >= _exponentialMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. + // Execute sell if the Linear Regression Slope is above the Simple Moving Average. if (_linearRegressionSlope.Result.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Macd Cross Over Sample/Macd Cross Over Sample/Macd Cross Over Sample.cs b/Robots/Macd Cross Over Sample/Macd Cross Over Sample/Macd Cross Over Sample.cs index 8250707..6c7ca41 100644 --- a/Robots/Macd Cross Over Sample/Macd Cross Over Sample/Macd Cross Over Sample.cs +++ b/Robots/Macd Cross Over Sample/Macd Cross Over Sample/Macd Cross Over Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the MACD Crossover indicator to trade trend reversals. It opens a buy position when the MACD line +// crosses above the Signal line and a sell position when the MACD line crosses below the Signal line. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,77 +16,89 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MacdCrossOverSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private MacdCrossOver _macdCrossOver; + private MacdCrossOver _macdCrossOver; // Store the MACD Crossover indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, with a default of 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MacdCrossOverSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders opened by this bot. [Parameter("Source", Group = "Macd Crossover")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Source data series for the MACD calculation. [Parameter("Long Cycle", DefaultValue = 26, Group = "Macd Crossover", MinValue = 1)] - public int LongCycle { get; set; } + public int LongCycle { get; set; } // Long period for the MACD calculation, default is 26 periods. [Parameter("Short Cycle", DefaultValue = 12, Group = "Macd Crossover", MinValue = 1)] - public int ShortCycle { get; set; } + public int ShortCycle { get; set; } // Short period for the MACD calculation, default is 12 periods. [Parameter("Signal Periods", DefaultValue = 9, Group = "Macd Crossover", MinValue = 1)] - public int SignalPeriods { get; set; } - + public int SignalPeriods { get; set; } // Signal line smoothing period, default is 9 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the MACD Crossover indicator with the specified parameters. _macdCrossOver = Indicators.MacdCrossOver(Source, LongCycle, ShortCycle, SignalPeriods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the MACD line crosses above the Signal line, execute a buy trade. if (_macdCrossOver.MACD.Last(0) > _macdCrossOver.Signal.Last(0) && _macdCrossOver.MACD.Last(1) <= _macdCrossOver.Signal.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the MACD line crosses below the Signal line, execute a sell trade. else if (_macdCrossOver.MACD.Last(0) < _macdCrossOver.Signal.Last(0) && _macdCrossOver.MACD.Last(1) >= _macdCrossOver.Signal.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Macd Histogram Sample/Macd Histogram Sample/Macd Histogram Sample.cs b/Robots/Macd Histogram Sample/Macd Histogram Sample/Macd Histogram Sample.cs index 7de7a3a..3bf025c 100644 --- a/Robots/Macd Histogram Sample/Macd Histogram Sample/Macd Histogram Sample.cs +++ b/Robots/Macd Histogram Sample/Macd Histogram Sample/Macd Histogram Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the MACD Histogram indicator to trade based on momentum shifts. It opens a buy position when the +// Histogram crosses above zero and a sell position when the Histogram crosses below zero. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,76 +16,89 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MacdHistogramSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private MacdHistogram _macdHistogram; + private MacdHistogram _macdHistogram; // Store the MACD Histogram indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, default is 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, default is 10 pips. [Parameter("Label", DefaultValue = "MacdHistogramSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Macd Histogram")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Source data series for the MACD Histogram calculation. [Parameter("Long Cycle", DefaultValue = 26, Group = "Macd Histogram", MinValue = 1)] - public int LongCycle { get; set; } + public int LongCycle { get; set; } // Long period for the MACD calculation, default is 26 periods. [Parameter("Short Cycle", DefaultValue = 12, Group = "Macd Histogram", MinValue = 1)] - public int ShortCycle { get; set; } + public int ShortCycle { get; set; } // Short period for the MACD calculation, default is 12 periods. [Parameter("Signal Periods", DefaultValue = 9, Group = "Macd Histogram", MinValue = 1)] - public int SignalPeriods { get; set; } + public int SignalPeriods { get; set; } // Signal line smoothing period, default is 9 periods. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the MACD Histogram indicator with the specified parameters. _macdHistogram = Indicators.MacdHistogram(Source, LongCycle, ShortCycle, SignalPeriods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the Histogram crosses above zero, execute a buy trade. if (_macdHistogram.Histogram.Last(0) > 0 && _macdHistogram.Histogram.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the Histogram crosses below zero, execute a sell trade. else if (_macdHistogram.Histogram.Last(0) < 0 && _macdHistogram.Histogram.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Mass Index Sample/Mass Index Sample/Mass Index Sample.cs b/Robots/Mass Index Sample/Mass Index Sample/Mass Index Sample.cs index 5a95358..246c318 100644 --- a/Robots/Mass Index Sample/Mass Index Sample/Mass Index Sample.cs +++ b/Robots/Mass Index Sample/Mass Index Sample/Mass Index Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Mass Index indicator along with a Simple Moving Average (SMA) to detect +// potential trend reversals. A sell trade is executed if the close price is above the SMA, and +// a buy trade is executed if the close price is below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,80 +16,94 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MassIndexSample : Robot { + // Private fields for storing indicators and trade volume. private double _volumeInUnits; - private MassIndex _massIndex; + private MassIndex _massIndex; // Store the Mass Index indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MassIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 9, Group = "Mass Index", MinValue = 4)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods for the Mass Index indicator, default is 9. [Parameter("Source", Group = "Simple Moving Average")] - public DataSeries SourceSimpleMovingAverage { get; set; } + public DataSeries SourceSimpleMovingAverage { get; set; } // Data source for the SMA calculation. [Parameter("Periods", DefaultValue = 20, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } - + public int PeriodsSimpleMovingAverage { get; set; } // Number of periods for the SMA, default is 20. + // This property finds all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the bot. } } + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Mass Index indicator with the specified periods. _massIndex = Indicators.MassIndex(Periods); + // Initialise the SMA with the specified data source and periods. _simpleMovingAverage = Indicators.SimpleMovingAverage(SourceSimpleMovingAverage, PeriodsSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Ensure the Mass Index has sufficient data before making decisions. if (_massIndex.Result.Last(0) < Periods) return; + // If the close price is above the SMA, execute a sell trade. if (Bars.ClosePrices.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } + + // If the close price is below the SMA, execute a buy trade. else if (Bars.ClosePrices.Last(0) < _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Median Price Sample/Median Price Sample/Median Price Sample.cs b/Robots/Median Price Sample/Median Price Sample/Median Price Sample.cs index f5331de..07a13d5 100644 --- a/Robots/Median Price Sample/Median Price Sample/Median Price Sample.cs +++ b/Robots/Median Price Sample/Median Price Sample/Median Price Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Median Price indicator to generate trading signals. It executes buy orders +// when the closing price is above the Median Price and sell orders when the closing price is +// below it. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,70 +16,85 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MedianPriceSample : Robot { - private double _volumeInUnits; + // Private fields for storing trade volume and the Median Price indicator. + private double _volumeInUnits; // Stores the volume in units based on the specified lot size. - private MedianPrice _medianPrice; + private MedianPrice _medianPrice; // Store the Median Price indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MedianPriceSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Median Price indicator. _medianPrice = Indicators.MedianPrice(); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the close price is above the Median Price, execute a buy trade. if (Bars.ClosePrices.Last(0) > _medianPrice.Result.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. + // Open a buy order only if there are no active positions. if (BotPositions.Length == 0) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + + // If the close price is below the Median Price, execute a sell trade. else if (Bars.ClosePrices.Last(0) < _medianPrice.Result.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. + // Open a Sell order only if there are no active positions. if (BotPositions.Length == 0) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Momentum Oscillator Sample/Momentum Oscillator Sample/Momentum Oscillator Sample.cs b/Robots/Momentum Oscillator Sample/Momentum Oscillator Sample/Momentum Oscillator Sample.cs index 01f44a9..06b3037 100644 --- a/Robots/Momentum Oscillator Sample/Momentum Oscillator Sample/Momentum Oscillator Sample.cs +++ b/Robots/Momentum Oscillator Sample/Momentum Oscillator Sample/Momentum Oscillator Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Momentum Oscillator indicator along with a Simple Moving Average (SMA) to generate +// trading signals. It executes buy orders when the Momentum Oscillator crosses above the SMA and sell +// orders when the Momentum Oscillator crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,84 +16,99 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MomentumOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicators and trade volume. + private double _volumeInUnits; // Store the volume in units based on the specified lot size. - private MomentumOscillator _momentumOscillator; + private MomentumOscillator _momentumOscillator; // Store the Momentum Oscillator indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MomentumOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Source", Group = "Momentum Oscillator")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Source for Momentum Oscillator, e.g., Close prices. [Parameter("Periods", DefaultValue = 14, Group = "Momentum Oscillator", MinValue = 1)] - public int PeriodsMomentumOscillator { get; set; } + public int PeriodsMomentumOscillator { get; set; } // Periods for the Momentum Oscillator, defaulting to 14. [Parameter("Periods", DefaultValue = 14, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } + public int PeriodsSimpleMovingAverage { get; set; } // Periods for the Simple Moving Average, defaulting to 14. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Momentum Oscillator indicator. _momentumOscillator = Indicators.MomentumOscillator(Source, PeriodsMomentumOscillator); + // Initialise the Simple Moving Average indicator. _simpleMovingAverage = Indicators.SimpleMovingAverage(_momentumOscillator.Result, PeriodsSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // Check if the Momentum Oscillator is above the Simple Moving Average, signaling a buy opportunity. if (_momentumOscillator.Result.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. + // Open a buy order only if the previous Momentum Oscillator value was below the SMA. if (_momentumOscillator.Result.Last(1) <= _simpleMovingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } + + // Check if the Momentum Oscillator is below the Simple Moving Average, signaling a sell opportunity. else if (_momentumOscillator.Result.Last(0) < _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. + // Open a sell order only if the previous Momentum Oscillator value was above the SMA. if (_momentumOscillator.Result.Last(1) >= _simpleMovingAverage.Result.Last(1)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Money Flow Index Sample/Money Flow Index Sample/Money Flow Index Sample.cs b/Robots/Money Flow Index Sample/Money Flow Index Sample/Money Flow Index Sample.cs index 66e52a5..386fcfa 100644 --- a/Robots/Money Flow Index Sample/Money Flow Index Sample/Money Flow Index Sample.cs +++ b/Robots/Money Flow Index Sample/Money Flow Index Sample/Money Flow Index Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Money Flow Index (MFI) to generate buy and sell signals. It opens a sell position +// when the MFI crosses above a certain threshold (Level Up), and opens a buy position when the MFI crosses +// below a lower threshold (Level Down). +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,80 +16,94 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MoneyFlowIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store the volume in units based on the specified lot size. - private MoneyFlowIndex _moneyFlowIndex; + private MoneyFlowIndex _moneyFlowIndex; // Store the Money Flow Index (MFI) indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MoneyFlowIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 14, Group = "Money Flow Index", MinValue = 2)] - public int Periods { get; set; } + public int Periods { get; set; } // Periods for the Money Flow Index, defaulting to 14. [Parameter("Level Up", DefaultValue = 80, Group = "Money Flow Index", MinValue = 50, MaxValue = 100)] - public int LevelUp { get; set; } + public int LevelUp { get; set; } // Upper level threshold for the MFI, defaulting to 80. [Parameter("Level Down", DefaultValue = 20, Group = "Money Flow Index", MinValue = 0, MaxValue = 50)] - public int LevelDown { get; set; } - + public int LevelDown { get; set; } // Lower level threshold for the MFI, defaulting to 20. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Money Flow Index (MFI) indicator. _moneyFlowIndex = Indicators.MoneyFlowIndex(Periods); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the MFI is above the upper threshold, it's considered overbought, triggering a sell signal. if (_moneyFlowIndex.Result.Last(0) > LevelUp) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. + // Open a sell order if no positions are open. if (BotPositions.Length == 0) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + + // If the MFI is below the lower threshold, it's considered oversold, triggering a buy signal. else if (_moneyFlowIndex.Result.Last(0) < LevelDown) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. + // Open a buy order if no positions are open. if (BotPositions.Length == 0) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Moving Average Sample/Moving Average Sample/Moving Average Sample.cs b/Robots/Moving Average Sample/Moving Average Sample/Moving Average Sample.cs index a4ace06..87ba68f 100644 --- a/Robots/Moving Average Sample/Moving Average Sample/Moving Average Sample.cs +++ b/Robots/Moving Average Sample/Moving Average Sample/Moving Average Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses two Moving Averages (Fast and Slow) to generate buy and sell signals based on +// crossovers. When the Fast MA crosses above the Slow MA, a buy position is opened, and when +// the Fast MA crosses below the Slow MA, a sell position is opened. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,88 +16,107 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class MovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store the volume in units based on the specified lot size. + + private MovingAverage _fastMa; // Stores the Fast Moving Average indicator. - private MovingAverage _fastMa; + private MovingAverage _slowMa; // Store the Slow Moving Average indicator. - private MovingAverage _slowMa; + // Input parameters for the Fast Moving Average. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the Fast MA. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the Fast MA, defaulting to 9. [Parameter("Type", DefaultValue = MovingAverageType.Exponential, Group = "Fast MA")] - public MovingAverageType FastMaType { get; set; } + public MovingAverageType FastMaType { get; set; } // Type of the Fast MA, defaulting to Exponential. + + // Input parameters for the Slow Moving Average. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the Slow MA. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the Slow MA, defaulting to 20. [Parameter("Type", DefaultValue = MovingAverageType.Exponential, Group = "Slow MA")] - public MovingAverageType SlowMaType { get; set; } + public MovingAverageType SlowMaType { get; set; } // Type of the Slow MA, defaulting to Exponential. + + // Input parameters for trade settings. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "MovingAverageSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Fast and Slow Moving Averages. _fastMa = Indicators.MovingAverage(FastMaSource, FastMaPeriod, FastMaType); _slowMa = Indicators.MovingAverage(SlowMaSource, SlowMaPeriod, SlowMaType); + // Set the line colors for the Fast and Slow MAs. _fastMa.Result.Line.Color = Color.Blue; _slowMa.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the Fast MA crosses above the Slow MA, it's considered a buy signal. if (_fastMa.Result.HasCrossedAbove(_slowMa.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the Fast MA crosses below the Slow MA, it's considered a sell signal. else if (_fastMa.Result.HasCrossedBelow(_slowMa.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/On Balance Volume Sample/On Balance Volume Sample/On Balance Volume Sample.cs b/Robots/On Balance Volume Sample/On Balance Volume Sample/On Balance Volume Sample.cs index 6ad955a..e4fbe66 100644 --- a/Robots/On Balance Volume Sample/On Balance Volume Sample/On Balance Volume Sample.cs +++ b/Robots/On Balance Volume Sample/On Balance Volume Sample/On Balance Volume Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilizes the On-Balance Volume (OBV) indicator in combination with a Simple Moving +// Average (SMA) to trigger buy and sell orders. A buy order is placed when OBV crosses above +// the SMA, and a sell order is placed when OBV crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,70 +16,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class OnBalanceVolumeSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicators and trade volume. + private double _volumeInUnits; // Store the volume in units based on the specified lot size. - private OnBalanceVolume _onBalanceVolume; + private OnBalanceVolume _onBalanceVolume; // Store the On-Balance Volume indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Stores the Simple Moving Average. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, defaulting to 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "OnBalanceVolumeSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Periods", DefaultValue = 9, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } + public int PeriodsSimpleMovingAverage { get; set; } // Period for the Simple Moving Average, defaulting to 9. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the On-Balance Volume and Simple Moving Average. _onBalanceVolume = Indicators.OnBalanceVolume(Bars.ClosePrices); _simpleMovingAverage = Indicators.SimpleMovingAverage(_onBalanceVolume.Result, PeriodsSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the OBV crosses above the SMA, it's considered a buy signal. if (_onBalanceVolume.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the OBV crosses below the SMA, it's considered a sell signal. else if (_onBalanceVolume.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Parabolic SAR Sample/Parabolic SAR Sample/Parabolic SAR Sample.cs b/Robots/Parabolic SAR Sample/Parabolic SAR Sample/Parabolic SAR Sample.cs index a42133c..67cfa0c 100644 --- a/Robots/Parabolic SAR Sample/Parabolic SAR Sample/Parabolic SAR Sample.cs +++ b/Robots/Parabolic SAR Sample/Parabolic SAR Sample/Parabolic SAR Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Parabolic SAR indicator to trigger buy and sell orders. A buy order is placed +// when the Parabolic SAR flips below the price and the previous SAR value was above the price. +// A sell order is placed when the Parabolic SAR flips above the price and the previous SAR value +// was below the price. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,71 +17,84 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class ParabolicSARSample : Robot { - private double _volumeInUnits; + // Private fields for storing indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private ParabolicSAR _parabolicSAR; + private ParabolicSAR _parabolicSAR; // Store the Parabolic SAR indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "ParabolicSARSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this bot. [Parameter("Min AF", DefaultValue = 0.02, Group = "Parabolic SAR", MinValue = 0)] - public double MinAf { get; set; } + public double MinAf { get; set; } // Minimum Acceleration Factor for the Parabolic SAR, default is 0.02. [Parameter("Max AF", DefaultValue = 0.2, Group = "Parabolic SAR", MinValue = 0)] - public double MaxAf { get; set; } + public double MaxAf { get; set; } // Maximum Acceleration Factor (AF) for the Parabolic SAR, default is 0.2. + // This property retrieves all positions opened by this bot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label as this bot. } } + // This method is called when the bot starts and is used for initialization. protected override void OnStart() { + // Convert the volume in lots to the appropriate volume in units for the symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Parabolic SAR indicator. _parabolicSAR = Indicators.ParabolicSAR(MinAf, MaxAf); } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { + // If the Parabolic SAR is below the current bar and was above the previous bar, it is a buy signal. if (_parabolicSAR.Result.Last(0) < Bars.LowPrices.Last(0) && _parabolicSAR.Result.Last(1) > Bars.HighPrices.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a buy market order with the specified volume, stop loss and take profit. } + + // If the Parabolic SAR is above the current bar and was below the previous bar, it is a sell signal. else if (_parabolicSAR.Result.Last(0) > Bars.HighPrices.Last(0) && _parabolicSAR.Result.Last(1) < Bars.LowPrices.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a sell market order with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Partial Close Sample/Partial Close Sample/Partial Close Sample.cs b/Robots/Partial Close Sample/Partial Close Sample/Partial Close Sample.cs index b41887d..fd00ad8 100644 --- a/Robots/Partial Close Sample/Partial Close Sample/Partial Close Sample.cs +++ b/Robots/Partial Close Sample/Partial Close Sample/Partial Close Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates partial closing of positions at predefined levels. When a position reaches +// a specified pip value, a portion of the position is closed based on a percentage defined by the +// user. This allows for securing partial profits while letting the remaining position run. +// // ------------------------------------------------------------------------------------------------- using System; @@ -14,104 +18,127 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PartialCloseSample : Robot { + // Private fields for tracking closed positions at different levels. private readonly List _firstLevelClosedPositions = new List(); private readonly List _secondLevelClosedPositions = new List(); + // Parameters for first-level partial close. [Parameter("Close %", DefaultValue = 20, Group = "First Level")] - public double FirstLevelCloseAmountInPercentage { get; set; } + public double FirstLevelCloseAmountInPercentage { get; set; } // Percentage to close at first level, default is 20. [Parameter("Pips", DefaultValue = 20, Group = "First Level")] - public double FirstLevelClosePips { get; set; } + public double FirstLevelClosePips { get; set; } // Pips required to trigger the first-level close, default is 20. [Parameter("Close %", DefaultValue = 20, Group = "Second Level")] - public double SecondLevelCloseAmountInPercentage { get; set; } + public double SecondLevelCloseAmountInPercentage { get; set; } // Percentage to close at second level, default is 20. [Parameter("Pips", DefaultValue = 35, Group = "Second Level")] - public double SecondLevelClosePips { get; set; } + public double SecondLevelClosePips { get; set; } // Pips required to trigger the second-level close, default is 35. + // This method is called when the bot starts and is used for initialisation. protected override void OnStart() { - FirstLevelCloseAmountInPercentage /= 100; - SecondLevelCloseAmountInPercentage /= 100; + FirstLevelCloseAmountInPercentage /= 100; // Convert first level percentage to a decimal. + SecondLevelCloseAmountInPercentage /= 100; // Convert second level percentage to a decimal. - Positions.Opened += Positions_Opened; - Positions.Closed += Positions_Closed; + Positions.Opened += Positions_Opened; // Attach event handler for position opened. + Positions.Closed += Positions_Closed; // Attach event handler for position closed. } + // This method handles actions when a position is closed. private void Positions_Closed(PositionClosedEventArgs obj) { - // In case position closed fully clean it's enteries from ID collections + + // Check if the position is fully closed and no longer exists in the open positions list. if (Positions.Any(position => position.Id == obj.Position.Id) == false) { + // If the position was tracked in the first-level list, clean its enteries from ID collections. if (_firstLevelClosedPositions.Contains(obj.Position.Id)) { _firstLevelClosedPositions.Remove(obj.Position.Id); } + // If the position was tracked in the second-level list, clean its enteries from ID collections. if (_secondLevelClosedPositions.Contains(obj.Position.Id)) { _secondLevelClosedPositions.Remove(obj.Position.Id); } } - // If there are other positions from same symbol then don't remove the symbol Tick event handler + // If there are other positions from same symbol then do not remove the symbol Tick event handler. if (Positions.Any(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal))) { return; } - // If there is no other position from the closed position symbol then remove the Tick event handler + // If there is no other position from the closed position symbol then remove the Tick event handler. var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName); positionSymbol.Tick -= PositionSymbol_Tick; } + // This method is called when a position is opened. private void Positions_Opened(PositionOpenedEventArgs obj) { - // If there are other positions from same symbol then don't add the symbol Tick event handler - // Because we already have one + // If there are other positions from same symbol then do not add the symbol Tick event handler. + // Because we already have one. if (Positions.Count(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal)) > 1) { return; } - // Add position symbol tick event handler + // Add position symbol tick event handler. var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName); positionSymbol.Tick += PositionSymbol_Tick; } + // This method is triggered when a tick event occurs for a symbol. private void PositionSymbol_Tick(SymbolTickEventArgs obj) { + // Get all positions for the symbol that triggered the tick event. var symbolPositions = Positions.Where(position => position.SymbolName.Equals(obj.SymbolName, StringComparison.Ordinal)).ToArray(); + // Loop through each position for the symbol. foreach (var position in symbolPositions) { + // If the first level closing condition is met (position is not already closed and Pips exceed the threshold). if (_firstLevelClosedPositions.Contains(position.Id) == false && position.Pips >= FirstLevelClosePips) { + // Close a portion of the position based on the percentage defined for the first level. ClosePositionByVolumePercenatage(position, FirstLevelCloseAmountInPercentage); + // Add the position ID to the list of closed positions for the first level to avoid re-closing. _firstLevelClosedPositions.Add(position.Id); } + + // If the second level closing condition is met (position is not already closed and Pips exceed the second level threshold). else if (_secondLevelClosedPositions.Contains(position.Id) == false && position.Pips >= SecondLevelClosePips) { + // Close a portion of the position based on the percentage defined for the second level. ClosePositionByVolumePercenatage(position, SecondLevelCloseAmountInPercentage); + // Add the position ID to the list of closed positions for the second level to avoid re-closing. _secondLevelClosedPositions.Add(position.Id); } } } + // This method closes a specified percentage of the position volume. private void ClosePositionByVolumePercenatage(Position position, double volumePercent) { + // Get the symbol for the position. var symbol = Symbols.GetSymbol(position.SymbolName); + // Calculate the volume to close based on the percentage of the position total volume. var volumeToClose = symbol.NormalizeVolumeInUnits(position.VolumeInUnits * volumePercent); + // Close the calculated portion of the position. ClosePosition(position, volumeToClose); } } -} \ No newline at end of file +} diff --git a/Robots/Patterns Strategy Sample/Patterns Strategy Sample/Patterns Strategy Sample.cs b/Robots/Patterns Strategy Sample/Patterns Strategy Sample/Patterns Strategy Sample.cs index 170c2ac..6cd7aa3 100644 --- a/Robots/Patterns Strategy Sample/Patterns Strategy Sample/Patterns Strategy Sample.cs +++ b/Robots/Patterns Strategy Sample/Patterns Strategy Sample/Patterns Strategy Sample.cs @@ -18,35 +18,39 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class PatternsStrategySample : Robot { [Parameter(DefaultValue = 1000)] - public double Volume { get; set; } + public double Volume { get; set; } // Parameter for the trading volume, default value is 1000. [Parameter(DefaultValue = 10)] - public double StopLoss { get; set; } + public double StopLoss { get; set; } // Parameter for the stop loss in pips, default value is 10. [Parameter(DefaultValue = 10)] - public double TakeProfit { get; set; } + public double TakeProfit { get; set; } // Parameter for the take profit in pips, default value is 10. protected override void OnStart() { } + // This method is triggered whenever a bar is closed and drives the bot’s decision-making. protected override void OnBarClosed() { - if (Bars.Last(0).Close == Bars.Last(0).High && - (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2) + // Check for Hammer pattern (bullish) on the last bar. + if (Bars.Last(0).Close == Bars.Last(0).High && // Close price is equal to High. + (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2) // The body is less than 20% of the total bar size, with a longer lower wick. { - ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); + ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); // Open a buy market order with the specified volume, stop loss and take profit. } - if (Bars.Last(0).Close == Bars.Last(0).Low && - (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2) + // Check for Hanging Man pattern (bearish) on the last bar. + if (Bars.Last(0).Close == Bars.Last(0).Low && // Close price is equal to Low. + (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2) // The body is less than 20% of the total bar size, with a longer upper wick. { - ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); + ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); // Open a sell market order with the specified volume, stop loss and take profit. } } @@ -56,4 +60,4 @@ protected override void OnStop() } } -} \ No newline at end of file +} diff --git a/Robots/Pending Order Cancelation Sample/Pending Order Cancelation Sample/Pending Order Cancelation Sample.cs b/Robots/Pending Order Cancelation Sample/Pending Order Cancelation Sample/Pending Order Cancelation Sample.cs index 03e5285..52b8fd3 100644 --- a/Robots/Pending Order Cancelation Sample/Pending Order Cancelation Sample/Pending Order Cancelation Sample.cs +++ b/Robots/Pending Order Cancelation Sample/Pending Order Cancelation Sample/Pending Order Cancelation Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot searches for a pending order based on the specified comment and label, and if found, +// cancels the order. It allows filtering the orders by comment, label or both. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,40 +16,44 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrderCancelationSample : Robot { [Parameter("Order Comment")] - public string OrderComment { get; set; } + public string OrderComment { get; set; } // Store the comment for the order. [Parameter("Order Label")] - public string OrderLabel { get; set; } + public string OrderLabel { get; set; } // Store the label for the order. + // This method is called when the bot starts. protected override void OnStart() { - PendingOrder order = null; + PendingOrder order = null; // Initialize a variable to store the pending order. - if (!string.IsNullOrWhiteSpace(OrderComment) && !string.IsNullOrWhiteSpace(OrderLabel)) + if (!string.IsNullOrWhiteSpace(OrderComment) && !string.IsNullOrWhiteSpace(OrderLabel)) // Checks if both order comment and label are provided. { + // Searches for the pending order with the specified comment and label. order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, OrderComment, StringComparison.OrdinalIgnoreCase) && string.Equals(iOrder.Label, OrderLabel, StringComparison.OrdinalIgnoreCase)); } - else if (!string.IsNullOrWhiteSpace(OrderComment)) + else if (!string.IsNullOrWhiteSpace(OrderComment)) // If only the comment is provided. { + // Searches for the pending order with the specified comment. order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, OrderComment, StringComparison.OrdinalIgnoreCase)); } - else if (!string.IsNullOrWhiteSpace(OrderLabel)) + else if (!string.IsNullOrWhiteSpace(OrderLabel)) // If only the label is provided. { + // Searches for the pending order with the specified label. order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Label, OrderLabel, StringComparison.OrdinalIgnoreCase)); } - - if (order == null) + if (order == null) // If no order matching the criteria was found. { - Print("Couldn't find the order, please check the comment and label"); + Print("Couldn't find the order, please check the comment and label"); // Prints an error message. - Stop(); + Stop(); // Stops the robot as the order could not be found. } - CancelPendingOrder(order); + CancelPendingOrder(order); // Cancels the found pending order. } } -} \ No newline at end of file +} diff --git a/Robots/Pending Order Events/Pending Order Events/Pending Order Events.cs b/Robots/Pending Order Events/Pending Order Events/Pending Order Events.cs index c81fc4e..cd18a3d 100644 --- a/Robots/Pending Order Events/Pending Order Events/Pending Order Events.cs +++ b/Robots/Pending Order Events/Pending Order Events/Pending Order Events.cs @@ -5,39 +5,48 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot is intended to demonstrate the handling of pending order events. It subscribes to +// three events related to pending orders: Cancelled, Modified and Filled. The cBot performs +// actions when these events occur, such as processing the filled order or handling modifications +// and cancellations. // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrderEvents : Robot { + // This method is called when the bot starts. protected override void OnStart() { - PendingOrders.Cancelled += PendingOrders_Cancelled; - PendingOrders.Modified += PendingOrders_Modified; - PendingOrders.Filled += PendingOrders_Filled; + PendingOrders.Cancelled += PendingOrders_Cancelled; // Subscribe to the PendingOrders Cancelled event. + PendingOrders.Modified += PendingOrders_Modified; // Subscribe to the PendingOrders Modified event. + PendingOrders.Filled += PendingOrders_Filled; // Subscribe to the PendingOrders Filled event. } + // This method is triggered when a pending order is filled. private void PendingOrders_Filled(PendingOrderFilledEventArgs obj) { - var pendingOrderThatFilled = obj.PendingOrder; + var pendingOrderThatFilled = obj.PendingOrder; // Retrieve the pending order that was filled. - var filledPosition = obj.Position; + var filledPosition = obj.Position; // Retrieve the position associated with the filled order. } + // This method is triggered when a pending order is modified. private void PendingOrders_Modified(PendingOrderModifiedEventArgs obj) { - var modifiedOrder = obj.PendingOrder; + var modifiedOrder = obj.PendingOrder; // Retrieve the modified pending order. } + // This method is triggered when a pending order is cancelled. private void PendingOrders_Cancelled(PendingOrderCancelledEventArgs obj) { - var cancelledOrder = obj.PendingOrder; + var cancelledOrder = obj.PendingOrder; // Retrieve the cancelled pending order. - var cancellationReason = obj.Reason; + var cancellationReason = obj.Reason; // Retrieve the reason for the cancellation. } } -} \ No newline at end of file +} diff --git a/Robots/Pending Order Modification Sample/Pending Order Modification Sample/Pending Order Modification Sample.cs b/Robots/Pending Order Modification Sample/Pending Order Modification Sample/Pending Order Modification Sample.cs index 5789320..9e2b5e5 100644 --- a/Robots/Pending Order Modification Sample/Pending Order Modification Sample/Pending Order Modification Sample.cs +++ b/Robots/Pending Order Modification Sample/Pending Order Modification Sample/Pending Order Modification Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to modify pending orders in cAlgo. The bot allows modifications to +// pending orders based on parameters such as Target Price, Stop Loss, Take Profit, Expiry Time +// and more. It supports modifying Limit, Stop and Stop Limit orders. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -14,111 +18,141 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrderModificationSample : Robot { + // Define input parameters for the cBot. [Parameter("Order Comment")] - public string OrderComment { get; set; } + public string OrderComment { get; set; } // Order comment for the pending order. [Parameter("Order Label")] - public string OrderLabel { get; set; } + public string OrderLabel { get; set; } // Order label for the pending order. [Parameter("Target Price", DefaultValue = 0.0)] - public double TargetPrice { get; set; } + public double TargetPrice { get; set; } // Target price for the pending order, which defaults to 0.0. [Parameter("Stop Loss (Pips)", DefaultValue = 10)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Stop Loss Trigger Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopLossTriggerMethod { get; set; } + public StopTriggerMethod StopLossTriggerMethod { get; set; } // Stop loss trigger method, default value is Trade. [Parameter("Take Profit (Pips)", DefaultValue = 10)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Expiry (HH:mm:ss)")] - public string Expiry { get; set; } + public string Expiry { get; set; } // Expiry time for the pending order in HH:mm:ss format. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Volume in lots, which defaults to 0.01. [Parameter("Has Trailing Stop", DefaultValue = false)] - public bool HasTrailingStop { get; set; } + public bool HasTrailingStop { get; set; } // Whether to use a trailing stop, default value is false. [Parameter("Order Trigger Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod OrderTriggerMethod { get; set; } + public StopTriggerMethod OrderTriggerMethod { get; set; } // Order trigger method for stop orders, default value is Trade. [Parameter("Limit Range (Pips)", DefaultValue = 10)] - public double LimitRangeInPips { get; set; } + public double LimitRangeInPips { get; set; } // Limit range in pips for stop limit orders, which defaults to 10. + // This method is called when the cBot starts. protected override void OnStart() { PendingOrder order = null; + // Search for a pending order using both comment and label. + // If found, the order is stored in the variable 'order' for further modifications. if (!string.IsNullOrWhiteSpace(OrderComment) && !string.IsNullOrWhiteSpace(OrderComment)) { order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, OrderComment, StringComparison.OrdinalIgnoreCase) && string.Equals(iOrder.Label, OrderLabel, StringComparison.OrdinalIgnoreCase)); } + + // Search for a pending order using comment only. + // If found, the order is stored in the variable 'order' for further modifications. else if (!string.IsNullOrWhiteSpace(OrderComment)) { order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, OrderComment, StringComparison.OrdinalIgnoreCase)); } + + // Search for a pending order using label only. + // If found, the order is stored in the variable 'order' for further modifications. else if (!string.IsNullOrWhiteSpace(OrderLabel)) { order = PendingOrders.FirstOrDefault(iOrder => string.Equals(iOrder.Label, OrderLabel, StringComparison.OrdinalIgnoreCase)); } + // Stops execution if no matching order is found. if (order == null) { Print("Couldn't find the order, please check the comment and label"); - Stop(); } + // Set target price or keep the original value. var targetPrice = TargetPrice == 0 ? order.TargetPrice : TargetPrice; + // Get symbol details of the order. var orderSymbol = Symbols.GetSymbol(order.SymbolName); + // Set stop-loss and take-profit values or keep the original. var stopLossInPips = StopLossInPips == 0 ? order.StopLossPips : (double?)StopLossInPips; var takeProfitInPips = TakeProfitInPips == 0 ? order.TakeProfitPips : (double?)TakeProfitInPips; - DateTime? expiryTime; + DateTime? expiryTime; // Declare a nullable DateTime variable to store the expiry time of the pending order. + // Set expiry time or keep the original value. if (string.IsNullOrWhiteSpace(Expiry)) { expiryTime = order.ExpirationTime; } + + // Set expiry to null if explicitly defined as "0". else if (Expiry.Equals("0", StringComparison.OrdinalIgnoreCase)) { expiryTime = null; } + + // Parse expiry time from input. else { - var expiryTimeSpan = default(TimeSpan); + var expiryTimeSpan = default(TimeSpan); // Initialize a TimeSpan variable to hold the parsed expiry duration. + // Try to parse the "Expiry" parameter into a TimeSpan using HH:mm:ss format. if (!TimeSpan.TryParse(Expiry, CultureInfo.InvariantCulture, out expiryTimeSpan)) { + // If parsing fails, print an error message and stop the cBot execution. Print("Your provided value for expiry is not valid, please use HH:mm:ss format"); - Stop(); } + // If the parsed TimeSpan is valid and not the default, calculate expiry time. expiryTime = expiryTimeSpan == default(TimeSpan) ? null : (DateTime?)Server.Time.Add(expiryTimeSpan); } + // Calculate volume in units or keep the original. var volumeInUnits = VolumeInLots == 0 ? order.VolumeInUnits : orderSymbol.QuantityToVolumeInUnits(VolumeInLots); + // Check if the pending order is of type Limit. + // If yes, modify the order with the specified parameters. if (order.OrderType == PendingOrderType.Limit) { ModifyPendingOrder(order, targetPrice, stopLossInPips, takeProfitInPips, expiryTime, volumeInUnits, HasTrailingStop, StopLossTriggerMethod); } + + // Check if the pending order is of type Stop. + // If yes, modify the order with the specified parameters, including the order trigger method. else if (order.OrderType == PendingOrderType.Stop) { ModifyPendingOrder(order, targetPrice, stopLossInPips, takeProfitInPips, expiryTime, volumeInUnits, HasTrailingStop, StopLossTriggerMethod, OrderTriggerMethod); } + + // Check if the pending order is of type StopLimit. + // If yes, modify the order with the specified parameters, including the limit range in pips. else if (order.OrderType == PendingOrderType.StopLimit) { ModifyPendingOrder(order, targetPrice, stopLossInPips, takeProfitInPips, expiryTime, volumeInUnits, HasTrailingStop, StopLossTriggerMethod, OrderTriggerMethod, LimitRangeInPips); } } } -} \ No newline at end of file +} diff --git a/Robots/Pending Order Placing Sample/Pending Order Placing Sample/Pending Order Placing Sample.cs b/Robots/Pending Order Placing Sample/Pending Order Placing Sample/Pending Order Placing Sample.cs index b02af6c..ae532af 100644 --- a/Robots/Pending Order Placing Sample/Pending Order Placing Sample/Pending Order Placing Sample.cs +++ b/Robots/Pending Order Placing Sample/Pending Order Placing Sample/Pending Order Placing Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot places pending orders (Limit, Stop or StopLimit) for the specified trade direction, +// volume and other parameters. It allows users to set a trailing stop, specify expiry times and +// choose whether orders are placed asynchronously or synchronously. The bot validates the parameters, +// handles the order placement process and invokes a callback function when the trade is completed. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,119 +18,134 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrderPlacingSample : Robot { [Parameter("Type", DefaultValue = PendingOrderType.Limit)] - public PendingOrderType OrderType { get; set; } + public PendingOrderType OrderType { get; set; } // Order type parameter with a default value of PendingOrderType.Limit. [Parameter("Direction", DefaultValue = TradeType.Buy)] - public TradeType OrderTradeType { get; set; } + public TradeType OrderTradeType { get; set; } // Trade direction (buy or sell) for the order. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Volume in lots for the trade, defaulting to 0.01 lots. [Parameter("Distance (Pips)", DefaultValue = 20, MinValue = 1)] - public double DistanceInPips { get; set; } + public double DistanceInPips { get; set; } // Distance in pips from the current price for pending orders, defaulting to 20 pips. [Parameter("Stop (Pips)", DefaultValue = 10, MinValue = 0)] - public double StopInPips { get; set; } + public double StopInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Target (Pips)", DefaultValue = 10, MinValue = 0)] - public double TargetInPips { get; set; } + public double TargetInPips { get; set; } // Target (take profit) in pips, defaulting to 10 pips. [Parameter("Limit Range (Pips)", DefaultValue = 10, MinValue = 1)] - public double LimitRangeInPips { get; set; } + public double LimitRangeInPips { get; set; } // Limit range for stop limit orders, defaulting to 10 pips. [Parameter("Expiry", DefaultValue = "00:00:00")] - public string Expiry { get; set; } + public string Expiry { get; set; } // Expiry time for pending orders in HH:mm:ss format. [Parameter("Label")] - public string Label { get; set; } + public string Label { get; set; } // Label for the order to help identify it. [Parameter("Comment")] - public string Comment { get; set; } + public string Comment { get; set; } // Comment for the order to provide additional context. [Parameter("Trailing Stop", DefaultValue = false)] - public bool HasTrailingStop { get; set; } + public bool HasTrailingStop { get; set; } // Enable or disable trailing stop for the order, disabled by default. [Parameter("Stop Loss Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopLossTriggerMethod { get; set; } + public StopTriggerMethod StopLossTriggerMethod { get; set; } // Method for stop loss trigger. [Parameter("Stop Order Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopOrderTriggerMethod { get; set; } + public StopTriggerMethod StopOrderTriggerMethod { get; set; } // Method for stop order trigger. [Parameter("Async", DefaultValue = false)] - public bool IsAsync { get; set; } + public bool IsAsync { get; set; } // Whether the order should be placed asynchronously, disabled by default. + // This method is called when the cBot starts. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. var volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Adjust the distance in pips according to the symbol pip size. DistanceInPips *= Symbol.PipSize; + // Set stop-loss and take-profit values or null if they are zero. var stopLoss = StopInPips == 0 ? null : (double?)StopInPips; var takeProfit = TargetInPips == 0 ? null : (double?)TargetInPips; - TimeSpan expiry; + TimeSpan expiry; // Declare expiry as a TimeSpan. + // Try parsing the expiry string into a TimeSpan. if (!TimeSpan.TryParse(Expiry, CultureInfo.InvariantCulture, out expiry)) { + // Print an error message and stop the cBot if expiry time is invalid. Print("Invalid expiry"); - Stop(); } + // Calculate the expiry time, adding the expiry TimeSpan to the server time if valid. var expiryTime = expiry != TimeSpan.FromSeconds(0) ? (DateTime?)Server.Time.Add(expiry) : null; - TradeResult result = null; + TradeResult result = null; // Initialize the trade result variable. + // Switch to handle different order types: Limit, Stop or StopLimit. switch (OrderType) { case PendingOrderType.Limit: - var limitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask - DistanceInPips : Symbol.Ask + DistanceInPips; + var limitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask - DistanceInPips : Symbol.Ask + DistanceInPips; // Calculate the price for a limit order based on the trade direction. + // If the IsAsync flag is true, place the limit order asynchronously. if (IsAsync) PlaceLimitOrderAsync(OrderTradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, OnCompleted); + // If the IsAsync flag is false, place the limit order synchronously. else result = PlaceLimitOrder(OrderTradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod); break; case PendingOrderType.Stop: - var stopPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips; + var stopPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips; // Calculate the stop price based on the trade direction. + // If the IsAsync flag is true, place the stop order asynchronously. if (IsAsync) PlaceStopOrderAsync(OrderTradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod, OnCompleted); + // If the IsAsync flag is false, place the stop order synchronously. else - result = PlaceStopOrder(OrderTradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod); + result = PlaceStopOrder(OrderTradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod); // Place the stop order. break; case PendingOrderType.StopLimit: - var stopLimitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips; + var stopLimitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips; // Calculate the stop limit price based on the trade direction. + // If the IsAsync flag is true, place the stop limit order asynchronously. if (IsAsync) PlaceStopLimitOrderAsync(OrderTradeType, SymbolName, volumeInUnits, stopLimitPrice, LimitRangeInPips, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod, OnCompleted); + // If the IsAsync flag is false, place the stop limit order synchronously. else result = PlaceStopLimitOrder(OrderTradeType, SymbolName, volumeInUnits, stopLimitPrice, LimitRangeInPips, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod); break; default: - Print("Invalid order type"); + Print("Invalid order type"); // Print an error message if the order type is invalid. - throw new ArgumentOutOfRangeException("OrderType"); + throw new ArgumentOutOfRangeException("OrderType"); // Throw an exception if the order type is not valid. } - if (!IsAsync) OnCompleted(result); + if (!IsAsync) OnCompleted(result); // If the order is not placed asynchronously, trigger the completion for synchronous execution. } + // This method is called when the trade order is completed, either successfully or with an error. private void OnCompleted(TradeResult result) { - if (!result.IsSuccessful) Print("Error: ", result.Error); + if (!result.IsSuccessful) Print("Error: ", result.Error); // Print an error message if the order was not successful. - Stop(); + Stop(); // Stop the robot after completing the trade. } } -} \ No newline at end of file +} diff --git a/Robots/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample.cs b/Robots/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample.cs index a40e12a..3425431 100644 --- a/Robots/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample.cs +++ b/Robots/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample/PendingOrderCancellationReason Sample.cs @@ -5,38 +5,45 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot listens for the cancellation of pending orders and handles different reasons for +// cancellation (Cancelled, Expired or Rejected). It prints the cancellation reason and allows +// you to add custom actions based on the specific reason for the cancellation. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrderCancellationReasonSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { - PendingOrders.Cancelled += PendingOrders_Cancelled; + PendingOrders.Cancelled += PendingOrders_Cancelled; // Subscribe to the event that is triggered when a pending order is cancelled. } + // This method handles the cancellation event. private void PendingOrders_Cancelled(PendingOrderCancelledEventArgs obj) { - Print(obj.Reason); + Print(obj.Reason); // Print the reason for order cancellation. - switch (obj.Reason) + switch (obj.Reason) // Switches based on the reason for the cancellation. { case PendingOrderCancellationReason.Cancelled: - // Do something if order cancelled + // Do something if order cancelled. break; case PendingOrderCancellationReason.Expired: - // Do something if order expired + // Do something if order expired. break; case PendingOrderCancellationReason.Rejected: - // Do something if order rejected + // Do something if order rejected. break; } } } -} \ No newline at end of file +} diff --git a/Robots/PendingOrders Sample/PendingOrders Sample/PendingOrders Sample.cs b/Robots/PendingOrders Sample/PendingOrders Sample/PendingOrders Sample.cs index 38937c4..2454e17 100644 --- a/Robots/PendingOrders Sample/PendingOrders Sample/PendingOrders Sample.cs +++ b/Robots/PendingOrders Sample/PendingOrders Sample/PendingOrders Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot listens for events such as creation, modification, filling and cancellation of pending +// orders and logs the related information. +// // ------------------------------------------------------------------------------------------------- using System; @@ -13,44 +16,50 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PendingOrdersSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { + // Subscribes to various pending orders events: Cancelled, Created, Modified, Filled. PendingOrders.Cancelled += PendingOrders_Cancelled; PendingOrders.Created += PendingOrders_Created; PendingOrders.Modified += PendingOrders_Modified; PendingOrders.Filled += PendingOrders_Filled; + // LINQ query to filter orders with MyOrders label. var myOrders = PendingOrders.Where(order => order.Label.Equals("MyOrders", StringComparison.OrdinalIgnoreCase)); + // LINQ query to select target prices of all pending orders. var orderPrices = from order in PendingOrders select order.TargetPrice; + // LINQ query to select symbols of all pending orders. var orderSymbols = from order in PendingOrders - let symbol = Symbols.GetSymbol(order.SymbolName) + let symbol = Symbols.GetSymbol(order.SymbolName) // Retrieve the symbol for each order. select symbol; } - private void PendingOrders_Filled(PendingOrderFilledEventArgs obj) + private void PendingOrders_Filled(PendingOrderFilledEventArgs obj) // Handle the event when a pending order is filled. { - Print("Order Filled: {0}", obj.PendingOrder.Id); + Print("Order Filled: {0}", obj.PendingOrder.Id); // Print the ID of the filled order. } - private void PendingOrders_Modified(PendingOrderModifiedEventArgs obj) + private void PendingOrders_Modified(PendingOrderModifiedEventArgs obj) // Handle the event when a pending order is modified. { - Print("Order Modified: {0}", obj.PendingOrder.Id); + Print("Order Modified: {0}", obj.PendingOrder.Id); // Print the ID of the modified order. } - private void PendingOrders_Created(PendingOrderCreatedEventArgs obj) + private void PendingOrders_Created(PendingOrderCreatedEventArgs obj) // Handle the event when a pending order is created. { - Print("Order Created: {0}", obj.PendingOrder.Id); + Print("Order Created: {0}", obj.PendingOrder.Id); // Print the ID of the created order. } - private void PendingOrders_Cancelled(PendingOrderCancelledEventArgs obj) + private void PendingOrders_Cancelled(PendingOrderCancelledEventArgs obj) // Handle the event when a pending order is cancelled. { - Print("Order Cancelled: {0}", obj.PendingOrder.Id); + Print("Order Cancelled: {0}", obj.PendingOrder.Id); // Print the ID of the cancelled order. } } -} \ No newline at end of file +} diff --git a/Robots/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample.cs b/Robots/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample.cs index 5db2509..e78f4fd 100644 --- a/Robots/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample.cs +++ b/Robots/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample/Polynomial Regression Channels Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot is an example of using Polynomial Regression Channels with the cTrader Algo API. +// The bot uses these channels to detect potential trend reversals, closing the opposite positions +// and opening new ones based on price action relative to the regression channels. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,74 +16,87 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class PolynomialRegressionChannelsSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private PolynomialRegressionChannels _polynomialRegressionChannels; + private PolynomialRegressionChannels _polynomialRegressionChannels; // Store the Polynomial Regression Channels indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Label", DefaultValue = "PolynomialRegressionChannelsSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // Parameters for configuring the Polynomial Regression Channels. [Parameter("Source", Group = "Polynomial Regression Channels")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Parameter to define the source data series (e.g., closing prices). [Parameter(DefaultValue = 3.0, Group = "Polynomial Regression Channels", MinValue = 1, MaxValue = 4)] - public int Degree { get; set; } + public int Degree { get; set; } // Polynomial degree setting with range between 1 and 4. [Parameter(DefaultValue = 120, Group = "Polynomial Regression Channels", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Period setting for the Polynomial Regression Channels. [Parameter("Standard Deviation", DefaultValue = 1.62, Group = "Polynomial Regression Channels", Step = 0.01)] - public double StandardDeviation { get; set; } + public double StandardDeviation { get; set; } // Standard deviation parameter for the first channel. [Parameter("Standard Deviation 2", DefaultValue = 2, Group = "Polynomial Regression Channels", Step = 0.01)] - public double StandardDeviation2 { get; set; } - + public double StandardDeviation2 { get; set; } // Standard deviation parameter for the second channel. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Instantiates the Polynomial Regression Channels indicator with parameters. _polynomialRegressionChannels = Indicators.PolynomialRegressionChannels(Degree, Periods, StandardDeviation, StandardDeviation2); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the low price of the current bar crosses below the lower regression channel. if (Bars.LowPrices.Last(0) <= _polynomialRegressionChannels.Sql.Last(0) && Bars.LowPrices.Last(1) > _polynomialRegressionChannels.Sql.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label); // Open a market order to buy. } + + // Check if the high price of the current bar crosses above the upper regression channel. else if (Bars.HighPrices.Last(0) >= _polynomialRegressionChannels.Sqh.Last(0) && Bars.HighPrices.Last(1) < _polynomialRegressionChannels.Sqh.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label); // Open a market order to sell. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Position Bars Passed Sample/Position Bars Passed Sample/Position Bars Passed Sample.cs b/Robots/Position Bars Passed Sample/Position Bars Passed Sample/Position Bars Passed Sample.cs index 2974b29..3692a65 100644 --- a/Robots/Position Bars Passed Sample/Position Bars Passed Sample/Position Bars Passed Sample.cs +++ b/Robots/Position Bars Passed Sample/Position Bars Passed Sample/Position Bars Passed Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot example calculates the number of bars that have passed since each position with a +// specified label was opened. The bot demonstrates how to work with position properties and +// bar indexing in the cTrader API. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,26 +16,33 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionBarsPassedSample : Robot { [Parameter("Label", DefaultValue = "MyBot")] - public string Label { get; set; } + public string Label { get; set; } // Store the unique label for filtering positions. + // This method is called when the cBot starts. protected override void OnStart() { - var currentIndex = Bars.Count - 1; + var currentIndex = Bars.Count - 1; // Get the index of the most recent bar. + // Loop through all open positions. foreach (var position in Positions) { + // Check if the position label matches the specified label. if (!string.Equals(position.Label, Label, StringComparison.OrdinalIgnoreCase)) continue; + // Determine the index of the bar when the position was opened. var positionOpenBarIndex = Bars.OpenTimes.GetIndexByTime(position.EntryTime); + // Calculate the number of bars that have passed since the position was opened. var numberOfBarsPassedSincePositionOpened = currentIndex - positionOpenBarIndex; + // Output the calculated number of bars to the log. Print(numberOfBarsPassedSincePositionOpened); } } } -} \ No newline at end of file +} diff --git a/Robots/Position Closing Sample/Position Closing Sample/Position Closing Sample.cs b/Robots/Position Closing Sample/Position Closing Sample/Position Closing Sample.cs index 562eaf2..8fec211 100644 --- a/Robots/Position Closing Sample/Position Closing Sample/Position Closing Sample.cs +++ b/Robots/Position Closing Sample/Position Closing Sample/Position Closing Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to find and close a trading position based on its label, comment +// or a combination of both. It identifies the relevant position and executes the closing process. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,40 +16,50 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionClosingSample : Robot { [Parameter("Position Comment")] - public string PositionComment { get; set; } + public string PositionComment { get; set; } // Parameter to specify the comment associated with a position. [Parameter("Position Label")] - public string PositionLabel { get; set; } + public string PositionLabel { get; set; } // Parameter to specify the label associated with a position. + // The main method executed when the cBot starts. protected override void OnStart() { - Position position = null; + Position position = null; // Initialize a variable to hold the target position. + // Check if both comment and label parameters are provided. if (!string.IsNullOrWhiteSpace(PositionComment) && !string.IsNullOrWhiteSpace(PositionLabel)) { + // Find the first position that matches the label and comment. position = Positions.FindAll(PositionLabel).FirstOrDefault(iOrder => string.Equals(iOrder.Comment, PositionComment, StringComparison.OrdinalIgnoreCase)); } + + // Check if only the comment parameter is provided. else if (!string.IsNullOrWhiteSpace(PositionComment)) { + // Find the first position that matches the comment. position = Positions.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, PositionComment, StringComparison.OrdinalIgnoreCase)); } + + // Check if only the label parameter is provided. else if (!string.IsNullOrWhiteSpace(PositionLabel)) { + // Find the first position that matches the label. position = Positions.Find(PositionLabel); } + // If no matching position is found. if (position == null) { - Print("Couldn't find the position, please check the comment and label"); - - Stop(); + Print("Couldn't find the position, please check the comment and label"); // Log a message indicating the position could not be found. + Stop(); // Stop the cBot to avoid further processing. } - ClosePosition(position); + ClosePosition(position); // Close the identified position. } } -} \ No newline at end of file +} diff --git a/Robots/Position Events Sample/Position Events Sample/Position Events Sample.cs b/Robots/Position Events Sample/Position Events Sample/Position Events Sample.cs index a71d37f..fbd9ca2 100644 --- a/Robots/Position Events Sample/Position Events Sample/Position Events Sample.cs +++ b/Robots/Position Events Sample/Position Events Sample/Position Events Sample.cs @@ -5,37 +5,49 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot tracks position events, including opening, closing and modifications. +// It subscribes to position-related events and processes data when these events occur. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionEventsSample : Robot { + // The main method executed when the cBot starts. protected override void OnStart() { - Positions.Opened += Positions_Opened; - Positions.Closed += Positions_Closed; - Positions.Modified += Positions_Modified; + Positions.Opened += Positions_Opened; // Subscribe to the Positions.Opened event to handle actions when a position is opened. + Positions.Closed += Positions_Closed; // Subscribe to the Positions.Closed event to handle actions when a position is closed. + Positions.Modified += Positions_Modified; // Subscribe to the Positions.Modified event to handle actions when a position is modified. } + // This method is triggered whenever an existing position is modified. private void Positions_Modified(PositionModifiedEventArgs obj) { + // Capture details of the modified position for further processing or logging. var modifiedPosition = obj.Position; } + // This method is triggered whenever a position is closed. private void Positions_Closed(PositionClosedEventArgs obj) { + // Capture details of the closed position, including the position itself and the reason for closing. var closedPosition = obj.Position; + // Identify the reason for the position closure (e.g., StopLoss, TakeProfit or ManualClose). var closeReason = obj.Reason; } + // This method is triggered whenever a position is opened. private void Positions_Opened(PositionOpenedEventArgs obj) { + // Capture details of the newly opened position for further processing or logging. var openedPosition = obj.Position; } } -} \ No newline at end of file +} diff --git a/Robots/Position Execution Sample/Position Execution Sample/Position Execution Sample.cs b/Robots/Position Execution Sample/Position Execution Sample/Position Execution Sample.cs index 884befe..a1a26b3 100644 --- a/Robots/Position Execution Sample/Position Execution Sample/Position Execution Sample.cs +++ b/Robots/Position Execution Sample/Position Execution Sample/Position Execution Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to execute a market order based on user-defined parameters, +// supporting both synchronous and asynchronous operations. It also handles trailing stops and +// other advanced trading features. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,63 +16,69 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionExecutionSample : Robot { [Parameter("Direction", DefaultValue = TradeType.Buy)] - public TradeType Direction { get; set; } + public TradeType Direction { get; set; } // The trade direction, default is Buy. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Volume to trade in lots, default is 0.01. [Parameter("Distance (Pips)", DefaultValue = 20, MinValue = 1)] - public double DistanceInPips { get; set; } + public double DistanceInPips { get; set; } // Distance in pips for price levels, defaulting to 20 pips. [Parameter("Stop (Pips)", DefaultValue = 10, MinValue = 0)] - public double StopInPips { get; set; } + public double StopInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Target (Pips)", DefaultValue = 10, MinValue = 0)] - public double TargetInPips { get; set; } + public double TargetInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Comment")] - public string Comment { get; set; } + public string Comment { get; set; } // Additional text to attach to the order. [Parameter("Trailing Stop", DefaultValue = false)] - public bool HasTrailingStop { get; set; } + public bool HasTrailingStop { get; set; } // Enable trailing stop, default is false. [Parameter("Stop Loss Trigger Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopLossTriggerMethod { get; set; } + public StopTriggerMethod StopLossTriggerMethod { get; set; } // Triggering mechanism for the stop loss, default is Trade. [Parameter("Async", DefaultValue = false)] - public bool IsAsync { get; set; } + public bool IsAsync { get; set; } // Place the order asynchronously if true, default is false. + // The main method executed when the cBot starts. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. var volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); - DistanceInPips *= Symbol.PipSize; + DistanceInPips *= Symbol.PipSize; // Adjusts the distance in pips to price. + // Set stop-loss and take-profit values or keep the original. var stopLoss = StopInPips == 0 ? null : (double?)StopInPips; var takeProfit = TargetInPips == 0 ? null : (double?)TargetInPips; TradeResult result = null; + // If the IsAsync flag is true, place the limit order asynchronously. if (IsAsync) ExecuteMarketOrderAsync(Direction, SymbolName, volumeInUnits, Label, stopLoss, takeProfit, Comment, HasTrailingStop, StopLossTriggerMethod, OnCompleted); + // If the IsAsync flag is false, place the limit order synchronously. else result = ExecuteMarketOrder(Direction, SymbolName, volumeInUnits, Label, stopLoss, takeProfit, Comment, HasTrailingStop, StopLossTriggerMethod); - if (!IsAsync) OnCompleted(result); + if (!IsAsync) OnCompleted(result); // If the order is not placed asynchronously, trigger the completion for synchronous execution. } private void OnCompleted(TradeResult result) { - if (!result.IsSuccessful) Print("Error: ", result.Error); + if (!result.IsSuccessful) Print("Error: ", result.Error); // Logs the error if the order fails. - Stop(); + Stop(); // Stops the cBot execution. } } -} \ No newline at end of file +} diff --git a/Robots/Position Modification Sample/Position Modification Sample/Position Modification Sample.cs b/Robots/Position Modification Sample/Position Modification Sample/Position Modification Sample.cs index d39a188..1a63ca7 100644 --- a/Robots/Position Modification Sample/Position Modification Sample/Position Modification Sample.cs +++ b/Robots/Position Modification Sample/Position Modification Sample/Position Modification Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to modify an existing position by adjusting stop loss, +// take profit, trailing stop or volume. It identifies the position using label or comment +// parameters and applies user-defined modifications. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,82 +17,102 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionModificationSample : Robot { [Parameter("Position Comment")] - public string PositionComment { get; set; } + public string PositionComment { get; set; } // Comment to identify the position. [Parameter("Position Label")] - public string PositionLabel { get; set; } + public string PositionLabel { get; set; } // Label to identify the position. [Parameter("Stop Loss (Pips)", DefaultValue = 10)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Stop Loss Trigger Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopLossTriggerMethod { get; set; } + public StopTriggerMethod StopLossTriggerMethod { get; set; } // Stop loss trigger method, default is Trade. [Parameter("Take Profit (Pips)", DefaultValue = 10)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Volume in lots for the trade, defaulting to 0.01 lots. [Parameter("Has Trailing Stop", DefaultValue = false)] - public bool HasTrailingStop { get; set; } + public bool HasTrailingStop { get; set; } // Whether to use a trailing stop, default value is false. + // This method is called when the cBot starts. protected override void OnStart() { Position position = null; + // Check if both position comment and label are provided for identification. if (!string.IsNullOrWhiteSpace(PositionComment) && !string.IsNullOrWhiteSpace(PositionLabel)) { + // Find a position that matches both the label and comment provided. position = Positions.FindAll(PositionLabel).FirstOrDefault(iOrder => string.Equals(iOrder.Comment, PositionComment, StringComparison.OrdinalIgnoreCase)); } + + // Check if only the position comment is provided for identification. else if (!string.IsNullOrWhiteSpace(PositionComment)) { + // Find the first position with a matching comment. position = Positions.FirstOrDefault(iOrder => string.Equals(iOrder.Comment, PositionComment, StringComparison.OrdinalIgnoreCase)); } + + // Check if only the position label is provided for identification. else if (!string.IsNullOrWhiteSpace(PositionLabel)) { + // Find a position with the matching label. position = Positions.Find(PositionLabel); } + // If no position is found, output an error message and stops the cBot. if (position == null) { Print("Couldn't find the position, please check the comment and label"); - Stop(); } - var positionSymbol = Symbols.GetSymbol(position.SymbolName); + var positionSymbol = Symbols.GetSymbol(position.SymbolName); // Retrieve the symbol information of the identified position. - var stopLossInPrice = position.StopLoss; + var stopLossInPrice = position.StopLoss; // Initialise the stop loss price variable with the current position stop loss. + // Check if the user has defined a stop loss in pips. if (StopLossInPips > 0) { + // Convert the stop loss in pips to price. var stopLossInPipsPrice = StopLossInPips * positionSymbol.PipSize; + // Calculate the stop loss price based on the trade type. stopLossInPrice = position.TradeType == TradeType.Buy ? position.EntryPrice - stopLossInPipsPrice : position.EntryPrice + stopLossInPipsPrice; } - var takeProfitInPrice = position.TakeProfit; + var takeProfitInPrice = position.TakeProfit; // Initialise the take profit price variable with the current position's take profit. + // Check if the user has defined a take profit in pips. if (TakeProfitInPips > 0) { + // Convert the take profit in pips to price. var takeProfitInPipsPrice = TakeProfitInPips * positionSymbol.PipSize; + // Calculate the take profit price based on the trade type. takeProfitInPrice = position.TradeType == TradeType.Buy ? position.EntryPrice + takeProfitInPipsPrice : position.EntryPrice - takeProfitInPipsPrice; } + // Modify the position with the new stop loss, take profit, trailing stop and stop loss trigger method. ModifyPosition(position, stopLossInPrice, takeProfitInPrice, HasTrailingStop, StopLossTriggerMethod); + // Check if the user has specified a new volume in lots. if (VolumeInLots > 0) { + // Convert the volume in lots to units. var volumeInUnits = positionSymbol.QuantityToVolumeInUnits(VolumeInLots); + // Update the position with the new volume. ModifyPosition(position, volumeInUnits); } } } -} \ No newline at end of file +} diff --git a/Robots/PositionCloseReason Sample/PositionCloseReason Sample/PositionCloseReason Sample.cs b/Robots/PositionCloseReason Sample/PositionCloseReason Sample/PositionCloseReason Sample.cs index d10fa3c..9d1e2ca 100644 --- a/Robots/PositionCloseReason Sample/PositionCloseReason Sample/PositionCloseReason Sample.cs +++ b/Robots/PositionCloseReason Sample/PositionCloseReason Sample/PositionCloseReason Sample.cs @@ -5,42 +5,49 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to handle position closing events. It listens for position closures +// and evaluates the reason for the closure, allowing specific actions to be executed based on +// the type of close event. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionCloseReasonSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { - Positions.Closed += Positions_Closed; + Positions.Closed += Positions_Closed; // Subscribe to the event triggered when a position is closed. } + // This method is triggered whenever a position is closed. private void Positions_Closed(PositionClosedEventArgs obj) { - Print(obj.Reason); + Print(obj.Reason); // Outputs the reason for the position closure to the log. - switch (obj.Reason) + switch (obj.Reason) // Evaluates the type of closure reason. { case PositionCloseReason.Closed: - // Do something if position closed + // Do something if position closed. break; case PositionCloseReason.StopLoss: - // Do something if position stop loss got hit + // Do something if position stop loss got hit. break; case PositionCloseReason.StopOut: - // Do something if position stopped out + // Do something if position stopped out. break; case PositionCloseReason.TakeProfit: - // Do something if position take profit got hit + // Do something if position take profit got hit. break; } } } -} \ No newline at end of file +} diff --git a/Robots/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs b/Robots/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs index cadcbed..044d56e 100644 --- a/Robots/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs +++ b/Robots/PositionCurrentPrice Sample/PositionCurrentPrice Sample/PositionCurrentPrice Sample.cs @@ -21,31 +21,32 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and an ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class PositionCurrentPriceSample : Robot { - - + // This method is called when the cBot starts. protected override void OnStart() { // Executing a market order so that - // there is at least one initial position + // there is at least one initial position. ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "cbot position"); } + // This method is triggered whenever a bar is closed. protected override void OnBarClosed() { - // Finding all positions opened by the cBot + // Finding all positions opened by the cBot. var cbotPositions = Positions.FindAll("cbot position"); - // Iterating over all positions opened by the cBot + // Iterating over all positions opened by the cBot. foreach (var position in cbotPositions) { if (position.CurrentPrice > position.EntryPrice) { // Placing a limit order in the opposite direction // and above the current price if the current price - // is greater than the entry price + // is greater than the entry price. PlaceLimitOrder(TradeType.Sell, SymbolName, 20000, position.CurrentPrice * 1.05, "cbot position"); } else @@ -54,7 +55,7 @@ protected override void OnBarClosed() // Placing a limit order in the opposite direction // and below the current price if the current price - // is smaller than the entry price + // is smaller than the entry price. PlaceLimitOrder(TradeType.Buy, SymbolName, 20000, position.CurrentPrice * 0.95, "cbot position"); } } @@ -62,4 +63,4 @@ protected override void OnBarClosed() } -} \ No newline at end of file +} diff --git a/Robots/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample.cs b/Robots/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample.cs index 8497f06..5743a27 100644 --- a/Robots/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample.cs +++ b/Robots/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample/PositionModifiedEventArgs Sample.cs @@ -5,23 +5,31 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to handle position modification events. +// It listens for changes in position details and logs the modified position ID. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class PositionModifiedEventArgsSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { + // Register a handler for the Positions.Modified event to respond when a position is modified. Positions.Modified += Positions_Modified; } + // This method is triggered whenever a position is modified. private void Positions_Modified(PositionModifiedEventArgs obj) { + // Log the ID of the modified position for monitoring purposes. Print("Position {0} modified", obj.Position.Id); } } -} \ No newline at end of file +} diff --git a/Robots/Price Oscillator Sample/Price Oscillator Sample/Price Oscillator Sample.cs b/Robots/Price Oscillator Sample/Price Oscillator Sample/Price Oscillator Sample.cs index 22edb92..796224d 100644 --- a/Robots/Price Oscillator Sample/Price Oscillator Sample/Price Oscillator Sample.cs +++ b/Robots/Price Oscillator Sample/Price Oscillator Sample/Price Oscillator Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Price Oscillator to trade based on bullish and bearish crossovers. +// It opens a buy position when the oscillator crosses above zero and a sell position when it +// crosses below zero. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,77 +16,89 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class PriceOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private PriceOscillator _priceOscillator; + private PriceOscillator _priceOscillator; // Store the Price Oscillator indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "PriceOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Price Oscillator")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data series for the Price Oscillator calculation. [Parameter("Long Cycle", DefaultValue = 22, Group = "Price Oscillator", MinValue = 1)] - public int LongCycle { get; set; } + public int LongCycle { get; set; } // Number of periods for the long cycle, defaulting to 22. [Parameter("Short Cycle", DefaultValue = 14, Group = "Price Oscillator", MinValue = 1)] - public int ShortCycle { get; set; } + public int ShortCycle { get; set; } // Number of periods for the short cycle, defaulting to 14. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Price Oscillator")] - public MovingAverageType MAType { get; set; } - + public MovingAverageType MAType { get; set; } // Moving average type, default is Simple. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Price Oscillator indicator with the specified period. _priceOscillator = Indicators.PriceOscillator(Source, LongCycle, ShortCycle, MAType); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the Price Oscillator crosses above zero, execute a buy trade. if (_priceOscillator.Result.Last(0) > 0 && _priceOscillator.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the Price Oscillator crosses below zero, execute a sell trade. else if (_priceOscillator.Result.Last(0) < 0 && _priceOscillator.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Price ROC Sample/Price ROC Sample/Price ROC Sample.cs b/Robots/Price ROC Sample/Price ROC Sample/Price ROC Sample.cs index c4043f8..fa20f2e 100644 --- a/Robots/Price ROC Sample/Price ROC Sample/Price ROC Sample.cs +++ b/Robots/Price ROC Sample/Price ROC Sample/Price ROC Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Price Rate of Change (Price ROC) indicator to identify potential trend +// reversals. It opens a buy position when the Price ROC value crosses above zero and a sell +// position when it crosses below zero. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,71 +16,81 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class PriceROCSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private PriceROC _priceROC; + private PriceROC _priceROC; // Store the Price ROC indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "PriceROCSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Price ROC")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data series used as input for the Price ROC. [Parameter(DefaultValue = 12, Group = "Price ROC", MinValue = 1)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods for calculating the Price ROC, default is 12. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Price ROC indicator with the specified period. _priceROC = Indicators.PriceROC(Source, Periods); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the Price ROC value crosses above zero, execute a buy trade. if (_priceROC.Result.Last(0) > 0 && _priceROC.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } else if (_priceROC.Result.Last(0) < 0 && _priceROC.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Price Volume Trend Sample/Price Volume Trend Sample/Price Volume Trend Sample.cs b/Robots/Price Volume Trend Sample/Price Volume Trend Sample/Price Volume Trend Sample.cs index d7065a0..77946f6 100644 --- a/Robots/Price Volume Trend Sample/Price Volume Trend Sample/Price Volume Trend Sample.cs +++ b/Robots/Price Volume Trend Sample/Price Volume Trend Sample/Price Volume Trend Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Price Volume Trend (PVT) indicator along with a Simple Moving Average (SMA) +// to detect potential trend reversals. It opens a buy position when the Price Volume Trend crosses +// above the SMA and a sell position when the Price Volume Trend crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,73 +16,86 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class PriceVolumeTrendSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private PriceVolumeTrend _priceVolumeTrend; + private PriceVolumeTrend _priceVolumeTrend; // Store the Price Volume Trend indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "PriceVolumeTrendSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Price Volume Trend")] - public DataSeries SourcePriceVolumeTrend { get; set; } + public DataSeries SourcePriceVolumeTrend { get; set; } // Data series used as input for the PVT. [Parameter("Periods", DefaultValue = 20, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } + public int PeriodsSimpleMovingAverage { get; set; } // Number of periods for calculating the SMA, default is 20. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialize the Price Volume Trend and Simple Moving Average indicators. _priceVolumeTrend = Indicators.PriceVolumeTrend(SourcePriceVolumeTrend); _simpleMovingAverage = Indicators.SimpleMovingAverage(_priceVolumeTrend.Result, PeriodsSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the Price Volume Trend crosses above the SMA, execute a buy trade. if (_priceVolumeTrend.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the Price Volume Trend crosses below the SMA, execute a sell trade. else if (_priceVolumeTrend.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample.cs b/Robots/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample.cs index cfbd0d5..5d3d456 100644 --- a/Robots/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample.cs +++ b/Robots/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample/RSI Reversal Strategy Sample.cs @@ -19,28 +19,37 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class RSIReversalStrategySample : Robot { + // Define input parameters for the cBot. [Parameter(DefaultValue = 30)] - public int BuyLevel { get; set; } + public int BuyLevel { get; set; } // Buy level, below which the cBot opens a buy position, defaulting to 30. [Parameter(DefaultValue = 70)] - public int SellLevel { get; set; } + public int SellLevel { get; set; } // Sell level, above which the cBot opens a sell position, defaulting to 70. - private RelativeStrengthIndex _rsi; + private RelativeStrengthIndex _rsi; // Store the Relative Strength Index indicator. + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Initialize the RSI indicator with a period of 14 using the closing prices of the bars. _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the RSI value is below the Buy level, open a buy trade. if (_rsi.Result.LastValue < BuyLevel) { + // Ensure there are no open positions before opening a buy trade. if (Positions.Count == 0) - ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000); + ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000); // Open a buy market order with 1000 units. + + // Close any existing sell positions. foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell)) { position.Close(); @@ -48,10 +57,14 @@ protected override void OnBarClosed() } + // If the RSI value is above the Sell level, open a sell trade. else if (_rsi.Result.LastValue > SellLevel) { + // Ensure there are no open positions before opening a sell trade. if (Positions.Count == 0) - ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000); + ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000); // Open a sell market order with 1000 units. + + // Close any existing buy positions. foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy)) { position.Close(); @@ -64,4 +77,4 @@ protected override void OnStop() } } -} \ No newline at end of file +} diff --git a/Robots/Rainbow Oscillator Sample/Rainbow Oscillator Sample/Rainbow Oscillator Sample.cs b/Robots/Rainbow Oscillator Sample/Rainbow Oscillator Sample/Rainbow Oscillator Sample.cs index c4f2819..aa19fdd 100644 --- a/Robots/Rainbow Oscillator Sample/Rainbow Oscillator Sample/Rainbow Oscillator Sample.cs +++ b/Robots/Rainbow Oscillator Sample/Rainbow Oscillator Sample/Rainbow Oscillator Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot implements a trading strategy that uses the Rainbow Oscillator indicator in combination +// with a Simple Moving Average (SMA). The strategy executes trades based on the crossover of +// the Rainbow Oscillator with the Simple Moving Average. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,80 +16,92 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class RainbowOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private RainbowOscillator _rainbowOscillator; + private RainbowOscillator _rainbowOscillator; // Store the Rainbow Oscillator indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "RainbowOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Rainbow Oscillator")] - public DataSeries SourceRainbowOscillator { get; set; } + public DataSeries SourceRainbowOscillator { get; set; } // Data source for the Rainbow Oscillator. [Parameter(MinValue = 2, DefaultValue = 9, Group = "Rainbow Oscillator")] - public int LevelsRainbowOscillator { get; set; } + public int LevelsRainbowOscillator { get; set; } // Number of levels for the Rainbow Oscillator, defaulting to 9. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Rainbow Oscillator")] - public MovingAverageType MATypeRainbowOscillator { get; set; } + public MovingAverageType MATypeRainbowOscillator { get; set; } // Type of moving average type, defaulting to Simple. [Parameter("Periods", DefaultValue = 9, Group = "Simple Moving Average", MinValue = 0)] - public int PeriodsSimpleMovingAverage { get; set; } - + public int PeriodsSimpleMovingAverage { get; set; } // Number of periods for calculating the SMA, default is 9. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialize the Rainbow Oscillator and Simple Moving Average indicators. _rainbowOscillator = Indicators.RainbowOscillator(SourceRainbowOscillator, LevelsRainbowOscillator, MATypeRainbowOscillator); _simpleMovingAverage = Indicators.SimpleMovingAverage(_rainbowOscillator.Result, PeriodsSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the Rainbow Oscillator has crossed above the SMA. if (_rainbowOscillator.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } + + // Check if the Rainbow Oscillator has crossed below the SMA. else if (_rainbowOscillator.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Range Strategy Example/Range Strategy Example/Range Strategy Example.cs b/Robots/Range Strategy Example/Range Strategy Example/Range Strategy Example.cs index b84e2ef..9cd609f 100644 --- a/Robots/Range Strategy Example/Range Strategy Example/Range Strategy Example.cs +++ b/Robots/Range Strategy Example/Range Strategy Example/Range Strategy Example.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot implements a simple range-based trading strategy that opens a buy trade when the price +// closes higher than it opened and the previous bar closed lower. It opens a sell trade when the +// current bar closes lower than it opened and the previous bar closed higher. +// // ------------------------------------------------------------------------------------------------- using System; @@ -18,42 +22,45 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights. [Robot(AccessRights = AccessRights.None)] public class RangeStrategyExample : Robot { [Parameter(DefaultValue = 100000)] - public double Volume { get; set; } + public double Volume { get; set; } // Trade volume in units, default is 100000 units. [Parameter(DefaultValue = 20)] - public double StopLoss { get; set; } + public double StopLoss { get; set; } // Stop loss in pips, default is 20 pips. [Parameter(DefaultValue = 20)] - public double TakeProfit { get; set; } + public double TakeProfit { get; set; } // Take profit in pips, default is 20 pips. protected override void OnStart() { } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the current bar closes higher than it opened and the previous bar closed lower, execute a buy order. if (Bars.Last(0).Close > Bars.Last(0).Open && Bars.Last(1).Close < Bars.Last(1).Open && Bars.Last(0).Close > Bars.Last(1).Open) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); + ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); // Open a market order to buy with the specified volume, stop loss and take profit. } - + // If the current bar closes lower than it opened and the previous bar closed higher, execute a sell order. if (Bars.Last(0).Close < Bars.Last(0).Open && Bars.Last(1).Close > Bars.Last(1).Open && Bars.Last(0).Close < Bars.Last(1).Open) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); + ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit); // Open a market order to sell with the specified volume, stop loss and take profit. } } protected override void OnStop() { - // Handle cBot stop here + // Handle cBot stop here. } } -} \ No newline at end of file +} diff --git a/Robots/RefreshData Sample/RefreshData Sample/RefreshData Sample.cs b/Robots/RefreshData Sample/RefreshData Sample/RefreshData Sample.cs index abf326c..f7325b8 100644 --- a/Robots/RefreshData Sample/RefreshData Sample/RefreshData Sample.cs +++ b/Robots/RefreshData Sample/RefreshData Sample/RefreshData Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to execute multiple market orders asynchronously, +// then waits for all orders to complete before closing the positions. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,38 +16,46 @@ namespace RefreshDataSample { + // Define the cBot attributes, such as AccessRights. [Robot(AccessRights = AccessRights.None)] public class RefreshDataSample : Robot { + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Initialise an array to store 50 trade operations. var execututionResults = new TradeOperation[50]; + // Loop to send 50 market orders, alternating between buy and sell orders. for (var i = 0; i < 50; i++) { + // Send an asynchronous market order, alternating between buy and sell based on the index. + // A buy order is sent for even indices, a sell order is sent for odd ones, with the minimum volume in units. execututionResults[i] = ExecuteMarketOrderAsync(i % 2 == 0 ? TradeType.Buy : TradeType.Sell, SymbolName, Symbol.VolumeInUnitsMin); } - Print("All orders sent"); + Print("All orders sent"); // Print message once all orders are sent. + // Wait for all orders to finish execution. while (execututionResults.Any(operation => operation.IsExecuting)) { - Print("Waiting..."); - Thread.Sleep(100); - // If you remove the RefreshData method call - // cBot main thread will stuck and the rest - // of the code will not be executed + Print("Waiting..."); // Print message while waiting for orders to complete. + Thread.Sleep(100); // Pause the execution for 100 milliseconds. + + // Refresh the data to ensure the cBot can continue executing after the sleep period. + // If you remove the RefreshData method call cBot main thread will stuck and the rest of the code will not be executed. RefreshData(); } - Print("Closing Positions"); + Print("Closing Positions"); // Print message once all orders are completed. + // Iterate over all open positions to close them, but skip the sell positions. foreach (var position in Positions) { - if (position.TradeType == TradeType.Sell) continue; + if (position.TradeType == TradeType.Sell) continue; // Skip closing sell positions. - _ = ClosePositionAsync(position); + _ = ClosePositionAsync(position); // Asynchronously close each position that is not a sell order. } } } -} \ No newline at end of file +} diff --git a/Robots/Relative Strength Index Sample/Relative Strength Index Sample/Relative Strength Index Sample.cs b/Robots/Relative Strength Index Sample/Relative Strength Index Sample/Relative Strength Index Sample.cs index c31cc6b..475e3b6 100644 --- a/Robots/Relative Strength Index Sample/Relative Strength Index Sample/Relative Strength Index Sample.cs +++ b/Robots/Relative Strength Index Sample/Relative Strength Index Sample/Relative Strength Index Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot implements a trading strategy that uses the Relative Strength Index (RSI) indicator. +// It opens trades when the RSI crosses predefined upper or lower levels and closes positions in +// the opposite direction when thresholds are breached. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,77 +16,91 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class RelativeStrengthIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private RelativeStrengthIndex _relativeStrengthIndex; + private RelativeStrengthIndex _relativeStrengthIndex; // Store the Relative Strength Index indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "RelativeStrengthIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Relative Strength Index")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data source for the Relative Strength Index. [Parameter(DefaultValue = 14, Group = "Relative Strength Index", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // The RSI period, defaulting to 14 periods. [Parameter("Down level", DefaultValue = 30, Group = "Relative Strength Index", MinValue = 1, MaxValue = 50)] - public int DownValue { get; set; } + public int DownValue { get; set; } // The lower RSI threshold, defaulting to 30. [Parameter("Up level", DefaultValue = 70, Group = "Relative Strength Index", MinValue = 50, MaxValue = 100)] - public int UpValue { get; set; } - + public int UpValue { get; set; } // The upper RSI threshold, defaulting to 70. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the RSI indicator using the defined source and period. _relativeStrengthIndex = Indicators.RelativeStrengthIndex(Source, Periods); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Checks if the RSI value has crossed above the upper threshold. + // The condition ensures the crossover occurred between the previous and current bar. if (_relativeStrengthIndex.Result.Last(0) > UpValue && _relativeStrengthIndex.Result.Last(1) <= UpValue) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Checks if the RSI value has crossed below the lower threshold. + // The condition ensures the crossover occurred between the previous and current bar. else if (_relativeStrengthIndex.Result.Last(0) < DownValue && _relativeStrengthIndex.Result.Last(1) >= DownValue) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Simple Moving Average Sample/Simple Moving Average Sample/Simple Moving Average Sample.cs b/Robots/Simple Moving Average Sample/Simple Moving Average Sample/Simple Moving Average Sample.cs index d5336fe..d809774 100644 --- a/Robots/Simple Moving Average Sample/Simple Moving Average Sample/Simple Moving Average Sample.cs +++ b/Robots/Simple Moving Average Sample/Simple Moving Average Sample/Simple Moving Average Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This code implements a trading strategy using two Simple Moving Averages (SMA). +// The cBot opens buy or sell trades when the fast SMA crosses the slow SMA. +// It allows parameters for MA periods, trade volume and risk management. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,82 +16,96 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class SimpleMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private SimpleMovingAverage _fastSimpleMovingAverage; + private SimpleMovingAverage _fastSimpleMovingAverage; // Store the fast Simple Moving Average indicator. - private SimpleMovingAverage _slowSimpleMovingAverage; + private SimpleMovingAverage _slowSimpleMovingAverage; // Store the slow Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast SMA. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast SMA, defaulting to 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow SMA. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow SMA, defaulting to 20. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "SimpleMovingAverageSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow SMAs with the provided data source and period. _fastSimpleMovingAverage = Indicators.SimpleMovingAverage(FastMaSource, FastMaPeriod); _slowSimpleMovingAverage = Indicators.SimpleMovingAverage(SlowMaSource, SlowMaPeriod); + // Set the colours of the fast and slow SMA lines for visual distinction. _fastSimpleMovingAverage.Result.Line.Color = Color.Blue; _slowSimpleMovingAverage.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the fast SMA has crossed above the slow SMA. if (_fastSimpleMovingAverage.Result.HasCrossedAbove(_slowSimpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the fast SMA has crossed below the slow SMA. else if (_fastSimpleMovingAverage.Result.HasCrossedBelow(_slowSimpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Standard Deviation Sample/Standard Deviation Sample/Standard Deviation Sample.cs b/Robots/Standard Deviation Sample/Standard Deviation Sample/Standard Deviation Sample.cs index 65094e0..adf91d3 100644 --- a/Robots/Standard Deviation Sample/Standard Deviation Sample/Standard Deviation Sample.cs +++ b/Robots/Standard Deviation Sample/Standard Deviation Sample/Standard Deviation Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates a trading strategy using Standard Deviation and Simple Moving Average (SMA). +// It opens trades based on the crossing of closing prices above or below the SMA, with +// risk management derived from the Standard Deviation. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,87 +17,106 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class StandardDeviationSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private StandardDeviation _standardDeviation; + private StandardDeviation _standardDeviation; // Store the Standard Deviation indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default value is 0.01. [Parameter("Label", DefaultValue = "StandardDeviationSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Standard Deviation")] - public DataSeries SourceStandardDeviation { get; set; } + public DataSeries SourceStandardDeviation { get; set; } // Data source for the Standard Deviation. [Parameter("Periods Standard Deviation", DefaultValue = 20, Group = "Standard Deviation", MinValue = 2)] - public int PeriodsStandardDeviation { get; set; } + public int PeriodsStandardDeviation { get; set; } // Number of periods for the Standard Deviation, default is 20. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Standard Deviation")] - public MovingAverageType MATypeStandardDeviation { get; set; } + public MovingAverageType MATypeStandardDeviation { get; set; } // Type of moving average, default is Simple. [Parameter("Source", Group = "Moving Average")] - public DataSeries SourceMovingAverage { get; set; } + public DataSeries SourceMovingAverage { get; set; } // Data source for the SMA. [Parameter("Periods Moving Average", DefaultValue = 14, Group = "Moving Average", MinValue = 2)] - public int PeriodsMovingAverage { get; set; } - + public int PeriodsMovingAverage { get; set; } // Number of periods for the SMA, default is 14. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Standard Deviation and SMA indicators with the specified parameters. _standardDeviation = Indicators.StandardDeviation(SourceStandardDeviation, PeriodsStandardDeviation, MATypeStandardDeviation); _simpleMovingAverage = Indicators.SimpleMovingAverage(SourceMovingAverage, PeriodsMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the closing price has crossed above the SMA on the most recent bar. if (Bars.ClosePrices.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteOrder(TradeType.Buy); + ExecuteOrder(TradeType.Buy); // Open a buy order. } + + // Check if the closing price has crossed below the SMA on the most recent bar. else if (Bars.ClosePrices.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteOrder(TradeType.Sell); + ExecuteOrder(TradeType.Sell); // Open a sell order. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } + // Execute a market order of the specified trade type with dynamically calculated stop loss + // and take profit levels based on the standard deviation of price movements. private void ExecuteOrder(TradeType tradeType) { + // Convert the Standard Deviation value to pips for risk management. var standardDeviationInPips = _standardDeviation.Result.Last(1) * (Symbol.TickSize / Symbol.PipSize * Math.Pow(10, Symbol.Digits)); + // Set the stop loss to twice the Standard Deviation. var stopLossInPips = standardDeviationInPips * 2; + + // Set the take profit to twice the stop loss value. var takeProfitInPips = stopLossInPips * 2; + // Open a market order with the calculated stop loss and take profit values. ExecuteMarketOrder(tradeType, SymbolName, _volumeInUnits, Label, stopLossInPips, takeProfitInPips); } } -} \ No newline at end of file +} diff --git a/Robots/Start cBot Sample/Start cBot Sample/Start cBot Sample.cs b/Robots/Start cBot Sample/Start cBot Sample/Start cBot Sample.cs index 1cbd613..d7f688d 100644 --- a/Robots/Start cBot Sample/Start cBot Sample/Start cBot Sample.cs +++ b/Robots/Start cBot Sample/Start cBot Sample/Start cBot Sample.cs @@ -19,45 +19,53 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class AddcBots : Robot { - + // Hold references to the two cBots being managed by this robot. ChartRobot _robot1; ChartRobot _robot2; + // This method is called when the cBot starts. protected override void OnStart() { + // Add two instances of "Sample Trend cBot" with unique parameters to the chart. _robot1 = Chart.Robots.Add("Sample Trend cBot", 0.01, MovingAverageType.Simple, Bars.ClosePrices, 10, 5); _robot2 = Chart.Robots.Add("Sample Trend cBot", 0.01, MovingAverageType.Simple, Bars.ClosePrices, 12, 7); + // Subscribe to the event triggered when a robot starts. Chart.Robots.RobotStarted += ChartRobots_RobotStarted; } + // Event handler related to the started robot. private void ChartRobots_RobotStarted(ChartRobotStartedEventArgs obj) { - Print ("Robot Started"); - + Print ("Robot Started"); // Logs a message indicating that a robot has started. } + // This method is triggered whenever a bar is closed. protected override void OnBarClosed() { + // Check if the first robot is stopped and starts it while stopping the second robot. if (_robot1.State == RobotState.Stopped) { - _robot1.Start(); - _robot2.Stop(); + _robot1.Start(); // Starts the first robot. + _robot2.Stop(); // Stops the second robot. } + // Check if the first robot is running and stops it while starting the second robot. else if (_robot1.State == RobotState.Running) { - _robot2.Start(); - _robot1.Stop(); + _robot2.Start(); // Starts the second robot. + _robot1.Stop(); // Stops the first robot. } } + // This method is called when the cBot is stopped. protected override void OnStop() { - // Handle cBot stop here + // Handle cBot stop here. } } -} \ No newline at end of file +} diff --git a/Robots/Stochastic Oscillator Sample/Stochastic Oscillator Sample/Stochastic Oscillator Sample.cs b/Robots/Stochastic Oscillator Sample/Stochastic Oscillator Sample/Stochastic Oscillator Sample.cs index 212a2a5..7385048 100644 --- a/Robots/Stochastic Oscillator Sample/Stochastic Oscillator Sample/Stochastic Oscillator Sample.cs +++ b/Robots/Stochastic Oscillator Sample/Stochastic Oscillator Sample/Stochastic Oscillator Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Stochastic Oscillator to trade based on momentum signals. A buy position is +// opened when %K crosses above %D in oversold territory, and a sell position is opened when %K +// crosses below %D in overbought territory. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,83 +16,95 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class StochasticOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private StochasticOscillator _stochasticOscillator; + private StochasticOscillator _stochasticOscillator; // Store the Stochastic Oscillator indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "StochasticOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("%K Periods", DefaultValue = 9, Group = "Stochastic Oscillator", MinValue = 1)] - public int KPeriods { get; set; } + public int KPeriods { get; set; } // Number of periods for %K, defaulting to 9. [Parameter("%K Slowing", DefaultValue = 3, Group = "Stochastic Oscillator", MinValue = 1)] - public int KSlowing { get; set; } + public int KSlowing { get; set; } // Smoothing factor for %K, defaulting to 3. [Parameter("%D Periods", DefaultValue = 9, Group = "Stochastic Oscillator", MinValue = 0)] - public int DPeriods { get; set; } + public int DPeriods { get; set; } // Number of periods for %D, defaulting to 9. [Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Stochastic Oscillator")] - public MovingAverageType MAType { get; set; } + public MovingAverageType MAType { get; set; } // Moving Average type used for smoothing %D. [Parameter("Down level", DefaultValue = 20, Group = "Stochastic Oscillator", MinValue = 1, MaxValue = 50)] - public int DownValue { get; set; } + public int DownValue { get; set; } // Oversold level, defaulting to 20. [Parameter("Up level", DefaultValue = 80, Group = "Stochastic Oscillator", MinValue = 50, MaxValue = 100)] - public int UpValue { get; set; } - + public int UpValue { get; set; } // Overbought level, defaulting to 80. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Finds positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Stochastic Oscillator with the specified parameters. _stochasticOscillator = Indicators.StochasticOscillator(KPeriods, KSlowing, DPeriods, MAType); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Open a buy position if %K crosses above %D in oversold territory. if (_stochasticOscillator.PercentK.HasCrossedAbove(_stochasticOscillator.PercentD, 0) && _stochasticOscillator.PercentK.Last(1) <= DownValue) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Open a sell position if %K crosses below %D in overbought territory. else if (_stochasticOscillator.PercentK.HasCrossedBelow(_stochasticOscillator.PercentD, 0) && _stochasticOscillator.PercentK.Last(1) >= UpValue) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/StopTriggerMethod Sample/StopTriggerMethod Sample/StopTriggerMethod Sample.cs b/Robots/StopTriggerMethod Sample/StopTriggerMethod Sample/StopTriggerMethod Sample.cs index cb7e25a..82afa40 100644 --- a/Robots/StopTriggerMethod Sample/StopTriggerMethod Sample/StopTriggerMethod Sample.cs +++ b/Robots/StopTriggerMethod Sample/StopTriggerMethod Sample/StopTriggerMethod Sample.cs @@ -5,43 +5,52 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to use the StopTriggerMethod in various trading operations. It sets +// StopTriggerMethod for market orders, stop orders, and modifies existing positions and pending +// orders based on the specified StopTriggerMethod parameter. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class StopTriggerMethodSample : Robot { + // Define input parameter for selecting the StopTriggerMethod. [Parameter("Stop Trigger Method", DefaultValue = StopTriggerMethod.Trade)] - public StopTriggerMethod StopTriggerMethod { get; set; } + public StopTriggerMethod StopTriggerMethod { get; set; } // Set the StopTriggerMethod for orders and modifications. + // This method is called when the cBot starts and handles the StopTriggerMethod setup. protected override void OnStart() { - // Setting a new position StopTriggerMethod + // Open a new market order with the specified StopTriggerMethod. ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin, "StopTriggerMethod Test", 10, 10, string.Empty, false, StopTriggerMethod); - // Setting a new stop order StopTriggerMethod for both order and its stop loss - var target = Symbol.Bid + (100 * Symbol.PipSize); + var target = Symbol.Bid + (100 * Symbol.PipSize); // Calculate the target price. + // Place a stop order with the StopTriggerMethod applied to the order. PlaceStopOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin, target, "StopTriggerMethod Test", 10, 10, null, string.Empty, false, StopTriggerMethod, StopTriggerMethod); - // Changing open positions StopTriggerMethod + // Modify open positions to apply the specified StopTriggerMethod. foreach (var position in Positions) { + // Skip positions without a stop loss set. if (!position.StopLoss.HasValue) continue; - ModifyPosition(position, position.StopLoss, position.TakeProfit, position.HasTrailingStop, StopTriggerMethod); + ModifyPosition(position, position.StopLoss, position.TakeProfit, position.HasTrailingStop, StopTriggerMethod); // Update the position StopTriggerMethod. } - // Changing open pending orders (Stop and StopLimit) StopTriggerMethod + // Modify open pending orders (Stop and StopLimit) to apply the specified StopTriggerMethod. foreach (var order in PendingOrders) { + // Skip orders without a stop loss or orders that are not Stop or StopLimit. if (!order.StopLossPips.HasValue || order.OrderType == PendingOrderType.Limit) continue; - ModifyPendingOrder(order, order.TargetPrice, order.StopLossPips, order.TakeProfitPips, order.ExpirationTime, order.VolumeInUnits, order.HasTrailingStop, StopTriggerMethod, StopTriggerMethod); + ModifyPendingOrder(order, order.TargetPrice, order.StopLossPips, order.TakeProfitPips, order.ExpirationTime, order.VolumeInUnits, order.HasTrailingStop, StopTriggerMethod, StopTriggerMethod); // Apply StopTriggerMethod for the order. } } } -} \ No newline at end of file +} diff --git a/Robots/Supertrend Sample/Supertrend Sample/Supertrend Sample.cs b/Robots/Supertrend Sample/Supertrend Sample/Supertrend Sample.cs index 21befef..e4f55d5 100644 --- a/Robots/Supertrend Sample/Supertrend Sample/Supertrend Sample.cs +++ b/Robots/Supertrend Sample/Supertrend Sample/Supertrend Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Supertrend indicator to identify trading opportunities based on trend direction. +// It opens a buy position when the price transitions above the Supertrend downtrend line and +// opens a sell position when the price transitions below the Supertrend uptrend line. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,71 +16,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class SupertrendSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private Supertrend _supertrend; + private Supertrend _supertrend; // Store the Supertrend indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "SupertrendSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Periods", DefaultValue = 10, Group = "Supertrend", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods, with a default of 10 periods. [Parameter("Multiplier", DefaultValue = 3.0, Group = "Supertrend")] - public double Multiplier { get; set; } - + public double Multiplier { get; set; } // Multiplier for ATR in Supertrend calculation, defaulting to 3. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Supertrend indicator with the specified periods and multiplier. _supertrend = Indicators.Supertrend(Periods, Multiplier); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the price transitions above the Supertrend downtrend line, execute a buy trade. if (_supertrend.UpTrend.Last(0) < Bars.LowPrices.Last(0) && _supertrend.DownTrend.Last(1) > Bars.HighPrices.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the price transitions below the Supertrend uptrend line, execute a sell trade. else if (_supertrend.DownTrend.Last(0) > Bars.HighPrices.Last(0) && _supertrend.UpTrend.Last(1) < Bars.LowPrices.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Swing Index Sample/Swing Index Sample/Swing Index Sample.cs b/Robots/Swing Index Sample/Swing Index Sample/Swing Index Sample.cs index e45bc2c..7d08453 100644 --- a/Robots/Swing Index Sample/Swing Index Sample/Swing Index Sample.cs +++ b/Robots/Swing Index Sample/Swing Index Sample/Swing Index Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Swing Index indicator to identify shifts in market momentum. +// It opens a buy position when the Swing Index value crosses above zero and +// opens a sell position when it crosses below zero. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,68 +16,80 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class SwingIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private SwingIndex _swingIndex; + private SwingIndex _swingIndex; // Store the Swing Index indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "SwingIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Limit Move Value", DefaultValue = 12, Group = "Swing Index", MinValue = 1)] - public int LimitMoveValue { get; set; } - + public int LimitMoveValue { get; set; } // Limit Move value, defaulting to 12. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Swing Index indicator with the specified limit move value. _swingIndex = Indicators.SwingIndex(LimitMoveValue); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the Swing Index crosses above zero, indicating a potential uptrend. if (_swingIndex.Result.Last(0) > 0 && _swingIndex.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the Swing Index crosses below zero, indicating a potential downtrend. else if (_swingIndex.Result.Last(0) < 0 && _swingIndex.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Time Series Moving Average Sample/Time Series Moving Average Sample/Time Series Moving Average Sample.cs b/Robots/Time Series Moving Average Sample/Time Series Moving Average Sample/Time Series Moving Average Sample.cs index 5c6845b..f707037 100644 --- a/Robots/Time Series Moving Average Sample/Time Series Moving Average Sample/Time Series Moving Average Sample.cs +++ b/Robots/Time Series Moving Average Sample/Time Series Moving Average Sample/Time Series Moving Average Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilises two Time Series Moving Average indicators: a fast and a slow one, to identify +// potential trade opportunities based on crossovers. A buy trade is executed when the fast MA +// crosses above the slow MA, and a sell trade is executed when the fast MA crosses below the slow MA. +// // ------------------------------------------------------------------------------------------------- @@ -13,82 +17,96 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TimeSeriesMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private TimeSeriesMovingAverage _fastTimeSeriesMovingAverage; + private TimeSeriesMovingAverage _fastTimeSeriesMovingAverage; // Store the fast Time Series Moving Average. - private TimeSeriesMovingAverage _slowTimeSeriesMovingAverage; + private TimeSeriesMovingAverage _slowTimeSeriesMovingAverage; // Store the slow Time Series Moving Average. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast Time Series Moving Average. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast Time Series Moving Average, default value is 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow Time Series Moving Average. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow Time Series Moving Average, default value is 20. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "TimeSeriesMovingAverageSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow Time Series Moving Average indicators with the specified periods. _fastTimeSeriesMovingAverage = Indicators.TimeSeriesMovingAverage(FastMaSource, FastMaPeriod); _slowTimeSeriesMovingAverage = Indicators.TimeSeriesMovingAverage(SlowMaSource, SlowMaPeriod); + // Set colors for the moving averages, blue for the fast MA and red for the slow MA. _fastTimeSeriesMovingAverage.Result.Line.Color = Color.Blue; _slowTimeSeriesMovingAverage.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the fast Time Series Moving Average crosses above the slow one, execute a buy trade. if (_fastTimeSeriesMovingAverage.Result.HasCrossedAbove(_slowTimeSeriesMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the fast Time Series Moving Average crosses below the slow one, execute a sell trade. else if (_fastTimeSeriesMovingAverage.Result.HasCrossedBelow(_slowTimeSeriesMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Timer Sample/Timer Sample/Timer Sample.cs b/Robots/Timer Sample/Timer Sample/Timer Sample.cs index c2a5f17..5af03e0 100644 --- a/Robots/Timer Sample/Timer Sample/Timer Sample.cs +++ b/Robots/Timer Sample/Timer Sample/Timer Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates the use of a timer to execute actions at regular intervals. The timer is started +// with a 1-second interval and can be stopped. It allows for executing code in a scheduled manner based on +// elapsed time. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,27 +16,29 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class TimerSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { - // You can start the cBot timer by calling Timer.Start method, for interval you can pass a time span or seconds + // You can start the cBot timer by calling Timer.Start method, for interval you can pass a time span or seconds. Timer.Start(TimeSpan.FromSeconds(1)); - // You can also use the TimerTick event instead of OnTimer method + // You can also use the TimerTick event instead of OnTimer method. Timer.TimerTick += Timer_TimerTick; - // To stop the timer you can call Timer.Stop method anywhere on your cBot/indicator + // To stop the timer you can call Timer.Stop method anywhere on your cBot/indicator. Timer.Stop(); } private void Timer_TimerTick() { - // Put your logic for timer elapsed event here + // Put your logic for timer elapsed event here. } protected override void OnTimer() { - // Put your logic for timer elapsed event here + // Put your logic for timer elapsed event here. } } -} \ No newline at end of file +} diff --git a/Robots/Trade Volume Index Sample/Trade Volume Index Sample/Trade Volume Index Sample.cs b/Robots/Trade Volume Index Sample/Trade Volume Index Sample/Trade Volume Index Sample.cs index 827eecb..b4638b1 100644 --- a/Robots/Trade Volume Index Sample/Trade Volume Index Sample/Trade Volume Index Sample.cs +++ b/Robots/Trade Volume Index Sample/Trade Volume Index Sample/Trade Volume Index Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates the usage of the Trade Volume Index (TVI) combined with a Simple Moving +// Average (SMA) to create trading signals. A buy trade is executed when the TVI crosses above the +// SMA, and a sell trade is executed when the TVI crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,74 +16,87 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TradeVolumeIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private TradeVolumeIndex _tradeVolumeIndex; + private TradeVolumeIndex _tradeVolumeIndex; // Store the Trade Volume Index indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. - [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + // Define input parameters for the cBot. + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "TradeVolumeIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "TradeVolumeIndex")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data series source for TVI. [Parameter("Period", DefaultValue = 14, Group = "Simple Moving Average", MinValue = 1)] - public int PeriodSimpleMovingAverage { get; set; } + public int PeriodSimpleMovingAverage { get; set; } // Period for the SMA, default value is 14. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Trade Volume Index indicator with the given data series. _tradeVolumeIndex = Indicators.TradeVolumeIndex(Source); + // Initialise the Simple Moving Average with the period and TVI results. _simpleMovingAverage = Indicators.SimpleMovingAverage(_tradeVolumeIndex.Result, PeriodSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the TVI crosses above the SMA, execute a buy trade. if (_tradeVolumeIndex.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the TVI crosses below the SMA, execute a sell trade. else if (_tradeVolumeIndex.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/TradeOperation Sample/TradeOperation Sample/TradeOperation Sample.cs b/Robots/TradeOperation Sample/TradeOperation Sample/TradeOperation Sample.cs index 72f6945..910a772 100644 --- a/Robots/TradeOperation Sample/TradeOperation Sample/TradeOperation Sample.cs +++ b/Robots/TradeOperation Sample/TradeOperation Sample/TradeOperation Sample.cs @@ -5,32 +5,43 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates the use of asynchronous trade execution using the ExecuteMarketOrderAsync +// method. It executes a buy order asynchronously and checks whether the order was successfully placed +// or not. The outcome is printed in the log based on the execution result. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class TradeOperationSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { + // Asynchronously execute a market order for a buy trade. var tradeOperation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin, OnTradeResult); + // Check if the trade operation is currently executing. if (tradeOperation.IsExecuting) { - Print("Executing"); + Print("Executing"); // Print message indicating the trade is still executing. } + + // Check if the trade operation is not executing, which means it is completed. else { - Print("Completed"); + Print("Completed"); // Print message indicating the trade operation has completed. } } + // This method is triggered upon trade operation result. private void OnTradeResult(TradeResult obj) { - Print("Was Trade Operation Successful: ", obj.IsSuccessful); + Print("Was Trade Operation Successful: ", obj.IsSuccessful); // Print whether the trade operation was successful or not. } } -} \ No newline at end of file +} diff --git a/Robots/TradeResult Sample/TradeResult Sample/TradeResult Sample.cs b/Robots/TradeResult Sample/TradeResult Sample/TradeResult Sample.cs index 3073368..25fe24e 100644 --- a/Robots/TradeResult Sample/TradeResult Sample/TradeResult Sample.cs +++ b/Robots/TradeResult Sample/TradeResult Sample/TradeResult Sample.cs @@ -5,31 +5,42 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to execute a market order and check if the order was successful or not. +// It opens a buy position using the minimum volume allowed by the symbol and prints the result based on +// whether the order was successful. If successful, it prints the position ID of the newly opened position. +// If unsuccessful, it prints a failure message. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class TradeResultSample : Robot { + // This method is called when the cBot starts. protected override void OnStart() { + // Execute a market order for a buy trade, with the minimum trade volume and returns the trade result. var tradeResult = ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin); + // Check whether the market order execution was successful. if (tradeResult.IsSuccessful) { - Print("Market order execution was successful"); + Print("Market order execution was successful"); // Print a success message indicating the market order was executed successfully. - var position = tradeResult.Position; + var position = tradeResult.Position; // Store the position object from the trade result. - Print("A new position opend with ID ", position.Id); + Print("A new position opend with ID ", position.Id); // Print the ID of the newly opened position. } + + // If the trade result indicates that the order was not successful. else { - Print("Market order execution was not successful"); + Print("Market order execution was not successful"); // Print a failure message indicating the market order execution was not successful. } } } -} \ No newline at end of file +} diff --git a/Robots/TradeType Sample/TradeType Sample/TradeType Sample.cs b/Robots/TradeType Sample/TradeType Sample/TradeType Sample.cs index 3199e5e..bf00aa3 100644 --- a/Robots/TradeType Sample/TradeType Sample/TradeType Sample.cs +++ b/Robots/TradeType Sample/TradeType Sample/TradeType Sample.cs @@ -5,21 +5,27 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to execute a market order with a specified trade type (buy or sell). +// The trade type is passed as a parameter and the cBot executes a market order with the minimum volume +// allowed by the symbol using that trade type. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone and AccessRights. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class TradeTypeSample : Robot { [Parameter("Trade Type", DefaultValue = TradeType.Buy)] - public TradeType TradeType { get; set; } + public TradeType TradeType { get; set; } // Define a parameter for the trade type, the default value is set to 'Buy'. + // This method is called when the cBot starts. protected override void OnStart() { - ExecuteMarketOrder(TradeType, SymbolName, Symbol.VolumeInUnitsMin); + ExecuteMarketOrder(TradeType, SymbolName, Symbol.VolumeInUnitsMin); // Executes a market order with the specified trade type, using the symbol minimum volume. } } -} \ No newline at end of file +} diff --git a/Robots/Triangular Moving Average Sample/Triangular Moving Average Sample/Triangular Moving Average Sample.cs b/Robots/Triangular Moving Average Sample/Triangular Moving Average Sample/Triangular Moving Average Sample.cs index 64417c0..fd8bbc4 100644 --- a/Robots/Triangular Moving Average Sample/Triangular Moving Average Sample/Triangular Moving Average Sample.cs +++ b/Robots/Triangular Moving Average Sample/Triangular Moving Average Sample/Triangular Moving Average Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates how to use two Triangular Moving Averages (TMA) to identify trade opportunities. +// A buy trade is executed when the fast TMA crosses above the slow TMA and a sell trade is executed when +// the fast TMA crosses below the slow TMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,82 +16,96 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TriangularMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private TriangularMovingAverage _fastTriangularMovingAverage; + private TriangularMovingAverage _fastTriangularMovingAverage; // Store the fast Triangular Moving Average. - private TriangularMovingAverage _slowTriangularMovingAverage; + private TriangularMovingAverage _slowTriangularMovingAverage; // Store the slow Triangular Moving Average. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast Triangular Moving Average. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast Triangular Moving Average, default value is 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow Triangular Moving Average. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the fast Triangular Moving Average, default value is 20. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "TriangularMovingAverageSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow Triangular Moving Average indicators with the specified periods. _fastTriangularMovingAverage = Indicators.TriangularMovingAverage(FastMaSource, FastMaPeriod); _slowTriangularMovingAverage = Indicators.TriangularMovingAverage(SlowMaSource, SlowMaPeriod); + // Set colors for the moving averages, blue for the fast MA and red for the slow MA. _fastTriangularMovingAverage.Result.Line.Color = Color.Blue; _slowTriangularMovingAverage.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the fast TMA crosses above the slow TMA to trigger a buy signal. if (_fastTriangularMovingAverage.Result.HasCrossedAbove(_slowTriangularMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the fast TMA crosses below the slow TMA to trigger a sell signal. else if (_fastTriangularMovingAverage.Result.HasCrossedBelow(_slowTriangularMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Trix Sample/Trix Sample/Trix Sample.cs b/Robots/Trix Sample/Trix Sample/Trix Sample.cs index 4fffae8..94e4b59 100644 --- a/Robots/Trix Sample/Trix Sample/Trix Sample.cs +++ b/Robots/Trix Sample/Trix Sample/Trix Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the TRIX indicator to identify buy and sell signals. It opens a buy trade when the TRIX +// indicator crosses above zero and a sell trade when the TRIX crosses below zero. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,71 +15,83 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TrixSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private Trix _trix; + private Trix _trix; // Store the TRIX indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "TrixSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Trix")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Source data for the TRIX indicator. [Parameter("Periods", DefaultValue = 8, Group = "Trix", MinValue = 1)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods, with a default of 8 periods. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the TRIX indicator with the given source and periods. _trix = Indicators.Trix(Source, Periods); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if TRIX has crossed above zero from below (bullish signal). if (_trix.Result.Last(0) > 0 && _trix.Result.Last(1) <= 0) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if TRIX has crossed below zero from above (bearish signal). else if (_trix.Result.Last(0) < 0 && _trix.Result.Last(1) >= 0) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/True Range Sample/True Range Sample/True Range Sample.cs b/Robots/True Range Sample/True Range Sample/True Range Sample.cs index aa27f61..3600bee 100644 --- a/Robots/True Range Sample/True Range Sample/True Range Sample.cs +++ b/Robots/True Range Sample/True Range Sample/True Range Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilises the True Range indicator to execute trades based on price reversals. +// It identifies bullish or bearish patterns using candlestick close and open values. +// It sets dynamic stop-loss and take-profit levels based on the True Range value. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -13,68 +17,84 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TrueRangeSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private TrueRange _trueRange; + private TrueRange _trueRange; // Store the True Range indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Label", DefaultValue = "TrueRangeSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the True Range indicator. _trueRange = Indicators.TrueRange(); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check for a bullish reversal pattern. if (Bars.ClosePrices.Last(0) > Bars.OpenPrices.Last(0) && Bars.ClosePrices.Last(1) < Bars.OpenPrices.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteOrder(TradeType.Buy); + ExecuteOrder(TradeType.Buy); // Execute a buy order. } + + // Check for a bearish reversal pattern. else if (Bars.ClosePrices.Last(0) < Bars.OpenPrices.Last(0) && Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteOrder(TradeType.Sell); + ExecuteOrder(TradeType.Sell); // Execute a sell order. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } + // This method is used to execute a market order with a specified trade type. private void ExecuteOrder(TradeType tradeType) { + // Calculate the True Range value in pips using symbol properties. var trueRangeInPips = _trueRange.Result.Last(1) * (Symbol.TickSize / Symbol.PipSize * Math.Pow(10, Symbol.Digits)); - var stopLossInPips = trueRangeInPips * 2; - var takeProfitInPips = stopLossInPips * 2; + var stopLossInPips = trueRangeInPips * 2; // Set the stop-loss level as twice the True Range value in pips. + var takeProfitInPips = stopLossInPips * 2; // Set the take-profit level as twice the stop-loss value. + // Open a market order with the specified trade type, volume, stop loss and take profit. ExecuteMarketOrder(tradeType, SymbolName, _volumeInUnits, Label, stopLossInPips, takeProfitInPips); } } -} \ No newline at end of file +} diff --git a/Robots/Typical Price Sample/Typical Price Sample/Typical Price Sample.cs b/Robots/Typical Price Sample/Typical Price Sample/Typical Price Sample.cs index 2005675..bdc8208 100644 --- a/Robots/Typical Price Sample/Typical Price Sample/Typical Price Sample.cs +++ b/Robots/Typical Price Sample/Typical Price Sample/Typical Price Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot demonstrates the use of the Typical Price indicator and Simple Moving Average (SMA) +// for trading decisions. It opens buy or sell orders when crossovers occur between the Typical +// Price and its SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,68 +16,82 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class TypicalPriceSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private TypicalPrice _typicalPrice; + private TypicalPrice _typicalPrice; // Store the Typical Price indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "TypicalPriceSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Typical Price indicator. _typicalPrice = Indicators.TypicalPrice(); + // Initialise the SMA using the Typical Price result with a 14-period setting. _simpleMovingAverage = Indicators.SimpleMovingAverage(_typicalPrice.Result, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the Typical Price crosses above the SMA. if (_typicalPrice.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any existing sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the Typical Price crosses below the SMA. else if (_typicalPrice.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any existing buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Ultimate Oscillator Sample/Ultimate Oscillator Sample/Ultimate Oscillator Sample.cs b/Robots/Ultimate Oscillator Sample/Ultimate Oscillator Sample/Ultimate Oscillator Sample.cs index efabd0d..67353e1 100644 --- a/Robots/Ultimate Oscillator Sample/Ultimate Oscillator Sample/Ultimate Oscillator Sample.cs +++ b/Robots/Ultimate Oscillator Sample/Ultimate Oscillator Sample/Ultimate Oscillator Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Ultimate Oscillator to trade based on overbought and oversold conditions. +// It opens a sell position when the oscillator crosses below the upper level and a buy position +// when it crosses above the lower level. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,79 +16,92 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class UltimateOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private UltimateOscillator _ultimateOscillator; + private UltimateOscillator _ultimateOscillator; // Store the Ultimate Oscillator indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "UltimateOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Cycle 1", DefaultValue = 7, Group = "Ultimate Oscillator", MinValue = 1)] - public int Cycle1 { get; set; } + public int Cycle1 { get; set; } // First cycle length of the oscillator, default is 7. [Parameter("Cycle 2", DefaultValue = 14, Group = "Ultimate Oscillator", MinValue = 1)] - public int Cycle2 { get; set; } + public int Cycle2 { get; set; } // Second cycle length of the oscillator, default is 14. [Parameter("Cycle 3", DefaultValue = 28, Group = "Ultimate Oscillator", MinValue = 1)] - public int Cycle3 { get; set; } + public int Cycle3 { get; set; } // Third cycle length of the oscillator, default is 28. [Parameter("Down level", DefaultValue = 30, Group = "Stochastic Oscillator", MinValue = 1, MaxValue = 50)] - public int DownValue { get; set; } + public int DownValue { get; set; } // Lower level of the oscillator, default is 30. [Parameter("Up level", DefaultValue = 70, Group = "Stochastic Oscillator", MinValue = 50, MaxValue = 100)] - public int UpValue { get; set; } + public int UpValue { get; set; } // Upper level of the oscillator, default is 70. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Ultimate Oscillator with the specified cycles. _ultimateOscillator = Indicators.UltimateOscillator(Cycle1, Cycle2, Cycle3); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the oscillator crosses below the upper level. if (_ultimateOscillator.Result.Last(0) > UpValue && _ultimateOscillator.Result.Last(1) < UpValue) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } + + // Check if the oscillator crosses above the lower level. else if (_ultimateOscillator.Result.Last(0) < DownValue && _ultimateOscillator.Result.Last(1) > DownValue) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample.cs b/Robots/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample.cs index b6fe6cd..9468f5d 100644 --- a/Robots/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample.cs +++ b/Robots/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample/Vertical Horizontal Filter Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Vertical Horizontal Filter (VHF) indicator combined with a simple moving average +// to identify trading conditions. It opens a buy position when the price crosses above the moving average +// and a sell position when it crosses below the moving average, provided the VHF is trending. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,79 +16,95 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class VerticalHorizontalFilterSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private VerticalHorizontalFilter _verticalHorizontalFilter; + private VerticalHorizontalFilter _verticalHorizontalFilter; // Store the Vertical Horizontal Filter indicator. - private SimpleMovingAverage _priceSimpleMovingAverage; - private SimpleMovingAverage _verticalHorizontalFilterSimpleMovingAverage; + private SimpleMovingAverage _priceSimpleMovingAverage; // Store the Simple Moving Average of closing prices. + private SimpleMovingAverage _verticalHorizontalFilterSimpleMovingAverage; // Store the Simple Moving Average of the VHF indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "VerticalHorizontalFilterSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = " Vertical Horizontal Filter")] - public DataSeries Source { get; set; } + public DataSeries Source { get; set; } // Data source for the VHF indicator. [Parameter("Periods", DefaultValue = 28, Group = " Vertical Horizontal Filter", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods, with a default of 28 periods. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the VHF indicator with the specified data source and period. _verticalHorizontalFilter = Indicators.VerticalHorizontalFilter(Source, Periods); + // Initialise a simple moving average of the VHF result with a period of 14. _verticalHorizontalFilterSimpleMovingAverage = Indicators.SimpleMovingAverage(_verticalHorizontalFilter.Result, 14); + // Initialise a simple moving average of closing prices with a period of 14. _priceSimpleMovingAverage = Indicators.SimpleMovingAverage(Bars.ClosePrices, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Skip trading if the VHF is below its moving average, indicating a lack of trend. if (_verticalHorizontalFilter.Result.Last(0) < _verticalHorizontalFilterSimpleMovingAverage.Result.Last(1)) return; + // Check if the closing price crosses above the moving average. if (Bars.ClosePrices.Last(0) > _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) <= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the closing price crosses below the moving average. else if (Bars.ClosePrices.Last(0) < _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) >= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Vidya Sample/Vidya Sample/Vidya Sample.cs b/Robots/Vidya Sample/Vidya Sample/Vidya Sample.cs index 76baa09..b29b556 100644 --- a/Robots/Vidya Sample/Vidya Sample/Vidya Sample.cs +++ b/Robots/Vidya Sample/Vidya Sample/Vidya Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the VIDYA (Variable Index Dynamic Average) indicator to determine trend direction. +// It opens buy and sell positions based on the crossover of two VIDYA lines with different settings. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,88 +15,102 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class VidyaSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private Vidya _fastVidya; + private Vidya _fastVidya; // Store the fast VIDYA indicator. - private Vidya _slowVidya; + private Vidya _slowVidya; // Store the slow VIDYA indicator. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast VIDYA indicator. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast VIDYA, defaulting to 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow VIDYA indicator. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow VIDYA, defaulting to 20. [Parameter("Sigma", DefaultValue = 0.65, Group = "Fast MA", MinValue = 0.1, MaxValue = 0.95)] - public double FastSigma { get; set; } + public double FastSigma { get; set; } // Sensitivity (Sigma) of the fast VIDYA, defaulting to 0.65. [Parameter("Sigma", DefaultValue = 0.6, Group = "Slow MA", MinValue = 0.1, MaxValue = 0.95)] - public double SlowSigma { get; set; } + public double SlowSigma { get; set; } // Sensitivity (Sigma) of the slow VIDYA, defaulting to 0.65. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "VidyaSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow VIDYA indicator with the specified parameters. _fastVidya = Indicators.Vidya(FastMaSource, FastMaPeriod, FastSigma); _slowVidya = Indicators.Vidya(SlowMaSource, SlowMaPeriod, SlowSigma); + // Set the display colors for the fast and slow VIDYA lines. _fastVidya.Result.Line.Color = Color.Blue; _slowVidya.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the fast VIDYA crosses above the slow VIDYA. if (_fastVidya.Result.HasCrossedAbove(_slowVidya.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close all sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Check if the fast VIDYA crosses below the slow VIDYA. else if (_fastVidya.Result.HasCrossedBelow(_slowVidya.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close all buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Volume Index Sample/Volume Index Sample/Volume Index Sample.cs b/Robots/Volume Index Sample/Volume Index Sample/Volume Index Sample.cs index 1f35627..b570e5a 100644 --- a/Robots/Volume Index Sample/Volume Index Sample/Volume Index Sample.cs +++ b/Robots/Volume Index Sample/Volume Index Sample/Volume Index Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Positive and Negative Volume Index indicators, along with a Simple Moving +// Average, to execute trades based on volume and price trends. +// // ------------------------------------------------------------------------------------------------- @@ -13,88 +16,104 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class VolumeIndexSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private PositiveVolumeIndex _positiveVolumeIndex; - private NegativeVolumeIndex _negativeVolumeIndex; + private PositiveVolumeIndex _positiveVolumeIndex; // Store the Positive Volume Index (PVI) indicator. + private NegativeVolumeIndex _negativeVolumeIndex; // Store the Negative Volume Index (NVI) indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average (SMA) for trend detection. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "VolumeIndexSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source for Positive Volume", Group = "Volume Index")] - public DataSeries PositiveSource { get; set; } + public DataSeries PositiveSource { get; set; } // Data source used by the Positive Volume Index. [Parameter("Source for Negative Volume", Group = "Volume Index")] - public DataSeries NegativeSource { get; set; } + public DataSeries NegativeSource { get; set; } // Data source used by the Negative Volume Index. [Parameter("Source", Group = "Simple Moving Average")] - public DataSeries SourceSimpleMovingAverage { get; set; } + public DataSeries SourceSimpleMovingAverage { get; set; } // Data source used by the SMA. [Parameter("Period", DefaultValue = 20, Group = "Simple Moving Average", MinValue = 1)] - public int PeriodSimpleMovingAverage { get; set; } + public int PeriodSimpleMovingAverage { get; set; } // Number of periods for the SMA, defaulting to 20. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Positive and Negative Volume Index indicators. _positiveVolumeIndex = Indicators.PositiveVolumeIndex(PositiveSource); _negativeVolumeIndex = Indicators.NegativeVolumeIndex(NegativeSource); + // Initialise the Simple Moving Average indicator. _simpleMovingAverage = Indicators.SimpleMovingAverage(SourceSimpleMovingAverage, PeriodSimpleMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check if the latest close price is above the SMA. if (Bars.ClosePrices.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Closу all sell positions. + // Open a buy position if no active trades exist and NVI > PVI. if (BotPositions.Length == 0 && _negativeVolumeIndex.Result.Last(0) > _positiveVolumeIndex.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } } + + // Check if the latest close price is below the SMA. else if (Bars.ClosePrices.Last(0) < _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close all игн positions. + // Open a sell position if no active trades exist and NVI < PVI. if (BotPositions.Length == 0 && _negativeVolumeIndex.Result.Last(0) < _positiveVolumeIndex.Result.Last(0)) { - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Volume Oscillator Sample/Volume Oscillator Sample/Volume Oscillator Sample.cs b/Robots/Volume Oscillator Sample/Volume Oscillator Sample/Volume Oscillator Sample.cs index 726b08d..44081cb 100644 --- a/Robots/Volume Oscillator Sample/Volume Oscillator Sample/Volume Oscillator Sample.cs +++ b/Robots/Volume Oscillator Sample/Volume Oscillator Sample/Volume Oscillator Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The cBot uses the Volume Oscillator and Simple Moving Averages to identify potential trade +// opportunities based on volume and price trends. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,80 +15,95 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class VolumeOscillatorSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private VolumeOscillator _volumeOscillator; + private VolumeOscillator _volumeOscillator; // Store the Volume Oscillator indicator. - private SimpleMovingAverage _priceSimpleMovingAverage; - private SimpleMovingAverage _volumeOscillatorSimpleMovingAverage; + private SimpleMovingAverage _priceSimpleMovingAverage; // Store the SMA applied to price for trend detection. + private SimpleMovingAverage _volumeOscillatorSimpleMovingAverage; // Store the SMA applied to the Volume Oscillator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "VolumeOscillatorSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Short Term", DefaultValue = 9, Group = "Volume Oscillator", MinValue = 1)] - public int ShortTerm { get; set; } + public int ShortTerm { get; set; } // Short-term period of the Volume Oscillator, defaulting to 9. [Parameter("Long Term", DefaultValue = 21, Group = "Volume Oscillator", MinValue = 1)] - public int LongTerm { get; set; } - + public int LongTerm { get; set; } // Long-term period of the Volume Oscillator, defaulting to 21. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Volume Oscillator with the specified periods. _volumeOscillator = Indicators.VolumeOscillator(ShortTerm, LongTerm); + // Calculate a 14-period SMA of the Volume Oscillator. _volumeOscillatorSimpleMovingAverage = Indicators.SimpleMovingAverage(_volumeOscillator.Result, 14); + // Calculate a 14-period SMA of the closing prices. _priceSimpleMovingAverage = Indicators.SimpleMovingAverage(Bars.ClosePrices, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Skip trading if the Volume Oscillator is below its SMA. if (_volumeOscillator.Result.Last(0) < _volumeOscillatorSimpleMovingAverage.Result.Last(0)) return; + // Identify a bullish signal: current close price crosses above the SMA. if (Bars.ClosePrices.Last(0) > _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) <= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Identify a bearish signal: current close price crosses below the SMA. else if (Bars.ClosePrices.Last(0) < _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) >= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Volume ROC Sample/Volume ROC Sample/Volume ROC Sample.cs b/Robots/Volume ROC Sample/Volume ROC Sample/Volume ROC Sample.cs index 848f92b..40dad8e 100644 --- a/Robots/Volume ROC Sample/Volume ROC Sample/Volume ROC Sample.cs +++ b/Robots/Volume ROC Sample/Volume ROC Sample/Volume ROC Sample.cs @@ -5,6 +5,9 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// The cBot uses the Volume Rate of Change (Volume ROC) indicator and Simple Moving Averages +// to detect potential trade opportunities based on volume and price momentum. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,77 +15,92 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class VolumeROCSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private VolumeROC _volumeROC; + private VolumeROC _volumeROC; // Store the Volume Rate of Change (Volume ROC) indicator. - private SimpleMovingAverage _priceSimpleMovingAverage; - private SimpleMovingAverage _volumeROCSimpleMovingAverage; + private SimpleMovingAverage _priceSimpleMovingAverage; // Store the Simple Moving Average (SMA) of closing prices. + private SimpleMovingAverage _volumeROCSimpleMovingAverage; // Store the SMA of the Volume ROC indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "VolumeROCSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Periods", DefaultValue = 14, Group = "Volume ROC", MinValue = 1)] - public int Periods { get; set; } - + public int Periods { get; set; } // Number of periods, with a default of 14 periods. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Volume ROC indicator with the specified period. _volumeROC = Indicators.VolumeROC(Periods); + // Calculate a 14-period SMA of the Volume ROC values. _volumeROCSimpleMovingAverage = Indicators.SimpleMovingAverage(_volumeROC.Result, 14); + // Calculate a 14-period SMA of the closing prices. _priceSimpleMovingAverage = Indicators.SimpleMovingAverage(Bars.ClosePrices, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Skip trading if the Volume ROC is below its SMA. if (_volumeROC.Result.Last(0) < _volumeROCSimpleMovingAverage.Result.Last(0)) return; + // Detect a bullish crossover: the current closing price crosses above the SMA. if (Bars.ClosePrices.Last(0) > _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) <= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close all sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // Detect a bearish crossover: the current closing price crosses below the SMA. else if (Bars.ClosePrices.Last(0) < _priceSimpleMovingAverage.Result.Last(0) && Bars.ClosePrices.Last(1) >= _priceSimpleMovingAverage.Result.Last(1)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close all buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Web Sockets Sample/Web Sockets Sample/Web Sockets Sample.cs b/Robots/Web Sockets Sample/Web Sockets Sample/Web Sockets Sample.cs index f86c35f..2a45d28 100644 --- a/Robots/Web Sockets Sample/Web Sockets Sample/Web Sockets Sample.cs +++ b/Robots/Web Sockets Sample/Web Sockets Sample/Web Sockets Sample.cs @@ -18,36 +18,47 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as AccessRights and its ability to add indicators. [Robot(AccessRights = AccessRights.None, AddIndicators = true)] public class WebSocketsExample : Robot { - private WebSocketClient _webSocketClient = new WebSocketClient(); - private readonly Uri _targetUri = new Uri("wss://marketdata.tradermade.com/feedadv"); + private WebSocketClient _webSocketClient = new WebSocketClient(); // Initialise a WebSocket client for managing server communication. + private readonly Uri _targetUri = new Uri("wss://marketdata.tradermade.com/feedadv"); // Define the WebSocket server URI for connecting to the price feed. + // This method is called when the cBot starts. protected override void OnStart() { + // Initiate a connection to the specified WebSocket server. _webSocketClient.Connect(_targetUri); + // Subscribe to the TextReceived event to handle incoming messages. _webSocketClient.TextReceived += _webSocketClient_TextReceived; + // Create a JSON payload with authentication and subscription details. var data = "{\"userKey\":\"PasteStreamingKeyHere\", \"symbol\":\"EURUSD\"}"; + // Send the subscription request to the WebSocket server. _webSocketClient.Send(data); } + // Event handler for processing received WebSocket messages. private void _webSocketClient_TextReceived(WebSocketClientTextReceivedEventArgs obj) { + // Log the message content after removing curly braces for cleaner output. Print(obj.Text.Replace("{", "").Replace("}", "").ToString()); } + // This method is triggered on every tick; can handle price updates or related tasks. protected override void OnTick() { - // Handle price updates here + // Handle price updates here. } + // This method is executed when the cBot stops. protected override void OnStop() { + // Close the WebSocket connection with a normal closure status. _webSocketClient.Close(WebSocketClientCloseStatus.NormalClosure); } } -} \ No newline at end of file +} diff --git a/Robots/Weighted Close Sample/Weighted Close Sample/Weighted Close Sample.cs b/Robots/Weighted Close Sample/Weighted Close Sample/Weighted Close Sample.cs index 2bb30cc..1e6f15d 100644 --- a/Robots/Weighted Close Sample/Weighted Close Sample/Weighted Close Sample.cs +++ b/Robots/Weighted Close Sample/Weighted Close Sample/Weighted Close Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Weighted Close indicator combined with a Simple Moving Average (SMA) to execute +// trades. It opens a buy position when the Weighted Close crosses above the SMA and a sell position +// when the Weighted Close crosses below the SMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,68 +16,82 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class WeightedCloseSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private WeightedClose _weightedClose; + private WeightedClose _weightedClose; // Store the Weighted Close indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average for Weighted Close. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "WeightedCloseSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Weighted Close indicator. _weightedClose = Indicators.WeightedClose(); + // Initialise the Simple Moving Average based on the Weighted Close result. _simpleMovingAverage = Indicators.SimpleMovingAverage(_weightedClose.Result, 14); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the Weighted Close crosses above the SMA, execute a buy trade. if (_weightedClose.Result.HasCrossedAbove(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the Weighted Close crosses below the SMA, execute a sell trade. else if (_weightedClose.Result.HasCrossedBelow(_simpleMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Weighted Moving Average Sample/Weighted Moving Average Sample/Weighted Moving Average Sample.cs b/Robots/Weighted Moving Average Sample/Weighted Moving Average Sample/Weighted Moving Average Sample.cs index 733fb0a..c5270e6 100644 --- a/Robots/Weighted Moving Average Sample/Weighted Moving Average Sample/Weighted Moving Average Sample.cs +++ b/Robots/Weighted Moving Average Sample/Weighted Moving Average Sample/Weighted Moving Average Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses two Weighted Moving Averages (WMAs), one fast and one slow, to determine trade signals. +// It opens a buy position when the fast WMA crosses above the slow WMA and a sell position when the fast +// WMA crosses below the slow WMA. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,82 +16,95 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class WeightedMovingAverageSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private WeightedMovingAverage _fastWeightedMovingAverage; + private WeightedMovingAverage _fastWeightedMovingAverage; // Store the fast Weighted Moving Average. - private WeightedMovingAverage _slowWeightedMovingAverage; + private WeightedMovingAverage _slowWeightedMovingAverage; // Store the slow Weighted Moving Average. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast moving average. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast moving average, default is 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow moving average. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow moving average, default is 20. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "WeightedMovingAverageSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow Weighted Moving Averages with the specified periods. _fastWeightedMovingAverage = Indicators.WeightedMovingAverage(FastMaSource, FastMaPeriod); _slowWeightedMovingAverage = Indicators.WeightedMovingAverage(SlowMaSource, SlowMaPeriod); + // Set the colors for the moving averages. _fastWeightedMovingAverage.Result.Line.Color = Color.Blue; _slowWeightedMovingAverage.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the fast WMA crosses above the slow WMA, execute a buy trade. if (_fastWeightedMovingAverage.Result.HasCrossedAbove(_slowWeightedMovingAverage.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + // If the fast WMA crosses below the slow WMA, execute a sell trade. else if (_fastWeightedMovingAverage.Result.HasCrossedBelow(_slowWeightedMovingAverage.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample.cs b/Robots/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample.cs index 1622ed4..7239942 100644 --- a/Robots/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample.cs +++ b/Robots/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample/Welles Wilder Smoothing Sample.cs @@ -5,6 +5,10 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses two Welles Wilder Smoothing (WWS) indicators, one fast and one slow, to generate +// trade signals. A buy position is opened when the fast WWS crosses above the slow WWS and a +// sell position is opened when the fast WWS crosses below the slow WWS. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,82 +16,96 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class WellesWilderSmoothingSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private WellesWilderSmoothing _fastWellesWilderSmoothing; + private WellesWilderSmoothing _fastWellesWilderSmoothing; // Store the fast Welles Wilder Smoothing indicator. - private WellesWilderSmoothing _slowWellesWilderSmoothing; + private WellesWilderSmoothing _slowWellesWilderSmoothing; // Store the slow Welles Wilder Smoothing indicator. + // Define input parameters for the cBot. [Parameter("Source", Group = "Fast MA")] - public DataSeries FastMaSource { get; set; } + public DataSeries FastMaSource { get; set; } // Data source for the fast WWS. [Parameter("Period", DefaultValue = 9, Group = "Fast MA")] - public int FastMaPeriod { get; set; } + public int FastMaPeriod { get; set; } // Period for the fast WWS, default is 9. [Parameter("Source", Group = "Slow MA")] - public DataSeries SlowMaSource { get; set; } + public DataSeries SlowMaSource { get; set; } // Data source for the slow WWS. [Parameter("Period", DefaultValue = 20, Group = "Slow MA")] - public int SlowMaPeriod { get; set; } + public int SlowMaPeriod { get; set; } // Period for the slow WWS, default is 20. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "WellesWilderSmoothingSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the fast and slow Welles Wilder Smoothing indicators with the specified periods. _fastWellesWilderSmoothing = Indicators.WellesWilderSmoothing(FastMaSource, FastMaPeriod); _slowWellesWilderSmoothing = Indicators.WellesWilderSmoothing(SlowMaSource, SlowMaPeriod); + // Set the colors for the WWS indicators. _fastWellesWilderSmoothing.Result.Line.Color = Color.Blue; _slowWellesWilderSmoothing.Result.Line.Color = Color.Red; } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // If the fast WWS crosses above the slow WWS, execute a buy trade. if (_fastWellesWilderSmoothing.Result.HasCrossedAbove(_slowWellesWilderSmoothing.Result, 0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } + + // If the fast WWS crosses below the slow WWS, execute a sell trade. else if (_fastWellesWilderSmoothing.Result.HasCrossedBelow(_slowWellesWilderSmoothing.Result, 0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +} diff --git a/Robots/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample.cs b/Robots/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample.cs index 1d4785b..07cd46f 100644 --- a/Robots/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample.cs +++ b/Robots/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample/Williams Accumulation Distribution Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot uses the Williams Accumulation/Distribution (WAD) indicator and a Simple Moving +// Average (SMA) to identify potential buy and sell signals. Correlation analysis is applied to +// evaluate the relationship between WAD and price movements. Signals are filtered out when +// correlation exceeds a threshold, focusing on uncorrelated data for trade execution. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -14,90 +19,107 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class WilliamsAccumulationDistributionSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private WilliamsAccumulationDistribution _williamsAccumulationDistribution; + private WilliamsAccumulationDistribution _williamsAccumulationDistribution; // Store the WAD indicator. - private SimpleMovingAverage _simpleMovingAverage; + private SimpleMovingAverage _simpleMovingAverage; // Store the Simple Moving Average for trade decisions. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, Group = "Trade", MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "WilliamsAccumulationDistributionSample", Group = "Trade")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Source", Group = "Simple Moving Average")] - public DataSeries SourceMovingAverage { get; set; } + public DataSeries SourceMovingAverage { get; set; } // Data series for SMA calculation. [Parameter("Periods Moving Average", DefaultValue = 14, Group = "Simple Moving Average", MinValue = 2)] - public int PeriodsMovingAverage { get; set; } + public int PeriodsMovingAverage { get; set; } // Number of periods for the SMA, default is 14. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the WAD indicator. _williamsAccumulationDistribution = Indicators.WilliamsAccumulationDistribution(); + // Initialise the SMA with the given data source and period. _simpleMovingAverage = Indicators.SimpleMovingAverage(SourceMovingAverage, PeriodsMovingAverage); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { - var correlation = GetCorrelation(14); + var correlation = GetCorrelation(14); // Calculate the correlation over the last 14 periods. + // Skip trade execution if the correlation is too high. if (correlation > 0.85) return; + // Check if the current close price is above the SMA to trigger a sell signal. if (Bars.ClosePrices.Last(0) > _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } + + // Check if the current close price is below the SMA to trigger a buy signal. else if (Bars.ClosePrices.Last(0) < _simpleMovingAverage.Result.Last(0)) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } + // This method calculates the correlation between WAD and close prices over a specified period. private double GetCorrelation(int period) { - var x = _williamsAccumulationDistribution.Result.Skip(_williamsAccumulationDistribution.Result.Count - period).ToArray(); - var y = Bars.ClosePrices.Skip(Bars.ClosePrices.Count - period).ToArray(); + var x = _williamsAccumulationDistribution.Result.Skip(_williamsAccumulationDistribution.Result.Count - period).ToArray(); // Extract WAD values for the period. + var y = Bars.ClosePrices.Skip(Bars.ClosePrices.Count - period).ToArray(); // Extract close prices for the period. if (!x.Any() || !y.Any()) { - return double.NaN; + return double.NaN; // Return NaN if data is insufficient. } + // Calculate sums and squared sums for both datasets. var xSum = x.Sum(); var ySum = y.Sum(); @@ -107,11 +129,12 @@ private double GetCorrelation(int period) var xSquaredSum = x.Select(value => Math.Pow(value, 2)).Sum(); var ySquaredSum = y.Select(value => Math.Pow(value, 2)).Sum(); - var xAndyProductSum = x.Zip(y, (value1, value2) => value1 * value2).Sum(); + var xAndyProductSum = x.Zip(y, (value1, value2) => value1 * value2).Sum(); // Calculate the sum of the product of corresponding values in both datasets. - double n = x.Count(); + double n = x.Count(); // Number of data points. + // Return the correlation coefficient. return (n * xAndyProductSum - xSum * ySum) / Math.Sqrt((n * xSquaredSum - xSumSquared) * (n * ySquaredSum - ySumSquared)); } } -} \ No newline at end of file +} diff --git a/Robots/WilliamsPctR Sample/WilliamsPctR Sample/WilliamsPctR Sample.cs b/Robots/WilliamsPctR Sample/WilliamsPctR Sample/WilliamsPctR Sample.cs index 1e57834..7abce98 100644 --- a/Robots/WilliamsPctR Sample/WilliamsPctR Sample/WilliamsPctR Sample.cs +++ b/Robots/WilliamsPctR Sample/WilliamsPctR Sample/WilliamsPctR Sample.cs @@ -5,6 +5,11 @@ // This cBot is intended to be used as a sample and does not guarantee any particular outcome or // profit of any kind. Use it at your own risk. // +// This cBot utilises the Williams %R indicator to identify overbought and oversold conditions +// in the market. Trading decisions are based on crossovers with user-defined levels (-20 and -80 +// by default). Buy and sell orders are executed when the indicator crosses these levels, aiming +// to capitalize on potential trend reversals. +// // ------------------------------------------------------------------------------------------------- using cAlgo.API; @@ -12,73 +17,86 @@ namespace cAlgo.Robots { + // Define the cBot attributes, such as TimeZone, AccessRights and its ability to add indicators. [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, AddIndicators = true)] public class WilliamsPctRSample : Robot { - private double _volumeInUnits; + // Private fields for storing the indicator and trade volume. + private double _volumeInUnits; // Store volume in units calculated based on the specified lot size. - private WilliamsPctR _williamsPctR; + private WilliamsPctR _williamsPctR; // Store the Williams %R indicator. + // Define input parameters for the cBot. [Parameter("Volume (Lots)", DefaultValue = 0.01)] - public double VolumeInLots { get; set; } + public double VolumeInLots { get; set; } // Trade volume in lots, default is 0.01 lots. [Parameter("Stop Loss (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double StopLossInPips { get; set; } + public double StopLossInPips { get; set; } // Stop-loss distance in pips, defaulting to 10 pips. [Parameter("Take Profit (Pips)", DefaultValue = 10, MaxValue = 100, MinValue = 1, Step = 1)] - public double TakeProfitInPips { get; set; } + public double TakeProfitInPips { get; set; } // Take-profit distance in pips, defaulting to 10 pips. [Parameter("Label", DefaultValue = "WilliamsPctRSample")] - public string Label { get; set; } + public string Label { get; set; } // Unique label for identifying orders placed by this cBot. [Parameter("Periods", DefaultValue = 14, Group = "Williams PctR", MinValue = 1)] - public int Periods { get; set; } + public int Periods { get; set; } // Number of periods, with a default of 14 periods. [Parameter("Up level", DefaultValue = -20, Group = "Williams PctR")] - public int UpValue { get; set; } + public int UpValue { get; set; } // Overbought threshold level, -20 by default. [Parameter("Down level", DefaultValue = -80, Group = "Williams PctR")] - public int DownValue { get; set; } + public int DownValue { get; set; } // Oversold threshold level, -80 by default. + // This property finds all positions opened by this cBot, filtered by the Label parameter. public Position[] BotPositions { get { - return Positions.FindAll(Label); + return Positions.FindAll(Label); // Find positions with the same label used by the cBot. } } + // This method is called when the cBot starts and is used for initialisation. protected override void OnStart() { + // Convert the specified volume in lots to volume in units for the trading symbol. _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots); + // Initialise the Williams %R indicator with the specified period. _williamsPctR = Indicators.WilliamsPctR(Periods); } + // This method is triggered whenever a bar is closed and drives the decision-making process for the cBot. protected override void OnBarClosed() { + // Check for a crossover above the upper threshold (overbought level) to trigger a sell trade. if (_williamsPctR.Result.Last(0) > UpValue && _williamsPctR.Result.Last(1) < UpValue) { - ClosePositions(TradeType.Buy); + ClosePositions(TradeType.Buy); // Close any open buy positions. - ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to sell with the specified volume, stop loss and take profit. } + + // Check for a crossover below the lower threshold (oversold level) to trigger a buy trade. else if (_williamsPctR.Result.Last(0) < DownValue && _williamsPctR.Result.Last(1) > DownValue) { - ClosePositions(TradeType.Sell); + ClosePositions(TradeType.Sell); // Close any open sell positions. - ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); + ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips); // Open a market order to buy with the specified volume, stop loss and take profit. } } + // This method closes all positions of the specified trade type. private void ClosePositions(TradeType tradeType) { foreach (var position in BotPositions) { + // Check if the position matches the specified trade type before closing. if (position.TradeType != tradeType) continue; - ClosePosition(position); + ClosePosition(position); // Close the position. } } } -} \ No newline at end of file +}