You can develop a cBot that trades multiple symbols in addition to the one specified when creating a new instance.
Making it possible, Symbols is a collection of all symbols available to your trading account. You can iterate over it by using loops; alternatively, you can search over it to find specific symbols.
To correctly work with multiple symbols, cBots need to know the following information:
The minimum and maximum allowed volume
The volume step
The pip tick size
The pip tick value (the monetary value of one pip or tick in the account deposit currency)
This data can be learned from a Symbol object. In the code below, we find a symbol with "GBPUSD" as its name and then create a market order for it. We also use its minimum allowed volume as order volume.
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*fromcAlgo.API.Internalsimport*# Import trading wrapper functionsfromrobot_wrapperimport*classSample_cBot():defon_start(self):symbol=api.Symbols.GetSymbol("GBPUSD")ifsymbolisnotNone:api.ExecuteMarketOrder(TradeType.Sell,symbol.Name,symbol.VolumeInUnitsMin)
Convert pips to ticks
When coding cBots, it is easy to encounter bugs arising from the fact that some variable values are calculated in units while other values are calculated in pips.
The below SymbolExtensions class showcases how pips can be converted to ticks. It also demonstrates how pips can be added to an absolute price value.
usingSystem;usingcAlgo.API;usingcAlgo.API.Internals;namespaceSamples{[Robot(AccessRights = AccessRights.None)]publicclassSample:Robot{protectedoverridevoidOnStart(){varspreadInPips=Symbol.NormalizePips(Symbol.ToPips(Symbol.Spread));Print(spreadInPips);varspreadInTicks=Math.Round(Symbol.ToTicks(Symbol.Spread));Print(spreadInTicks);/* Calculating a long position stop loss using the absolute price value. */varstopLossInPips=60;/* We use 'NormalizePips' to avoid the 'invalid decimal places' error in case our stop loss value has too many decimals. */varstopLossInPrice=Symbol.Ask-(Symbol.NormalizePips(stopLossInPips)*Symbol.PipSize);Print(stopLossInPrice);}}publicstaticclassSymbolExtensions{/// <summary>/// Returns a symbol pip value/// </summary>/// <param name="symbol"></param>/// <returns>double</returns>publicstaticdoubleGetPip(thisSymbolsymbol){returnsymbol.TickSize/symbol.PipSize*Math.Pow(10,symbol.Digits);}/// <summary>/// Returns a price value in terms of pips/// </summary>/// <param name="symbol"></param>/// <param name="price">The price level</param>/// <returns>double</returns>publicstaticdoubleToPips(thisSymbolsymbol,doubleprice){returnprice*symbol.GetPip();}/// <summary>/// Returns a price value in terms of ticks/// </summary>/// <param name="symbol"></param>/// <param name="price">The price level</param>/// <returns>double</returns>publicstaticdoubleToTicks(thisSymbolsymbol,doubleprice){returnprice*Math.Pow(10,symbol.Digits);}/// <summary>/// Rounds a price level to the number of symbol digits/// </summary>/// <param name="symbol">The symbol</param>/// <param name="price">The price level</param>/// <returns>double</returns>publicstaticdoubleRound(thisSymbolsymbol,doubleprice){returnMath.Round(price,symbol.Digits);}/// <summary>/// Normalize x Pips amount decimal places to something that can be used as a stop loss or take profit for an order./// For example if symbol is EURUSD and you pass to this method 10.456775 it will return back 10.5/// </summary>/// <param name="symbol">The symbol</param>/// <param name="pips">The amount of Pips</param>/// <returns>double</returns>publicstaticdoubleNormalizePips(thisSymbolsymbol,doublepips){varcurrentPrice=Convert.ToDecimal(symbol.Bid);varpipSize=Convert.ToDecimal(symbol.PipSize);varpipsDecimal=Convert.ToDecimal(pips);varpipsAddedToCurrentPrice=Math.Round((pipsDecimal*pipSize)+currentPrice,symbol.Digits);vartickSize=Convert.ToDecimal(symbol.TickSize);varresult=(pipsAddedToCurrentPrice-currentPrice)*tickSize/pipSize*Convert.ToDecimal(Math.Pow(10,symbol.Digits));returndecimal.ToDouble(result);}}}
Transactions contains types that provide data on deposits and withdrawals for accounts. These types enable you to access and manage transaction details for accounts programmatically.
You can retrieve data on the transaction type (deposit or withdrawal), amount, timestamps, transaction ID, balance details, equity properties, etc.
This cBot retrieves and prints out transaction details:
cTrader provides the HistoricalOrder collection to enable users to retrieve information on orders, including completed market orders and pending orders that were executed or cancelled. The retrievable details include the order ID, its type, label, target price, expiration, etc.
The cBot code below shows you how to get the details for historical orders:
When coding cBots, you have access to your account history. This means that you can iterate over your past trades and use their data for whatever purposes you have.
The code snippet below creates a .CSV file containing all of our past trades and their trade data.
usingSystem;usingcAlgo.API;usingSystem.Text;usingSystem.IO;namespaceSamples{/* We provide the access rights required for reading and writing in locally stored files. */[Robot(AccessRights = AccessRights.FullAccess)]publicclassSample:Robot{protectedoverridevoidOnStart(){varstringBuilder=newStringBuilder();_=stringBuilder.AppendLine($"PositionId,TradeType,SymbolName,VolumeInUnits,EntryTime,EntryPrice,ClosingTime,ClosingPrice,NetProfit,Balance");// All trades are inside the 'History' collectionforeach(vartradeinHistory){_=stringBuilder.AppendLine($"{trade.PositionId},{trade.TradeType},{trade.SymbolName},{trade.VolumeInUnits},{trade.EntryTime:o},{trade.EntryPrice},{trade.ClosingTime:o},{trade.ClosingPrice},{trade.NetProfit},{trade.Balance}");}// We will save the CSV file on our desktopvardesktopPath=Environment.GetFolderPath(Environment.SpecialFolder.Desktop);varfilePath=Path.Combine(desktopPath,$"{Account.Number}_History.csv");File.WriteAllText(filePath,stringBuilder.ToString());}}}
Get information on deals
In cTrader, deals execute orders and cause positions to be opened or closed. Depending on the market liquidity, an order may be filled entirely by a single deal or in parts by several deals. See Positions and deals to learn more.
The cBot code below shows you how to retrieve information about multiple deals that exist in a single position:
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*fromcAlgo.API.Internalsimport*# Import trading wrapper functionsfromrobot_wrapperimport*classDealsExample():defon_start(self):position=api.ExecuteMarketOrder(TradeType.Buy,"EURUSD",10000)deals=position.Position.Dealsfordealindeals:api.Print(f"{deal.ExecutionTime}{deal.Status}{deal.Id}")api.ClosePosition(position.Position,3000)api.ClosePosition(position.Position,7000)closing_deals=api.History.FindByPositionId(position.Position.Id)forclosing_dealinclosing_deals:api.Print(f"{closing_deal.ClosingDeal.ExecutionTime}{closing_deal.ClosingDeal.VolumeInUnits}")defon_stop(self):pass
Convert lots to units
By default, cTrader algos calculate volume in units instead of lots. However, in some cases you may find that working with lots is more convenient and familiar.
You can convert lots to units by using the Symbol.QuantityToVolumeUnits() method.
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*fromcAlgo.API.Internalsimport*# Import trading wrapper functionsfromrobot_wrapperimport*classSample():defon_start(self):lots=2.5volume_in_units=api.Symbol.QuantityToVolumeInUnits(lots)api.ExecuteMarketOrder(TradeType.Sell,api.SymbolName,volume_in_units)
Alternatively, you can use the Symbol.VolumeInUnitsToQuantity() method to convert units to lots.
Work with colours
cBots can use custom colours when performing various operations (for example, when displaying text on trading charts). To add colour as a customisable parameter, add the following code to your parameter declarations.
You can use both hexadecimal colour codes and colour names (such as "red") when defining the DefaultValue of such a parameter.
To illustrate how colour parameters work, we will create a simple cBot that, upon being started, will write text on the trading chart on which it is operating. The colour of this text will be customisable via the TextColor parameter.
1 2 3 4 5 6 7 8 910111213141516171819202122232425
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingcAlgo.API;usingcAlgo.API.Collections;usingcAlgo.API.Indicators;usingcAlgo.API.Internals;namespacecAlgo.Robots{[Robot(AccessRights = AccessRights.None)]publicclassSampleColorcBot:Robot{[Parameter("Text Color", DefaultValue = "red")]publicColorTextColor{get;set;}protectedoverridevoidOnStart(){varstaticText=Chart.DrawStaticText("static","Sample text to demonstrate how color works",VerticalAlignment.Center,HorizontalAlignment.Center,TextColor);}}}
1 2 3 4 5 6 7 8 91011121314151617181920
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*fromcAlgo.API.Internalsimport*# Import trading wrapper functionsfromrobot_wrapperimport*classSampleColorcBot():defon_start(self):api.Chart.DrawStaticText("static","Sample text to demonstrate how color works",VerticalAlignment.Center,HorizontalAlignment.Center,api.TextColor)