AI Agents And Algorithmic Trading

Agents are very important in Artificial Intelligence. 21st century belongs to Artificial Intelligence. AI agents are being a lot now a days that includes filtering email spam to controlling Air Traffic. You must  heard a lot about autonomous driving vehicles. If we can have autonomous driving cars why can’t we have autonomic trading agents. An AI Agent constantly monitors the environment and take autonomous decisions. We can use different AI Agent models. We will be discussing them in this post. Did you read my post on technical analysis and behavior finance?

GBP Pair Trading Strategy

Let’s discuss a trading strategy and how we can measure it. I have a simple trading strategy in my mind. I want to check if it has the potential to make some money. The trading strategy I think will work best on GBP pairs. We will test this trading strategy on a few GBP pairs like GBPUSD and GBPJPY. The pair trading strategy is if we have a pivot low on M30 and the MACD is bullish, we wait for the 24 period close high break on M5 and make an entry. We haven’t decided on the take profit target. Below I post the trading strategy performance on GBPUSD pair for around 20 months. The performance of this trading strategy is very good. Starting with $1K it more than doubled it to $2.6K which is excellent. The max drawdown was $437.

>>> data1.iloc[-1]
EntryPrice        1.363630
StopLoss          1.364070
Profit           43.200000
Loss              0.000000
GrossProfit    2223.400000
NW               29.000000
GrossLoss      1357.200000
NL              152.000000
Equity         2688.852387
NB               93.000000
Lots              0.611103
NS               89.000000
MaxEquity      3126.360407
MaxDrawdown     437.508019
Name: 14761, dtype: float64

Above is a sort of equity curve of the trading strategy on GBPUSD. Sort of in the sense that it plots the equity value at the end of each new bar which maybe not the right thing but it gives you a picture that the trading strategy is making pips and losing pips. You will be surprised that the winrate of the above trading strategy is only 16%. What this means is that this trading strategy is losing a lot something like 84 trades out of 100 trades but it still doubled the account. You will ask why? The stop loss is less than 10 pips and the take profit is something like 80 pips so whenever we  have a high Reward/Risk ratio we can have a low winrate trading strategy make good money.

Markets are not random. Efficient Market Hypothesis has been proven wrong by master traders who have been predicted the market and making a lot of money. Price has got context just like the piece on the chess board has a context. Today computers have become so good at playing chess that the chess grand master hesitates to play against a computer. Lee Sedol the best Go player got defeated by Algo Go algorithm developed by Deep Mind now owned by Google. Surely big banks and hedge funds must have developed AI Agents that they use to predict the markets. What I mean to say is the AI has become really good at playing Chess and Go and don’t forget Watson from IBM defeated the Jeopardy champions using latest machine learning and AIs. Read the post where I show how we can use dynamic linear models in trading.

The key to trading success is recognizing repeatable price patterns that often appear before a big move in the market. This repeated price behavior stems from the psychology of the market participants. When we aggregate a large group of people into a market we will see these price patterns. We cannot change human psychology and we will always see these price patterns develop in the market no matter how much algorithms start ruling the market, After all these trading algorithms are also developed by us humans. Important question is can our AI trading agents recognize these price patterns in the market. Learn how to trade with three exponential moving averages.

Let’s return to the trading strategy that we tested on GBPUSD. Let’s now test it on GBPJPY after all it is also a GBP pair and it moves a lot. Below is the backtesting data of the trading strategy that I mentioned in the start of this post. This time the performance of this trading strategy is miserable. It loses so much you just won’t want to trade live with it. We started with $1K and end up with $740 after two months. At least we didn’t lose the whole $1K we just lost $250 in two months. What this shows is that what may work for one pair may not work for another pair.

EntryPrice      144.149000
StopLoss        144.102000
Profit           19.300000
Loss              0.000000
GrossProfit    1640.900000
NW               20.000000
GrossLoss      1551.900000
NL              163.000000
Equity          735.391291
NB               84.000000
Lots              0.156466
NS              100.000000
MaxEquity      1110.720760
MaxDrawdown     439.957509
Name: 14759, dtype: float64

The winrate of this trading strategy on GBPJPY pair is even less something around 10%. If you have read about the Turtle Trading System it has a winrate around 30-40% yet it made a lot of money because it used a small stop loss to catch the big moves in the market. An edge means a slight statistical advantage over the so called random price behavior in the market. Statistical advantage means in the long run over a series of trades something like 50 trades if we have an edge over the market we will be profitable. But there is no guarantee that we will lose the trade. Developing a statistical advantage recognizing these price patterns is not an easy thing. If it had been easy lot of people would be making a lot of money trading. In reality very few people make money trading. Can the AI trading agent developed by us have that statistical edge? We can do a  backtest and try to get a rough idea. But there is no guarantee. Download this fuzzy hammer candlestick pattern indicator.

We need to understand the market structure before we should trade. We need to know how price is determined in the market. Suppose I have 100 shares of ABC company and I want to sell them at say $300 per share. There is a buyer who also wants to buy 200 shares of ABC company but he is willing only to pay $250 per share. As long as one out of us doesn’t capitulate we cannot make a trade. Let’s say I capitulate and agree to sell at $250. This is how price is determined in the market. There should be two parties who agree on a price to make a trade. Learn to catch big moves with a small stop loss.

The problem is with the retail small traders like us who lack the resources to hire Quants. The only solution for us to learn coding and AI ourselves and develop AI Trading Agents.  Can we do that? We will try in this post. Future of algorithmic trading belongs to these AI Trading Agents. Days of looking at the charts and making trading decisions are over. We need to reequip ourselves with new skills if we want to survive in the markets. With each decade the market changes. In the 1980s markets started becoming electronic. In 1990s this transition was fully completed almost all over the world. Now everything is shifting to AI. We need to embrace the change. Do you remember the GBPUSD Flash Crash? It was caused by Quants.

Artificial Intelligence Trading Agents

In this post we will discuss what are AI Agents and how we can use them in algorithmic trading. Algorithmic trading means fully autonomous trading. In the beginning, we cannot fully trust our autonomous trading agents. It can also mean we use it to generate trading signals and then use our intuition and judgement in making the final decision whether to plug the buy or sell trigger to simply ignore the signal. Once you develop confidence in your autonomous trading agents, you can give them more autonomy. This is precisely what is happening with autonomous driving cars. After a few accidents, developers are not taking any chances and the driver can also take back control.

Agents are also known as bots. When you are trading on cTrader, you can code a cBot to automate your trading strategy. The challenge is how to make the cBot intelligent enough to make the right business decisions. Using different indicators in your trading strategy will provide you will a number of signals most of which will be contradicting. One indicator will say buy while the other indicator will say sell. How are we going to do conflict resolution so that we take the right signal and ignore the false signal. This is the challenge. We can never be 100% right but we can strive for 70% accuracy. In this post we are going to see if we can do that.

In our case an AI Agent will analyze each bar when it is formed and look at a number of indicators to make a decision whether to open a trade or simply ignore it. On its own Agents are nothing. It is the algorithmic trading strategy that we code into it determines how well it is going to perform in reality. If our algorithmic trading strategy is not good, the agent will also not make good decision. How do we determine that our agent is going to perform good. We will conduct backtest that will give us a rough idea as to how the agent is going to perform in live trading. Rough idea means there is not guarantee that things will work our in reality.

Algorithmic trading is the name of the game now a days. If you want to become a master trader, you need to first learn how to code. Python and C# are two programming languages that are being used a lot now a days. There are many trading platforms that have been made using C# that includes NinjaTrader, cTrader, QuantTower and more. In this post we will discuss how we can code Trading Agents in C#. Trading agents are full fledged trading strategies that take into account the agent based modelling that we use in Game AI. Let’s fuse algorithmic trading with Game AI. We will be using C# and NinjaScript framework designed for coding indicators and strategies on NinjaTrader. Since we will be coding in C# we can easily modify the code and make it work for cTrader as well.

As said above an ai trading agent will continuously monitor the chart and take buy/sell decision which we have programmed into it. We can attach a trading agent on charts like M15, M20,  M30, M60 etc. We program the trading agent to give buy/sell signal and we consider it like a vote. So if we have a buy signal on M15, M30 we can consider it to be a strong buy signal. Autonomy means the trading agent can make buy and sell decisions without human intervention. The trading agent that we code should be reactive meaning it should be able to react to the different signals and resolve the conflicting signals. The trading agent should also be proactive meaning it should have the ability to look for trades that make a minimum of 60 pips with a small stop loss of 10 pips. Trading agent should have social ability meaning it should be able to interact with other trading agents.

A purely reactive agent does not remember the past and only makes the trading decision on the current bar close. So a purely reactive agent has a very short term horizon. Since decision making is made based only on the current bar, it is difficult to learn from experience and improve future performance. The trading agent should remember the past  trades meaning it should not be purely reactive. Ideally our trading agent should be proactive but at the same time should be able to react in a timely fashion and should have the ability to avoid a bad trade.

In a deterministic environment every action has a clear and unambiguous outcome. While in a nondeterministic environment there can be a number of outcomes. We will be dealing with deterministic agent that will give us clear buy and sell signals with clear stop loss levels. Take profit is always an ambiguous thing and involves guesswork. In an accessible environment we have completer information about the environment while in an inaccessible environment we have incomplete information about environment.

AI Trading Agent Developed for NinjaTrader

This is exactly what we find in financial markets. So many factors are in play we cannot know completely what is happening. Suddenly there is a breaking news and price starts diving. Similarly suddenly there is positive news and the price jumps up. We cannot simply track all the factors that are moving the price in the financial market. What we want is that our trading agent should remember the past. We do this by using the state variable. Let’s start coding our trading agent. We will code the trading agent in C# using the NinjaScript Framework which is indeed very powerful.

public class TradingAgent{}

First let’s define some properties:

#region Trading Agent Properties
public int Timeframe { get; set; }//timeframe for the agent
public int Rule { get; set; }//Rule that is fired
public double Profit; //Profit made by the agent
public double Loss; //Loss made by the agent
public int State { get; set; } //Buy and sell state			
public double EntryPrice { get; set; } //entry price 			
public double StopLoss { get; set; } //stoploss 					public double TakeProfit { get; set; } //take profit 
public int Signal { get; set; } // Signal Long/Short
public double GrossProfit { get; set; }//Gross profit made
public double GrossLoss { get; set; }//Gross Loss made
public int NW { get; set; } //number of winning trades
public int NL { get; set; } //number of losing trades
public int NB { get; set; } //number of long trades
public int NS { get; set; } //number of short trades
public double Equity { get; set; } //Account equity
public double Risk { get; set; } //Risk level
public double Lots { get; set; } //Number of Lots
public List<double[]> Journal { get; set; }//Trading Journal
public double[] JournalEntry { get; set; }//Trading Journal Entry
public double Drawdown { get; set; }//Strategy Drawdown
public double MaxEquity { get; set; }//Strategy Max Equity 
public double MaxDrawdown { get; set; }//Strategy Max Drawdown
public double TSL { get; set; }//Trailing Stop Loss
#endregion

Above we have defined the properties. We want the trading agent to define the entry price and stop loss. We also want the trading agent to remember the result of each trade whether it was a winner or a loser and how much profit did it make. In total there are 25 properties that this trading agent is going to remember. We also want the trading agent to calculate the drawdown and the gross profit and gross loss as it keeps on opening new trades. We record the details of each trade in the Journal property which is a list. These properties will help us measure the performance of the trading agent over 20K bars whatever we choose. Once we define the properties that the trading agent will maintain all the times, we need to provide the constructor that will be used to initialize the trading agent. We do that below:

#region Trading Agent Constructor
public TradingAgent(int _timeframe, double _equity, double _risk) 
{
Timeframe = _timeframe;
Equity = _equity;
Risk = _risk;
State = 0;
Rule = 0;
Profit = 0.0;
Loss = 0.0;
EntryPrice = 0.0;
StopLoss = 0.0;
TakeProfit = 0.0;
Signal = 0;
GrossProfit = 0;
GrossLoss = 0;
NW = 0;
NL = 0;
NB = 0;
NS = 0;
Lots = 0.0;
MaxEquity = Equity;
MaxDrawdown = 0;
Journal = new List<double[]>();
JournalEntry = new double[10];
}
#endregion

C# Compiler provides a default parameterless constructor. We don’t need that. So we define a constructor that has parameters of timeframe, equity and risk. We want the trading agent to start with a  certain equity amount and open trades risking not more than what we specify. So we can constantly measure the performance of the trading agent and keep track of total trades made so far and how many were winners and how many were losers. Now that we have the constructor we code the open trade method:

#region Open Trade Method
public void OpenTrade(int _signal, double _high, double _low, 
double _close, double _pip) 
{
				
if (_signal > 0 && State == 0 && _close !=_low)
{				
State = 1; //initialize Long position
EntryPrice = _close; //initialize Entry Price
if (Timeframe == 0 || Timeframe > 9) //only for H1 and above
{
StopLoss = _low - 5 * _pip; //initialze Stop Loss
}
else StopLoss = _low;
Rule = _signal; //specify rule
Signal = 1;
NB++;
LotSize(_pip);
JournalEntry[0] = State;
JournalEntry[1] = Rule;
JournalEntry[2] = EntryPrice;
JournalEntry[3] = StopLoss;
JournalEntry[4] = Lots;
}

else if (_signal < 0 && State == 0 && _close != _high) 
{ State = -1; //initialize Short position 
EntryPrice = _close; //initialize Entry Price 
if (Timeframe == 0 || Timeframe > 9) //only for H1 and above
{
StopLoss = _high + 5 * _pip; //initialize Stop Loss
}
else StopLoss = _high;
Rule = _signal; //specify rule
Signal = -1;
NS++;
LotSize(_pip);
JournalEntry[0] = State;
JournalEntry[1] = Rule;
JournalEntry[2] = EntryPrice;
JournalEntry[3] = StopLoss;
JournalEntry[4] = Lots;
}

else Signal = 0;				
}   //End OpenTrade	
#endregion

As you can see we are keeping a full fledged trading journal which is recording each trade with the entry price stop loss lots that we used to open the trade. But how do we calculate the lots? Let’s do that now.

#region Calculate Lot Size for the trade
public void LotSize(double _pip)
{
if (State == 1)
{
Lots = EntryPrice - StopLoss;					
}
				
else if (State == -1)
{
Lots = StopLoss - EntryPrice;					
}

Lots = Lots / _pip;
Lots = (Equity * Risk) / Lots;
Lots = Lots / 10.0;
}

//Calculate the lot size overload
public double LotSize(double _equity, double _entryPrice,
double _stopLoss, double _pip)
{
double _lots = 0.0;

if (_entryPrice > _stopLoss)
{
_lots = _entryPrice - _stopLoss;
}

else if (_entryPrice < _stopLoss)
{
_lots = _stopLoss - _entryPrice;
}

_lots = _lots / _pip;
_lots = (_equity * Risk) / _lots;
_lots = _lots / 10.0;

return _lots;
}
#endregion

Calculation of lot size depends on how much risk you want to take. I would never trade with a risk higher than 2%. Risk management is very important for me. Lot size also depends on the stop loss size. If you have a big stop loss you would want to lower the risk by trading with lesser lots. On the other hand if you have a small lot size you can trade with a higher number of lots. Small stop loss needs a good trading strategy with a higher percentage of wins otherwise the stop loss will keep on getting hit a lot. So whatever trading strategy you develop you should first back test it thoroughly. Backtesting is no guarantee that the trading strategy will perform well while trading live but it can give you a rough idea whether it has the potential to make some money or not. Now that we have the trade open we need to update the trade on the close of each new bar.

#region Update Trade Agent State
public void UpdateTA(double _high, double _low, double _close, 
double _pip, int _profit) 
{
if (State == 1)
{
if (_low < StopLoss) { State = 0; //losing trade, stoploss hit 
Loss = (EntryPrice - StopLoss) / _pip;//Loss for this trade 
GrossLoss += Loss; 
NL++; 
Equity -= Loss * Lots * 10.0; 
CalculateDrawdown(); 
JournalEntry[5] = Equity; 
JournalEntry[6] = Loss; 
JournalEntry[7] = 0.0;//Profit is zero 
JournalEntry[8] = MaxEquity; 
JournalEntry[9] = Drawdown; 
Lots = 0; StopLoss = 0; 
EntryPrice = 0; Loss = 0; 
Profit = 0; 
Journal.Add(JournalEntry); 
} 
else 
{ 
Profit = (_close - EntryPrice) / _pip;//Profit for that trade 
if (Profit > _profit)
{
State = 0; //winning trade, take profit hit
GrossProfit += Profit;
NW++;
Equity += Profit * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = 0.0;//Loss is zero
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Loss = 0;
Profit = 0;
Journal.Add(JournalEntry);
}//End if
}//End else
}//End if State==1

else if (State == -1)
{
if (_high > StopLoss)
{
State = 0; //losing trade, stop loss hit
Loss = (StopLoss - EntryPrice) / _pip;//Loss for this trade
GrossLoss += Loss;
NL++;
Equity -= Loss * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = Loss;
JournalEntry[7] = 0.0;//Profit is zero
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Loss = 0;
Profit = 0;
Journal.Add(JournalEntry);
}

else
{
Profit = (EntryPrice - _close) / _pip;//Profit for that trade

if (Profit > _profit)
{
State = 0; //winning trade
GrossProfit += Profit;
NW++;
Equity += Profit * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = 0.0;//Loss is zero
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Loss = 0;
Profit = 0;
Journal.Add(JournalEntry);
}//End if

} //End else
}//End else if State==-1
			
}//End UpdateTAState


//UpdateTA Method Overloading
public void UpdateTA(double _high, double _low, double _close,
double _pip, int _profit, int k)
{
if (State == 1)
{
if (_low < StopLoss) { State = 0; //losing trade, stoploss hit 
Loss = (EntryPrice - StopLoss) / _pip;//Loss for this trade 
GrossLoss += Loss; 
NL++; 
Equity -= Loss * Lots * 10.0; 
CalculateDrawdown(); 
JournalEntry[5] = Equity; 
JournalEntry[6] = Loss; 
JournalEntry[7] = Profit; 
JournalEntry[8] = MaxEquity; 
JournalEntry[9] = Drawdown; 
Lots = 0; StopLoss = 0; 
EntryPrice = 0; 
Loss = 0; 
Journal.Add(JournalEntry); 
} 
else 
{ 
Profit = (_close - EntryPrice) / _pip;//Profit for that trade 
if (Profit > 50)						
{
TrailingStop(_high, _low, _pip, k);
if (_low < TSL) { State = 0; //trade closed, stoploss hit 
Profit = (TSL - EntryPrice) / _pip; 
GrossProfit += Profit; 
Equity += Profit * Lots * 10.0; 
CalculateDrawdown(); NW++; 
JournalEntry[5] = Equity; 
JournalEntry[6] = Loss; 
JournalEntry[7] = Profit; 
JournalEntry[8] = MaxEquity; 
JournalEntry[9] = Drawdown; 
Lots = 0; 
StopLoss = 0; 
EntryPrice = 0; 
Profit = 0; 
Loss = 0; 
Journal.Add(JournalEntry); 
} 
} 
else if (Profit > _profit)
{
State = 0; //winning trade, take profit hit
GrossProfit += Profit;
NW++;
Equity += Profit * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = Loss;
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Profit = 0;
Loss = 0;
Journal.Add(JournalEntry);
}
}//End if
}
else if (State == -1)
{
if (_high > StopLoss)
{
State = 0; //losing trade, stop loss hit
Loss = (StopLoss - EntryPrice) / _pip;//Loss for this trade
GrossLoss += Loss;
NL++;
Equity -= Loss * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = Loss;
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Loss = 0;
Journal.Add(JournalEntry);
}
else
{
Profit = (EntryPrice - _close) / _pip;//Profit for that trade

if (Profit > 50)
{
TrailingStop(_high, _low, _pip, k);
if (_high > TSL)
{
State = 0; //trade closed, stop loss hit
Profit= (EntryPrice - TSL) / _pip;
GrossProfit += Profit;
NW++;
Equity += Profit * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = Loss;
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Loss = 0;
Journal.Add(JournalEntry);
}
}

else if (Profit > _profit)
{
State = 0; //winning trade
GrossProfit += Profit;
NW++;
Equity += Profit * Lots * 10.0;
CalculateDrawdown();
JournalEntry[5] = Equity;
JournalEntry[6] = Loss;
JournalEntry[7] = Profit;
JournalEntry[8] = MaxEquity;
JournalEntry[9] = Drawdown;
Lots = 0;
StopLoss = 0;
EntryPrice = 0;
Profit = 0;
Loss = 0;
Journal.Add(JournalEntry);
}//End else if

}//End else
}//End else if state==-1
}//End method overloading


#endregion

How to calculate the Max Drawdown?

Update the trading agent method checks on the close of each bar if the stop loss got hit. If the stop loss got hit, the trade is closed and the loss which is the stop loss is recorded as well as the number of losing trades is incremented. UpdateTA method also check if the take profit target has been achieved. If the take profit target is hit, it also closes the trade, records a winning trade and the updates the gross profit and the profit for that trade. Below we code how to calculate the drawdown.

#region Calculate Strategy Drawdown
public void CalculateDrawdown() 
{ 
if(Equity > MaxEquity) MaxEquity = Equity;
Drawdown = MaxEquity - Equity;
if (Drawdown > MaxDrawdown) MaxDrawdown = Drawdown;				
}		
#endregion

Drawdown is the difference between the peak equity and the low equity. Drawdown is an important metric and we need to know the maximum drawdown that the trading strategy can suffer. The trading strategy that I had provided as an example  in the beginning of this post had a max drawdown of around $450. We had started with an account equity of $1000 and in two months the trading strategy suffered a drawdown of around $450 which is the difference between the two adjacent peak and valley on the equity curve.

How to code Trailing Stop Loss?

We can also code the trailing stop loss. Let’s do that. Trailing stop loss can help us optimize the trading strategy by making the take profit vary according to the price. This way we can extract as much as we can. Let’s code the trailing stop loss.

#region Trailing Stop
//Breakeven Trailing Stop Loss
public void TrailingStop() 
{
if (Profit > 50) TSL = EntryPrice;			
			
}

//Simple Trailing Stop Loss
public void TrailingStop(double _high, double _low, 
double _pip, int n) 
{				
if (Profit > n)
{
if (State == 1 && StopLoss < (_low - n* _pip)) 
{ TSL = _low - n * _pip; } 
else if (State == -1 && StopLoss > (_high + n * _pip))
{
TSL = _high + n * _pip;
}
}						
}

//Moving Average Trailing Stop Loss
public void TrailingStop(double _sma)
{
if (Profit > 50)
{
if (State == 1 && StopLoss < _sma) { TSL = _sma; } 
else if (State == -1 && StopLoss > _sma)
{
TSL = _sma;
}
}
}
#endregion

As you can see I have provided two types  of trailing stop loss. One is the breakeven stop loss and the other is the moving average stop loss. Breakeven stop loss just moves the stop loss to breakeven when we have a 50 pip profit. Moving average stop loss keeps on moving the stop loss as long as the price stays above or below the moving average. When the the price crosses the moving average it will hit the stop loss and we will have our take profit. We don’t don’t know what it will be but the trade will close in profit. If the price is volatile we can hit the stop loss early and later the price continues to move in the direction of the trade. We have no way to avoid that.

How to write the Trading Agent data to CSV?

If you want to write the trading agent each trade data to a csv we can also do that. I have also coded that thing below:

#region Write to text file
public string TextFileWrite()

return EntryPrice + "," + StopLoss + "," + Profit + "," + Loss + "," +
GrossProfit + "," + NW + "," + GrossLoss + "," + NL + "," +
Equity + "," + NB + "," + Lots + "," + NS + "," +
MaxEquity + "," + MaxDrawdown;

}

#endregion

I had used python pandas to read the trading strategy csv files and plot the graphs in the beginning of this post.

Monte Carlo Simulation of the Trading Strategy

Monte Carlo Simulation is done by Quants to determine how much robust the trading strategy is. We simply permute the order of the trades made by the trading agent and recalculate the equity, drawdown and the stuff like that. This is known as Monte Carlo Simulation. Monte Carlo Simulation is done to check if we reorder the trades what is the trading strategy performance.

#region Monte Carlo Testing 
public double[][] MonteCarlo(double equity, double _pip)
{				
var _mc = new double[Journal.Count][];				
var _numbers = new List();

Random random = new Random();

int k = 0;
int _randNum = 0;
double _equity = equity;
double _maxEquity = _equity;
double _drawdown = 0;

do
{
_randNum = random.Next(0, Journal.Count - 1);

if (!_numbers.Contains(_randNum))
{
k++;
_numbers.Add(_randNum);
_mc[k] = new double[10];
_mc[k] = Journal[_randNum];
//Recalculate lot size	
_mc[k][ 4] = LotSize(_equity, _mc[k][2], _mc[k][3], _pip);

if (_mc[k][7] != 0)
{
_equity += _mc[k][7] * _mc[k][4] * 10;//Recalculate Equity
_mc[k][5] = _equity;
//calculate Max Equity and Drawdown
if (_equity > _maxEquity)
{
_maxEquity = _equity;
_mc[k][8] = _maxEquity;
}
_drawdown=_maxEquity-_equity;
_mc[k][9] = _drawdown;
							
}
else if (_mc[k][6] != 0)
{
_equity -= _mc[k][6] * _mc[k][4] * 10;//Recalculate Equity
_mc[k][5] -= _equity;
//calculate Max Equity and Drawdown
if (_equity > _maxEquity)
{
_maxEquity = _equity;
_mc[k][8] = _maxEquity;
}
_drawdown = _maxEquity - _equity;
_mc[k][9] = _drawdown;
}
}//End do loop
} while (k < Journal.Count);			
return _mc;
}

//Monte Carlo Simulation of the Trading Agent
public void MCSimulation(double _equity, double _pip, int _number) 
{
var _mcSimulation = new double[_number][][];
//iterate again and again
for (int k = 0; k < _number; k++) 
{ _mcSimulation[k] = new double[Journal.Count][]; //
_mcSimulation[k][i] = new double[10]; 
_mcSimulation[k] = MonteCarlo(_equity, _pip); }
 _mcSimulation.Max(); 
//Find the median 
_mcSimulation.OrderBy(x => x).Skip(
_mcSimulation.Count() / 2).First();
}
#endregion

As you can see our trading agent can do a lot of things.