Skip to content

HOW GridTradingOrchestrator WORKS - Detailed AnalysisΒΆ

🎯 Document Purpose¢

Show WHAT the orchestrator consists of and HOW EXACTLY it works at the code, methods and data level.


πŸ“¦ What the orchestrator is made ofΒΆ

1. Class structure (lines 13-28)ΒΆ

public class GridTradingOrchestrator
{
    // SINGLE DEPENDENCY
    private readonly MT5Service _service;

    // 7 CONFIGURABLE PARAMETERS
    public string Symbol { get; set; } = "EURUSD";
    public int GridLevels { get; set; } = 3;
    public int GridSpacingPoints { get; set; } = 20;
    public double VolumePerLevel { get; set; } = 0.01;
    public int StopLossPoints { get; set; } = 50;
    public int TakeProfitPoints { get; set; } = 30;
    public int MaxRunMinutes { get; set; } = 15;

    // DEPENDENCY INJECTION
    public GridTradingOrchestrator(MT5Service service)
    {
        _service = service;  // ← Get MT5Service from outside
    }
}

Dependency visualizationΒΆ

GridTradingOrchestrator
  Contains: private readonly MT5Service _service
    ↓
MT5Service
  Contains: private MT5Account _account
    ↓
MT5Account
  Contains: gRPC Client
    ↓
[MT5 Terminal]

πŸ”„ How ExecuteAsync() works - step by stepΒΆ

Phase 1: Initialization (lines 32-46)ΒΆ

public async Task<double> ExecuteAsync(CancellationToken ct = default)
{

    // β”‚  STEP 1: Output header                              
    // └─────────────────────────────
    Console.WriteLine("\n+============================================================+");
    Console.WriteLine("|  GRID TRADING ORCHESTRATOR                                |");
    Console.WriteLine("+============================================================+\n");


    // β”‚  STEP 2: Get initial balance                        
    // β”‚  Used: MT5Service.GetBalanceAsync()                 
    // β”‚  ↓ Calls: MT5Account.GetBalanceAsync()              
    // β”‚    ↓ Sends gRPC: GetAccountInfoRequest              
    // β”‚      ↓ Receives: AccountInfoData                    
    // β”‚        ↓ Returns: double balance                    
    // └────────────────────────────────────────────────
    var initialBalance = await _service.GetBalanceAsync();
    Console.WriteLine($"  Starting balance: ${initialBalance:F2}");


    // β”‚  STEP 3: Get current price                          
    // β”‚  Used: MT5Service.SymbolInfoTickAsync()             
    // β”‚  ↓ Calls: MT5Account.SymbolInfoTickAsync()          
    // β”‚    ↓ Sends gRPC: SymbolInfoTickRequest              
    // β”‚      ↓ Receives: SymbolInfoTickData                 
    // β”‚        ↓ Fields: Bid, Ask, Time, Volume             
    // └────────────────────────────────────────────────
    var tick = await _service.SymbolInfoTickAsync(Symbol);
    Console.WriteLine($"  Current: Bid={tick.Bid:F5}, Ask={tick.Ask:F5}\n");

    // β”‚  STEP 4: Create list to track orders                
    // └────────────────────────────────────────────────
    var placedOrders = new System.Collections.Generic.List<ulong>();
}

Phase 2: Placing Buy Limit grid (lines 50-73)ΒΆ

// β”‚  LOOP: Placing BUY LIMIT orders BELOW current price    
// └─────────────────────────────────────────────────────
Console.WriteLine($"  Placing {GridLevels} BUY LIMIT levels...");

for (int i = 1; i <= GridLevels; i++)  // i = 1, 2, 3
{
    // β”‚  Calculate offset in points                 
    // β”‚  IMPORTANT: NEGATIVE value!                 
    // └──────────────────────────────────────────
    var pointsBelow = -(i * GridSpacingPoints);

    // Examples with GridSpacingPoints = 20:
    // i=1 β†’ pointsBelow = -(1 Γ— 20) = -20
    // i=2 β†’ pointsBelow = -(2 Γ— 20) = -40
    // i=3 β†’ pointsBelow = -(3 Γ— 20) = -60

    // β”‚  Call MT5Sugar Extension Method             
    // └──────────────────────────────────────────
    var result = await _service.BuyLimitPoints(
        symbol: Symbol,                    // "EURUSD"
        volume: VolumePerLevel,            // 0.01
        priceOffsetPoints: pointsBelow,    // -20, -40, -60
        slPoints: StopLossPoints,          // 50
        tpPoints: TakeProfitPoints,        // 30
        comment: $"Grid-Buy-{i}"           // "Grid-Buy-1"
    );

    // β”‚  Check result                               
    // └──────────────────────────────────────────
    if (result.ReturnedCode == 10009)  // 10009 = TRADE_RETCODE_DONE
    {
        placedOrders.Add(result.Order);  // Save ticket
        Console.WriteLine($"    βœ“ Level {i}: #{result.Order} ({pointsBelow} pts below)");
    }
    else
    {
        Console.WriteLine($"    βœ— Level {i} failed: {result.Comment}");
    }
}

How BuyLimitPoints() works - inside MT5SugarΒΆ

// MT5Sugar.cs (extension method)
public static async Task<OrderSendData> BuyLimitPoints(
    this MT5Service service,
    string symbol,
    double volume,
    int priceOffsetPoints,  // ← RECEIVES -20
    int slPoints = 0,
    int tpPoints = 0,
    string comment = ""
)
{
    // β”‚  STEP 1: Get current Ask price                      
    // └──────────────────────────────────────────

    var tick = await service.SymbolInfoTickAsync(symbol);
    double askPrice = tick.Ask;  // For example: 1.10002

    // β”‚  STEP 2: Get point size for symbol                  
    // └──────────────────────────────────────────
    var symbolInfo = await service.SymbolInfoAsync(symbol);
    double point = symbolInfo.Point;  // For EURUSD: 0.00001

    // β”‚  STEP 3: Calculate order placement price            
    // β”‚  priceOffsetPoints = -20                            
    // β”‚  askPrice = 1.10002                                 
    // β”‚  point = 0.00001                                    
    // β”‚  price = 1.10002 + (-20 Γ— 0.00001)                  
    // β”‚       = 1.10002 - 0.00020                           
    // β”‚       = 1.09982                                     
    // └─────────────────────────────────────────────────────
    double price = askPrice + (priceOffsetPoints * point);

    // β”‚  STEP 4: Calculate SL and TP                        
    // β”‚  slPoints = 50                                      
    // β”‚  sl = 1.09982 - (50 Γ— 0.00001) = 1.09932            
    // β”‚  tpPoints = 30                                      
    // β”‚  tp = 1.09982 + (30 Γ— 0.00001) = 1.10012            
    // └─────────────────────────────────────────────────────
    double sl = slPoints > 0 ? price - (slPoints * point) : 0;
    double tp = tpPoints > 0 ? price + (tpPoints * point) : 0;

    // β”‚  STEP 5: Call low-level method MT5Service          
    // └─────────────────────────────────────────────────────
    return await service.BuyLimitAsync(
        symbol: symbol,      // "EURUSD"
        volume: volume,      // 0.01
        price: price,        // 1.09982
        sl: sl,              // 1.09932
        tp: tp,              // 1.10012
        comment: comment     // "Grid-Buy-1"
    );
}

Phase 3: Placing Sell Limit grid (lines 77-100)ΒΆ

// β”‚  LOOP: Placing SELL LIMIT orders ABOVE current price   
// └─────────────────────────────────────────────────────────
Console.WriteLine($"  Placing {GridLevels} SELL LIMIT levels...");

for (int i = 1; i <= GridLevels; i++)
{
    // β”‚  Calculate offset in points                 
    // β”‚  IMPORTANT: POSITIVE value!                 
    // └─────────────────────────────────────────────
    var pointsAbove = i * GridSpacingPoints;

    // Examples with GridSpacingPoints = 20:
    // i=1 β†’ pointsAbove = 1 Γ— 20 = +20
    // i=2 β†’ pointsAbove = 2 Γ— 20 = +40
    // i=3 β†’ pointsAbove = 3 Γ— 20 = +60

    var result = await _service.SellLimitPoints(
        symbol: Symbol,
        volume: VolumePerLevel,
        priceOffsetPoints: pointsAbove,    // +20, +40, +60
        slPoints: StopLossPoints,
        tpPoints: TakeProfitPoints,
        comment: $"Grid-Sell-{i}"
    );

    if (result.ReturnedCode == 10009)
    {
        placedOrders.Add(result.Order);
        Console.WriteLine($"    βœ“ Level {i}: #{result.Order} ({pointsAbove} pts above)");
    }
}

How SellLimitPoints() worksΒΆ

// MT5Sugar.cs (extension method)
public static async Task<OrderSendData> SellLimitPoints(
    this MT5Service service,
    string symbol,
    double volume,
    int priceOffsetPoints,  // ← RECEIVES +20
    int slPoints = 0,
    int tpPoints = 0,
    string comment = ""
)
{
    var tick = await service.SymbolInfoTickAsync(symbol);
    double bidPrice = tick.Bid;  // ← FOR SELL use BID, not Ask!

    var symbolInfo = await service.SymbolInfoAsync(symbol);
    double point = symbolInfo.Point;

    // β”‚  For SELL: placement price = Bid + offset           
    // β”‚  priceOffsetPoints = +20                            
    // β”‚  bidPrice = 1.10000                                 
    // β”‚  price = 1.10000 + (20 Γ— 0.00001) = 1.10020         
    // └─────────────────────────────────────────────────────
    double price = bidPrice + (priceOffsetPoints * point);

    // β”‚  For SELL: SL ABOVE entry price (protection)        
    // β”‚  sl = 1.10020 + (50 Γ— 0.00001) = 1.10070            
    // β”‚  For SELL: TP BELOW entry price (profit taking)     
    // β”‚  tp = 1.10020 - (30 Γ— 0.00001) = 1.09990            
    // └─────────────────────────────────────────────────────
    double sl = slPoints > 0 ? price + (slPoints * point) : 0;  // + for SELL
    double tp = tpPoints > 0 ? price - (tpPoints * point) : 0;  // - for SELL

    return await service.SellLimitAsync(
        symbol: symbol,
        volume: volume,
        price: price,    // 1.10020
        sl: sl,          // 1.10070
        tp: tp,          // 1.09990
        comment: comment
    );
}

Result of placing gridΒΆ

After both loops in MT5 Terminal:

PENDING ORDERS (6 orders):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Ticket β”‚    Type     β”‚  Price  β”‚   SL    β”‚   TP    β”‚ Comment β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ ...789 β”‚ BUY LIMIT   β”‚ 1.09982 β”‚ 1.09932 β”‚ 1.10012 β”‚ Grid-B-1β”‚
β”‚ ...790 β”‚ BUY LIMIT   β”‚ 1.09962 β”‚ 1.09912 β”‚ 1.09992 β”‚ Grid-B-2β”‚
β”‚ ...791 β”‚ BUY LIMIT   β”‚ 1.09942 β”‚ 1.09892 β”‚ 1.09972 β”‚ Grid-B-3β”‚
β”‚ ...792 β”‚ SELL LIMIT  β”‚ 1.10020 β”‚ 1.10070 β”‚ 1.09990 β”‚ Grid-S-1β”‚
β”‚ ...793 β”‚ SELL LIMIT  β”‚ 1.10040 β”‚ 1.10090 β”‚ 1.10010 β”‚ Grid-S-2β”‚
β”‚ ...794 β”‚ SELL LIMIT  β”‚ 1.10060 β”‚ 1.10110 β”‚ 1.10030 β”‚ Grid-S-3β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

placedOrders = [789, 790, 791, 792, 793, 794]

Phase 4: Monitoring (lines 105-114)ΒΆ

Console.WriteLine($"\n  βœ“ Grid placed: {placedOrders.Count} pending orders");
Console.WriteLine($"  ⏳ Running for {MaxRunMinutes} minutes...\n");

// β”‚  Calculate end time                                     
// β”‚  MaxRunMinutes = 15                                     
// β”‚  endTime = 12:00 + 15 min = 12:15                       
// └─────────────────────────────────────────────────────────
var endTime = DateTime.UtcNow.AddMinutes(MaxRunMinutes);


// β”‚  MONITORING LOOP: runs until time expires               
// β”‚  or CancellationToken triggers                          
// └─────────────────────────────────────────────────────────
while (DateTime.UtcNow < endTime && !ct.IsCancellationRequested)
{

    // β”‚  Wait 5 seconds                                 
    // └─────────────────────────────────────────────────
    await Task.Delay(5000, ct);


    // β”‚  Get current balance                            
    // └─────────────────────────────────────────────────
    var currentBalance = await _service.GetBalanceAsync();


    // β”‚  Calculate profit/loss                          
    // β”‚  initialBalance = 10000.00                      
    // β”‚  currentBalance = 10012.50                      
    // β”‚  currentProfit = 10012.50 - 10000.00 = +12.50   
    // └─────────────────────────────────────────────────
    var currentProfit = currentBalance - initialBalance;

    Console.WriteLine($"  Current P/L: ${currentProfit:F2}");
}

What happens during monitoringΒΆ

TIME      ACTION                           BALANCE    P/L
────────  ───────────────────────────────  ─────────  ─────
12:00:00  Grid placed                      10000.00   0.00
12:00:05  Waiting...                       10000.00   0.00
12:00:10  Waiting...                       10000.00   0.00
12:00:15  Price 1.09980 β†’ BUY-1 triggered  10000.00   0.00
12:00:20  Position opened                  10000.00   0.00
12:00:25  Price 1.09995                    10001.50  +1.50
12:00:30  Price 1.10010 β†’ TP triggered     10003.00  +3.00
12:00:35  Position closed                  10003.00  +3.00
...
12:15:00  Time expired β†’ exit loop         10012.50 +12.50

Phase 5: Closing (lines 117-128)ΒΆ

// β”‚  Time expired - close all remaining orders              
// └─────────────────────────────────────────────────────────
Console.WriteLine("\n  ⏱ Time expired - closing all remaining orders...");


// β”‚  Call MT5Sugar extension method: CloseAll()            
// └─────────────────────────────────────────────────────────
await _service.CloseAll(Symbol);

Console.WriteLine("  βœ“ All closed");


// β”‚  Get final balance                                      
// └─────────────────────────────────────────────────────────
var finalBalance = await _service.GetBalanceAsync();


// β”‚  Calculate total profit                                 
// └─────────────────────────────────────────────────────────
var profit = finalBalance - initialBalance;

Console.WriteLine($"\n  Final balance: ${finalBalance:F2}");
Console.WriteLine($"  Total Profit/Loss: ${profit:F2}");


// β”‚  Return profit as result of ExecuteAsync()              
// └─────────────────────────────────────────────────────────
return profit;

How CloseAll() worksΒΆ

// MT5Sugar.cs (extension method)
public static async Task CloseAll(
    this MT5Service service,
    string symbol
)
{

    // β”‚  STEP 1: Get all open positions                     
    // └─────────────────────────────────────────────────────
    var positions = await service.PositionsAsync(symbol);

    foreach (var position in positions)
    {
        // Close each position individually
        await service.PositionCloseAsync(position.Ticket);
    }


    // β”‚  STEP 2: Get all pending orders                     
    // └─────────────────────────────────────────────────────
    var orders = await service.OrdersAsync(symbol);

    foreach (var order in orders)
    {
        // Cancel each pending order
        await service.OrderDeleteAsync(order.Ticket);
    }
}

🎭 Complete Life Cycle¢

Execution timelineΒΆ

T=0      START ExecuteAsync()
         β”‚
         β”œβ”€β–Ί GetBalanceAsync()           β†’ 10000.00
         β”œβ”€β–Ί SymbolInfoTickAsync()       β†’ Bid:1.10000, Ask:1.10002
         β”‚
T=1s     β”œβ”€β–Ί LOOP 1: BuyLimitPoints (i=1)
         β”‚   └─► Order 789: BUY LIMIT @ 1.09982
         β”‚
T=2s     β”œβ”€β–Ί LOOP 1: BuyLimitPoints (i=2)
         β”‚   └─► Order 790: BUY LIMIT @ 1.09962
         β”‚
T=3s     β”œβ”€β–Ί LOOP 1: BuyLimitPoints (i=3)
         β”‚   └─► Order 791: BUY LIMIT @ 1.09942
         β”‚
T=4s     β”œβ”€β–Ί LOOP 2: SellLimitPoints (i=1)
         β”‚   └─► Order 792: SELL LIMIT @ 1.10020
         β”‚
T=5s     β”œβ”€β–Ί LOOP 2: SellLimitPoints (i=2)
         β”‚   └─► Order 793: SELL LIMIT @ 1.10040
         β”‚
T=6s     β”œβ”€β–Ί LOOP 2: SellLimitPoints (i=3)
         β”‚   └─► Order 794: SELL LIMIT @ 1.10060
         β”‚
T=7s     β”œβ”€β–Ί MONITORING START
         β”‚   endTime = DateTime.Now + 15 minutes
         β”‚
T=12s    β”œβ”€β–Ί Task.Delay(5000) β†’ output P/L: $0.00
T=17s    β”œβ”€β–Ί Task.Delay(5000) β†’ output P/L: $0.00
T=22s    β”œβ”€β–Ί Task.Delay(5000) β†’ output P/L: $1.50
         β”‚   (Market moved, position opened)
         ...
         ...
T=15min  β”œβ”€β–Ί MONITORING END (time expired)
         β”‚
         β”œβ”€β–Ί CloseAll("EURUSD")
         β”‚   β”œβ”€β–Ί Closed positions: 2
         β”‚   └─► Canceled orders: 4
         β”‚
         β”œβ”€β–Ί GetBalanceAsync()           β†’ 10012.50
         β”œβ”€β–Ί profit = 10012.50 - 10000.00 = +12.50
         β”‚
         └─► RETURN profit = 12.50

πŸ“Š What the result is made ofΒΆ

Profit calculationΒΆ

INITIAL BALANCE: $10000.00

TRIGGERED ORDERS:

1. Order 789: BUY LIMIT @ 1.09982
   β†’ Price fell to 1.09980 β†’ opened position BUY
   β†’ Price rose to 1.10012 β†’ TP triggered
   β†’ Profit: (1.10012 - 1.09982) Γ— 100000 Γ— 0.01 = +$3.00

2. Order 792: SELL LIMIT @ 1.10020
   β†’ Price rose to 1.10022 β†’ opened position SELL
   β†’ Price fell to 1.09990 β†’ TP triggered
   β†’ Profit: (1.10020 - 1.09990) Γ— 100000 Γ— 0.01 = +$3.00

NOT TRIGGERED (canceled at CloseAll):
- Order 790: BUY LIMIT @ 1.09962
- Order 791: BUY LIMIT @ 1.09942
- Order 793: SELL LIMIT @ 1.10040
- Order 794: SELL LIMIT @ 1.10060

FINAL RESULT:
- Profit from positions: $3.00 + $3.00 = $6.00
- Commissions/swap: -$0.50
- FINAL BALANCE: $10005.50
- PROFIT = $5.50

return 5.50;

🧩 Components and their roles¢

1. GridTradingOrchestratorΒΆ

Role: Strategy coordinator

Tasks:

  • Stores parameters (Symbol, GridLevels, etc.)
  • Manages life cycle
  • Calls MT5Service methods
  • Handles errors
  • Returns result

2. MT5ServiceΒΆ

Role: Service layer

Tasks:

  • Provides high-level methods
  • Delegates calls to MT5Account
  • Contains no business logic

3. MT5Sugar (extension methods)ΒΆ

Role: Simplifying layer

Tasks:

  • Converts points to prices
  • Calculates SL/TP
  • Makes API convenient
  • Reduces code amount

4. MT5AccountΒΆ

Role: gRPC client

Tasks:

  • Direct communication with MT5 Terminal
  • Serialization/deserialization
  • Connection management

5. MT5 TerminalΒΆ

Role: Executor

Tasks:

  • Places orders on market
  • Monitors execution
  • Manages positions

πŸ” Final Dependency DiagramΒΆ

β”‚  USER CODE                                                  
β”‚  var orchestrator = new GridTradingOrchestrator(service);   
β”‚  var profit = await orchestrator.ExecuteAsync();            
└──────────────────────────┬──────────────────────────────────
                           β”‚
                           β–Ό

β”‚  GridTradingOrchestrator                                    
β”‚    
β”‚  β”‚  - Symbol, GridLevels, GridSpacingPoints, ...           
β”‚  β”‚  - ExecuteAsync()                                       
β”‚  └───────────────────────────────────────────────────────  
└──────────────────────────┬──────────────────────────────────
                           β”‚ _service
                           β–Ό

β”‚  MT5Service                                                 
β”‚   
β”‚  β”‚  Methods:                                               
β”‚  β”‚  - GetBalanceAsync()                                    
β”‚  β”‚  - SymbolInfoTickAsync()                                
β”‚  β”‚  - BuyLimitAsync()                                      
β”‚  β”‚  - SellLimitAsync()                                     
β”‚  β”‚  - PositionCloseAsync()                                 
β”‚  └───────────────────────────────────────────────────────  
└──────────────────────────┬──────────────────────────────────
                           β”‚ _account
                           β–Ό

β”‚  MT5Account                                                 
β”‚    
β”‚  β”‚  gRPC Client:                                           
β”‚  β”‚  - OrderSendAsync(OrderSendRequest)                     
β”‚  β”‚  - GetAccountInfoAsync(GetAccountInfoRequest)           
β”‚  β”‚  - SymbolInfoTickAsync(SymbolInfoTickRequest)           
β”‚  └───────────────────────────────────────────────────────  
└──────────────────────────┬──────────────────────────────────
                           β”‚ gRPC
                           β–Ό

                    β”‚ MT5 Terminal 
                    └──────────────


β”‚  MT5Sugar (static extension methods)                        
β”‚    
β”‚  β”‚  Extension Methods on MT5Service:                       
β”‚  β”‚  - BuyLimitPoints(priceOffsetPoints, slPoints, ...)     
β”‚  β”‚  - SellLimitPoints(priceOffsetPoints, tpPoints, ...)    
β”‚  β”‚  - CloseAll(symbol)                                     
β”‚  β”‚  - BuyMarketByRisk(riskMoney, stopPoints, ...)          
β”‚  β”‚                                                         
β”‚  β”‚  Role: Convert points β†’ prices                          
β”‚  └───────────────────────────────────────────────────────  
└─────────────────────────────────────────────────────────────
         β”‚                          β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚ Calls low-level methods
                    β–Ό
              [MT5Service methods]

🎯 Summary¢

GridTradingOrchestrator is made of:

  1. 1 dependency: MT5Service _service (via DI)
  2. 7 parameters: Symbol, GridLevels, GridSpacingPoints, Volume, SL, TP, MaxRunMinutes
  3. 3 MT5Sugar methods: BuyLimitPoints, SellLimitPoints, CloseAll
  4. 5 MT5Service methods: GetBalanceAsync, SymbolInfoTickAsync, BuyLimitAsync, SellLimitAsync, PositionsAsync
  5. gRPC protocol: Communication with MT5 Terminal

Works through:

  • 2 loops for placing orders (Buy + Sell)
  • 1 monitoring loop with Task.Delay(5000)
  • 1 final close of all orders
  • Error handling via try-catch

Returns:

  • double profit - difference between final and initial balance