C# and .NET Basics
What Is C#¶
C# is an object-oriented programming language that can be used to build various types of extensions and applications. As an object-oriented language, C# is easy to learn and read even if you have no prior programming experience. It also provides a structured means for writing compact and reusable code.
C# is our language of choice for cBots and indicators because of the following reasons.
- Shallow learning curve. Even if you have never worked with C# before, creating and deploying your first bot or indicator should only take a couple of minutes.
- Language efficiency. As C# is easy-to-use, you can quickly rewrite any code snippets from this documentation to suit your needs.
- Extensive class library. When using C# and .NET, you can access a large number of libraries containing predefined classes and methods. These methods can efficiently handle common tasks, leaving you free to solve complex trading problems.
- Support of asynchronous operations. In C#, you can write code that does not block server threads upon execution. In other words, you can start certain tasks simultaneously with other tasks.
To be executed, C# source code has to be compiled into an Intermediary Language (IL). IL code, in turn, is necessary to ensure compliance with the international common language infrastructure (CLI) specification. During execution, IL code is compiled into a set of native machine instructions.
What Is .NET¶
.NET is a virtual execution system based on a number of class libraries and the common language runtime, Microsoft's interpretation of the CLI. Without going into technical intricacies, .NET fulfills the following functions.
- Facilitating the development and execution of applications. The .NET SDK already contains several built-in compilers and build engines, eliminating the need for creating any custom solutions.
- Providing runtime libraries. If you would like to add certain data types or collections to your code, there is a high chance that .NET already has the corresponding set of classes and methods.
In our opinion, .NET is the perfect environment for creating and running trading bots and indicators.
The Basics of C#¶
Data Types and Variable Declarations¶
Data types are a means of categorizing data so that C# knows exactly how to treat variables and properties. In variable/property declarations, data types always precede the variable/property name.
Alternatively, you can use the
var keyword to avoid specifying a data type.
Objects and Classes¶
Think of objects as abstractions of tangible or intangible entities. These entities can have certain characteristics (properties) and can perform various operations (methods). In turn, classes serve as templates for object creation.
As C# is an object-oriented language, classes can also inherit properties and methods from other classes. Consider the following example in which we declare a new
NewBot class that inherits from the
Robot class. We also define some new class properties.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
As C# is a strongly-typed language, it is necessary to specify data types when declaring variables and class properties. In brief, data types constitute unique classes with different sets of behaviors. Consider the following examples in which various data types are specified for different class properties and related parameters.
In the above code, the
DataSeries data type represents a read-only list of values and is, therefore, typically used to represent market prices.
When there is a need to create multi-option parameters, you can use the built-in
enum data type as detailed below. You can think of
enums as special classes that contain various constants.
1 2 3 4 5 6 7 8 9
To access a constant contained in an
enum, use the following syntax.
If a parameter or a property needs to be a number, you will most often use the
int (integer) or
double (decimal) data types. While the
double type has less precision than the
decimal type, it is also less resource-intensive.
Last but not least, the
bool type typically represents a 'Yes/No' input. The values 'Yes' and 'No' correspond to
Namespaces act as designated collections of classes. Once you assign a class to a namespace, it can later be accessed by using the
<Namespace>.<ClassName> notation. We will assign our
NewBot to the
1 2 3 4 5 6 7 8
Class methods are defined following class declaration. All objects of our
NewBot class will be able to call the
CustomTradeOperation() method. It takes two arguments, namely a
Symbol object, and a
double object. Our method is supposed to take a symbol and execute some sort of trading action for the specified volume
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Class libraries (and, subsequently, class methods) can be accessed by their namespace as shown in the below example.
Alternatively, you can type in the
using keyword at the beginning of your code to designate certain namespaces and avoid redundancies. Consider the following code snippet.
1 2 3
To use conditional statements, use a keyword followed by an expression in round brackets. The below example uses the
if keyword to finalize our
CustomTradingOperation() method. To do so, we use the
EvaluateMarket() method which is defined in the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Collections are defined as 'containers' that can store one or more objects of a particular class.
Collections are fully indexable, meaning that their members can be accessed by passing a certain
integer value in square bracers. Consider the following example in which the
Calculate() method prints the properties of a bar accessed via its index.
1 2 3 4 5
Creating cTrader Extensions¶
In the below snippet, we create a very basic cBot using only the knowledge covered in the above sections.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Synchronous and Asynchronous Operations¶
As stated previously, C# fully supports asynchronous operations. The diagram below defines a basic example of how trading activities are performed in synchronous execution.
graph TD A(Encounter a Technical Signal) ==> B(Execute a Market Order) B ==> C(Take Profit/Stop Loss Reached) C ==> D(Close the Position) D ==> A
Synchronous execution carries one important drawback. In the above example, the action of executing a market order fully occupies all server threads, meaning that your cBot is unable to do anything else before this operation is completed.
This is less than ideal when you want to quickly react to market events and volatility. Ideally, your cBot should be able to 'store' various actions or put certain tasks 'on hold' to engage in other, more pressing activities. We will expand our example to better reflect how asynchronous operations are performed.
graph TD A([Encounter a Technical Signal]) ==> B([Place a 'Buy' Order]) & C([Place a 'Sell' Order for Hedging]) ==> D([An Order Hits Its Take Profit/Stop Loss]) D ==> E([Close the Position]) E ==> A
In the above example, our cBot simultaneously placed orders in both directions for hedging its positions. In contrast to synchronous operations, there is no need to wait for one operation to complete before proceeding with another one. This significantly expands developers' opportunities for creating efficient and reliable cBots.
Note that asynchronous execution is different from multi-threading.
- In asynchronous execution, all tasks are started on the same thread. When they are 'stored' or 'put on hold', they free this thread and, when their execution continues later, it occurs on a different thread chosen from the thread pool.
- When multi-threading, all tasks start on different threads and continue their execution on their initial threads. There is no thread 'shuffling'.
cTrader Automate never invokes your methods in parallel so you do not have to worry about multi-threading issues.