Skip to content

User Code Sandbox Guide

What is This?

This is your sandbox for writing custom MT5 trading code. Connection setup is already done - you just add your trading logic!

Quick Start

  1. Uncomment the case block in Program.cs
  2. Open Program.cs (root folder)
  3. Find the USER CODE SANDBOX section (around line 172)
  4. Uncomment the case block for "usercode", "user", "sandbox"

  5. Open ProgramUserCode.cs

  6. Write your code or uncomment examples

  7. Run:

    dotnet run usercode
    

That's it! Your code will execute with full MT5 connection.

How to Use

Option 1: Uncomment Examples

The file contains 9 ready-to-use examples:

// Example 1: Get account information
// var accountInfo = await service.GetAccountInfoAsync();
// Console.WriteLine($"Balance: ${accountInfo.Balance}");

Just remove // to activate!

Option 2: Write Your Own Code

Add your logic between the markers:

// ═══════════════════════════════════════
// YOUR CODE STARTS HERE ↓
// ═══════════════════════════════════════

// Your trading strategy here...

// ═══════════════════════════════════════
// YOUR CODE ENDS HERE ↑
// ═══════════════════════════════════════

Available Commands

Run your code with any of these:

dotnet run usercode
dotnet run user
dotnet run sandbox

What's Already Set Up

Connection - MT5 Terminal connected via gRPC

Configuration - Loaded from appsettings.json

MT5Account - Low-level gRPC client (variable: account)

MT5Service - High-level wrapper with Sugar API (variable: service)

Can You Mix API Levels?

Yes! You can use all three levels in one file:

// Low-level (direct gRPC)
var positions = await account.PositionsGetAsync(new Empty());

// Mid-level (MT5Service)
var accountInfo = await service.GetAccountInfoAsync();

// High-level (Sugar API)
var result = await service.BuyMarketByRisk("EURUSD", 10.0, 20);

All three variables are available simultaneously: - account - for full control (gRPC) - service - for convenient methods (Service + Sugar)

Quick Reference

Get Account Info

var accountInfo = await service.GetAccountInfoAsync();
Console.WriteLine($"Balance: ${accountInfo.Balance}");
Console.WriteLine($"Equity: ${accountInfo.Equity}");

Get Current Price

var tick = await service.SymbolInfoTickAsync("EURUSD");
Console.WriteLine($"EURUSD Bid: {tick.Bid}, Ask: {tick.Ask}");

Open Market Order (Risk-Based)

var result = await service.BuyMarketByRisk(
    symbol: "EURUSD",
    riskAmount: 10.0,        // Risk $10
    stopLossPoints: 20       // SL 20 points away
);

if (result.ReturnedCode == 10009)
{
    Console.WriteLine($"✅ Order opened: #{result.Order}");
}
else
{
    Console.WriteLine($"❌ Failed: {result.ReturnedCodeDescription}");
}

Place Pending Order

var result = await service.BuyLimitPoints(
    symbol: "EURUSD",
    volume: 0.01,
    offsetPoints: 20,        // 20 points below Ask
    stopLossPoints: 15,
    takeProfitPoints: 30
);

Get Open Positions

var positions = await account.PositionsGetAsync(new Empty());
Console.WriteLine($"Open positions: {positions.Data.Positions.Count}");

foreach (var pos in positions.Data.Positions)
{
    Console.WriteLine($"  #{pos.Ticket} {pos.Symbol} {pos.Type} {pos.Volume} lots");
}

Close All Positions

await service.CloseAll("EURUSD");

Return Codes (RetCodes)

Always check RetCode after trading operations!

if (result.ReturnedCode == 10009)  // Success for market orders
if (result.ReturnedCode == 10008)  // Success for pending orders

Complete list: ReturnCodes_Reference_EN.md

Documentation

Tips

  1. Start simple - Uncomment one example at a time
  2. Check RetCode - Always validate trading operations
  3. Use Sugar API - Methods like BuyMarketByRisk() are easier than low-level
  4. Test on demo - Make sure you're using a demo account first!
  5. Read docs - ReturnCodes_Reference_EN.md explains all error codes