cTrader order execution guide

cTrader ExecuteMarketOrder: Orders, Volume Units, and Indicator Signals

Order code needs the correct API version, volume units, permissions, and event timing. This guide uses cBot fragments to explain market orders and indicator signals, while distinguishing them from the indicator trading workflow documented by cTrader.

Direct answer

Use ExecuteMarketOrder in a cBot with volume in units, inspect the returned TradeResult, and validate broker volume limits. Do not assume that all indicators are unable to trade: current cTrader documentation demonstrates an indicator trading panel using ExecuteMarketOrderAsync. Check the exact API version and permission workflow when diagnosing a missing-method error.

What to know first

  • Current cTrader documentation supports trading from indicators; a missing-method error requires checking the referenced API, overload, and calling context.
  • ExecuteMarketOrder accepts volume in symbol units, not lots. Passing 1.0 requests one unit; it does not establish that the broker will accept or fill it.
  • Convert lots with Symbol.QuantityToVolumeInUnits, normalize to the volume step, and separately check VolumeInUnitsMin and VolumeInUnitsMax.
  • Check TradeResult.IsSuccessful and a non-null Position before accessing the returned position.
  • Pineify can draft a single-file C# cBot and return compiler diagnostics; review volume, ownership, and execution rules independently.

Indicator vs cBot (Robot) capabilities in cTrader

CapabilityIndicator (cAlgo.API.Indicator)cBot (cAlgo.API.Robot)
Trading workflowOfficial indicator trading panels use ExecuteMarketOrderAsync; check API version and permissions.cBot order methods support automated execution; select an exact supported overload.
Primary design roleCalculate data series and draw chart graphicsAutomate order execution and manage trading accounts
Account and position accessAccount collections are available through the algorithm API; inspect the operations supported by the target version.Full access to Positions, PendingOrders, and History
Volume handlingTrading indicators also need valid symbol-unit volumeRequires raw units via Symbol.QuantityToVolumeInUnits
Main event handlersInitialize() and Calculate(int index)OnStart(), OnTick(), OnBar(), OnStop()
Backtesting supportCannot be backtested directlyFull historical simulation in cTrader Backtesting

Check API availability before diagnosing the error

Current cTrader documentation includes a custom indicator with Buy and Sell buttons that call ExecuteMarketOrderAsync. The user grants trading permission when using the panel. Indicators therefore cannot be described as universally unable to trade or access account collections.

For CS0103 or CS1061, inspect the actual compiler diagnostic, class context, method spelling, and referenced API version. Pineify checks its supported cTrader.Automate 1.0.19 contract; current online examples may target another API surface. A cBot remains the appropriate artifact for the historical backtesting workflow described here.

  • Indicators calculate through Initialize and Calculate and may also handle chart-control events.
  • Check the supported synchronous or asynchronous order method for the selected API version.
  • To automate an indicator, create a cBot that references the indicator output

How ExecuteMarketOrder works in a cTrader cBot

ExecuteMarketOrder sends an immediate market order to the broker. The call accepts trade direction, symbol, volume in units, order label, stop loss in pips, and take profit in pips.

The method returns a TradeResult object immediately upon completion or rejection. The caller should inspect TradeResult.IsSuccessful to handle broker rejections gracefully.

C# Calling ExecuteMarketOrder in a cBot
// Basic market order execution in a cBot
TradeResult result = ExecuteMarketOrder(
    TradeType.Buy,
    SymbolName,
    volumeInUnits,
    "MyStrategyLabel",
    20.0, // Stop Loss in pips
    40.0  // Take Profit in pips
);

if (result.IsSuccessful && result.Position != null)
{
    Print("Position #{0} opened at {1}", result.Position.Id, result.Position.EntryPrice);
}
else
{
    Print("Order failed with error: {0}", result.Error);
}

Converting lot sizes with Symbol.QuantityToVolumeInUnits

A common bug in cTrader cBots is passing lot quantities directly to ExecuteMarketOrder. In cTrader, order volume represents base units (for example, 100,000 units for 1 standard lot of EURUSD). A request for 1.0 unit is rejected if it violates the symbol minimum or step; do not assume every instrument uses the same limits.

Use Symbol.QuantityToVolumeInUnits to translate lots into units, then normalize to the symbol step with an explicit rounding mode. Normalization does not clamp minimum or maximum volume. The fragment below returns false for invalid or out-of-range volume so the caller can skip the order.

C# Lot to Volume In Units conversion
[Parameter("Volume (Lots)", DefaultValue = 0.1, MinValue = 0.01, Step = 0.01)]
public double QuantityInLots { get; set; }

private bool TryGetNormalizedVolume(out double volume)
{
    volume = 0;
    if (QuantityInLots <= 0 || double.IsNaN(QuantityInLots) || double.IsInfinity(QuantityInLots))
        return false;

    double rawVolume = Symbol.QuantityToVolumeInUnits(QuantityInLots);
    volume = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
    return !double.IsNaN(volume) && !double.IsInfinity(volume)
        && volume >= Symbol.VolumeInUnitsMin
        && volume <= Symbol.VolumeInUnitsMax;
}

Connecting Indicator signals to a cBot

To execute trades based on custom indicator conditions, instantiate the indicator inside your cBot using Indicators.GetIndicator. Read the indicator output series during OnBar or OnTick, and call ExecuteMarketOrder when your entry trigger occurs.

Filter existing positions by a stable strategy label and symbol. This checks currently open owned positions, but duplicate-entry prevention also needs an explicit repeat-signal and pending-order policy. MyCustomIndicator below is a placeholder dependency with a Result output, not a complete standalone source file. Configure that dependency in a native cTrader project; for the Pineify single-file workflow, ask for the permitted formula to be implemented inside the cBot instead of adding an external indicator project.

C# Bridging an Indicator to a cBot
// Inside a cBot class:
private MyCustomIndicator _indicator;

protected override void OnStart()
{
    _indicator = Indicators.GetIndicator<MyCustomIndicator>(14);
}

protected override void OnBar()
{
    // Example history guard for a 14-bar output; use the real indicator requirement.
    if (Bars.Count < 16 || _indicator == null) return;
    double signal = _indicator.Result.Last(1);
    if (double.IsNaN(signal) || double.IsInfinity(signal)) return;
    var openPositions = Positions.FindAll("MyCustomSignal", SymbolName);

    if (signal > 0 && openPositions.Length == 0)
    {
        double volume = Symbol.NormalizeVolumeInUnits(
            Symbol.QuantityToVolumeInUnits(0.1), RoundingMode.Down
        );
        if (volume < Symbol.VolumeInUnitsMin || volume > Symbol.VolumeInUnitsMax)
            return;
        TradeResult result = ExecuteMarketOrder(
            TradeType.Buy, SymbolName, volume, "MyCustomSignal", 25, 50);
        if (!result.IsSuccessful || result.Position == null)
            Print("Entry failed or returned no position: {0}", result.Error);
    }
}

Review generated execution code

Writing complete cBots with volume normalization, trade result handling, and indicator dependencies requires strict adherence to the cTrader Algo contract.

Pineify can draft C# cBots from indicator rules and check them against cTrader.Automate 1.0.19. Specify volume units, rounding, account ownership, and rejection handling, then review those paths in the generated code.

  • Transforms custom indicator formulas into automated cBot logic
  • Request lot conversion, step normalization, and explicit min/max checks
  • Review TradeResult status and position null checks
  • Resolve reported syntax and type errors before installation

Practical checks

Never pass raw lot numbers into ExecuteMarketOrder

In an order volume argument, 1.0 means one symbol unit. Convert lots and check step, minimum, and maximum; valid sizing alone does not guarantee acceptance.

Always inspect TradeResult.IsSuccessful

Market orders can fail, including when a market is closed or margin is insufficient. Inspect IsSuccessful, Error, and a non-null Position before accessing position fields.

Assign distinct labels to separate strategy positions

Use a stable label for the strategy and filter by both label and symbol. Avoid changing the label on every call, which can prevent later ownership lookups.

Primary sources

Pineify is an information tool, not investment advice. Automated order execution and compiler checks do not guarantee strategy profitability or eliminate market risk. Always test cBots on demo accounts before trading with real capital.

Frequently asked questions

Draft cTrader execution rules with AI

Describe indicator signals, volume rules, and order handling to draft a cBot, then review compiler diagnostics and test the behavior in cTrader.

Open the cTrader Coding Agent