Quick Answer
CS0019: Operator '&&' cannot be applied to operands of type 'int' and 'bool' means that you used an operator (&&, ==, +, > and others) between two values whose types do not work with it. The message names the operator and both types, so it tells you exactly what to change. In a cBot the usual cases are a number used as a condition, a DateTime combined with a number, a string compared with a number, and an enum such as TradeType compared with an int.
The fix is to make both sides the same type: write a real comparison, use the DateTime methods for time arithmetic, parse the text, or compare the enum with an enum value. It is the "operator" version of the conversion errors CS0029 and CS0266.
From the author: I build cBots in cTrader Automate and convert strategies from Pine Script and MQL5 to C#. CS0019 is common in converted code because MQL5 treats
datetimeandboolas integers: you can add 60 to adatetimeor use anintas a condition. C# is stricter, and it says so with CS0019.
Key Facts
| What you see | Usual cause | Fix |
|---|---|---|
| '&&' ... 'int' and 'bool' | A number used as a condition | Write a comparison: count > 0 && hasBuy |
| '+' ... 'DateTime' and 'int' | MQL5 style time arithmetic | time.AddSeconds(60) or AddMinutes |
| '==' ... 'string' and 'double' | Text compared with a number | Parse the text, or compare text with text |
| '==' ... 'TradeType' and 'int' | A number used for buy or sell | Compare with TradeType.Buy |
| '>' ... 'bool' and 'int' | A condition compared with a number | Compare the numbers, or the bools |
| '!' ... 'int' | !count as in MQL5 | count == 0 |
What the Error Looks Like
The message always has the same shape: the operator, then the two operand types. For example:
error CS0019: Operator '&&' cannot be applied to operands of type 'int' and 'bool'
error CS0019: Operator '+' cannot be applied to operands of type 'DateTime' and 'int'
error CS0019: Operator '==' cannot be applied to operands of type 'string' and 'double'
Read the two type names first. They show which side to change.
The Broken cBot
This cBot prints a few values. It does not place trades. Each marked line has a CS0019 error:
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class BrokenBot : Robot
{
[Parameter("Risk % (text)", DefaultValue = "1.5")]
public string RiskText { get; set; }
protected override void OnBar()
{
int count = Positions.Count;
bool isUp = Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1);
if (count && isUp) // CS0019: 'int' and 'bool'
Print("Up bar with open positions");
DateTime expiry = Server.Time + 60; // CS0019: 'DateTime' and 'int'
if (RiskText == 1.5) // CS0019: 'string' and 'double'
Print("Default risk");
TradeType side = isUp ? TradeType.Buy : TradeType.Sell;
if (side == 1) // CS0019: 'TradeType' and 'int'
Print("Sell");
Print("Expiry {0}", expiry);
}
}
}
The compiler may report them in another order. Fix each line and build again.
Cause 1: A Number Used as a Condition
In MQL5 and C, if (count && isUp) is true when count is not 0 and isUp is true. C# requires bool on both sides of &&, || and !:
if (count > 0 && isUp)
Print("Up bar with open positions");
if (count == 0) // and not: if (!count)
Print("No positions");
Write the comparison you mean. It is also easier to read.
Cause 2: A DateTime Combined With a Number
An MQL5 datetime is a number of seconds, so TimeCurrent() + 60 works. In C# a DateTime is an object, and you add time with methods:
DateTime expiry = Server.Time.AddMinutes(1); // one minute later
DateTime later = Server.Time.AddSeconds(60); // the same
DateTime day = Server.Time.AddDays(1);
Subtracting two DateTime values is allowed and gives a TimeSpan:
TimeSpan age = Server.Time - position.EntryTime;
if (age.TotalMinutes > 30)
Print("Open for more than 30 minutes");
Server.Time is the time of the server of the account, and position.EntryTime is the time when the position was opened. Check both names in the code completion of your cTrader version. A related mistake is comparing a DateTime with a number (time == 0): compare it with another DateTime, or with default(DateTime).
Cause 3: A String Compared With a Number
A string and a double cannot be compared. Parse the text first, or better, declare the parameter as a number, as in the CS0029 guide:
[Parameter("Risk %", DefaultValue = 1.5, MinValue = 0.1, MaxValue = 5.0)]
public double RiskPercent { get; set; }
if (RiskPercent == 1.5) // both sides are double
Print("Default risk");
When you must compare two double values for equality, remember that they can differ by a tiny amount after a calculation. For prices, compare with a tolerance (Math.Abs(a - b) < Symbol.TickSize / 2) or round both sides first.
Cause 4: An Enum Compared With a Number
TradeType, MovingAverageType and similar types are enums. Compare them with the enum values, not with numbers:
if (side == TradeType.Sell)
Print("Sell");
Comparing an enum with the literal 0 may compile, because C# allows the literal 0 to convert to any enum, and this hides mistakes: do not rely on it. If you keep a direction as a number from an MQL5 port, convert it once with an if or a switch, and use TradeType everywhere else.
Cause 5: Mixed Types in Arithmetic
+ between a bool and a number, or - between a string and a number, are CS0019 too. If the message names bool, you probably wanted isUp ? 1 : 0. If it names string, you probably wanted to build text ("Value " + value.ToString()) or to parse it. When one side is a double? (nullable, such as a stop loss), check HasValue or use ?? 0.0 before you calculate:
double sl = position.StopLoss ?? 0.0;
The Fixed cBot
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class FixedBot : Robot
{
[Parameter("Risk %", DefaultValue = 1.5, MinValue = 0.1, MaxValue = 5.0)]
public double RiskPercent { get; set; }
protected override void OnBar()
{
int count = Positions.Count;
bool isUp = Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1);
if (count > 0 && isUp)
Print("Up bar with open positions");
DateTime expiry = Server.Time.AddMinutes(1);
if (RiskPercent == 1.5)
Print("Default risk");
TradeType side = isUp ? TradeType.Buy : TradeType.Sell;
if (side == TradeType.Sell)
Print("Sell");
Print("Expiry {0}", expiry);
}
}
}
The bot only prints. DateTime needs using System; at the top, and without it the error is CS0246 (cTrader C# error CS0246). Compare the values with the chart before you add an order, and test on a demo account.
Similar Errors
| Error | Message | What it means | |---|---|---| | CS0019 | Operator cannot be applied to operands of type | The operator does not work with these two types | | CS0029 | Cannot implicitly convert type | A value of the wrong type is stored | | CS0266 | Cannot implicitly convert type, an explicit conversion exists | A cast fixes it | | CS1503 | Argument N: cannot convert | A call has an argument of the wrong type | | CS0103 | The name 'x' does not exist in the current context | A name is unknown |
Checklist: What to Check When You See CS0019
- Read the operator and both types in the message.
- Is a number used as a condition? Write a comparison.
- Is it a
DateTime? UseAddMinutes,AddSecondsor subtract two dates. - Is it text? Parse it, or declare the parameter as a number.
- Is it an enum? Compare with
TradeType.BuyorTradeType.Sell. - Is a value nullable? Use
HasValueor??first. - Build again after each change, and print the values.
- Test on a demo account before the cBot trades with real money.
Common Mistakes
- Using
if (count)orif (!count)as in MQL5. - Adding seconds to a
DateTimewith+. - Using a
stringparameter for a number. - Comparing a direction with a number.
- Comparing two
doublevalues for equality after a calculation. - Ignoring a nullable stop loss.
FAQ
Related Guides
- cTrader C# error CS0029: no conversion exists at all.
- cTrader C# error CS0266: when a cast fixes it.
- cTrader C# error CS1503: an argument of the wrong type in a call.
- cTrader C# errors CS7036 and CS1501: the wrong number of arguments.
- cTrader C# error CS0103: the name does not exist in the current context.
- cTrader C# error CS1061: the object is found, the member is not.
- Pine Script strategy.entry to cTrader C#: order calls and
TradeType. - Pine Script to cTrader C# cBot: the full conversion process.
- What to check in a trading bot before going live: a pre-live checklist for stops, lot size, spread and trade results.
- cTrader C# errors CS1002 and CS1513: a missing semicolon, brace or parenthesis.
- cTrader C# error CS0165: a variable is read before it has a value.
Fix Compile Errors Without Guessing
If a cBot or an Expert Advisor does not build, paste the code and the error message into the CodeFlowOS Error Fixer. It suggests a minimal fix, explains each error and shows what changed. A fix uses 1 credit, with up to 3 attempts included, and the compiler check is optional. Outputs are not guaranteed, and code that compiles can still have wrong trading logic, so always review the result. Before a bot goes live, the Code Review is free during the early-bird period. CodeFlowOS also converts strategies between Pine Script, MQL5 and cTrader C#: try the converter page.
This article is educational. It does not describe trading performance and is not financial advice. Always build the code in cTrader Automate and backtest it before using it on a live account.