/* MTP Auto-Sync — cTrader cBot ───────────────────────────── Writes every CLOSED position to your My Trader Pro journal automatically — entry, exit, stop, target, volume and P&L, marked broker-verified. INSTALL (3 minutes) 1. cTrader → Automate (cBots) → New → paste this entire file → Build. 2. Portal → Signals & Sync → copy your MTP sync key. 3. Add the cBot to any chart, paste the key into its "MTP Sync Key" parameter, press Play. Leave it running — one chart is enough for the whole account. The cBot only PUSHES closed trades out. It cannot read your password, place orders, or receive anything back. Nothing but the trade rows and your key ever leave the terminal. */ using System; using System.Net.Http; using System.Text; using cAlgo.API; namespace MTP { [Robot(AccessRights = AccessRights.FullAccess, TimeZone = TimeZones.UTC)] public class MTPAutoSync : Robot { [Parameter("MTP Sync Key", DefaultValue = "PASTE_YOUR_KEY_HERE")] public string SyncKey { get; set; } [Parameter("Endpoint", DefaultValue = "https://mytraderpro.com/wp-json/mtp/v1/ingest")] public string Endpoint { get; set; } private static readonly HttpClient Http = new HttpClient(); protected override void OnStart() { Positions.Closed += OnPositionClosed; Ping(); Print("MTP Auto-Sync armed — closed trades now write themselves to your journal."); } private void Ping() { var json = "{\"key\":\"" + Esc(SyncKey) + "\",\"platform\":\"ctrader\",\"account\":\"" + Esc(Account.Number.ToString()) + "\",\"ping\":true}"; Post(json); } private void OnPositionClosed(PositionClosedEventArgs args) { var p = args.Position; var h = History.FindLast(p.Label, p.SymbolName, p.TradeType); double exitPx = h != null ? h.ClosingPrice : Symbol.Bid; long openUtc = ToUnix(p.EntryTime); long closeUtc = ToUnix(Server.Time); var sb = new StringBuilder(); sb.Append("{\"key\":\"").Append(Esc(SyncKey)).Append("\",") .Append("\"platform\":\"ctrader\",") .Append("\"account\":\"").Append(Esc(Account.Number.ToString())).Append("\",") .Append("\"trades\":[{") .Append("\"ticket\":\"ct-").Append(p.Id).Append("\",") .Append("\"symbol\":\"").Append(Esc(p.SymbolName)).Append("\",") .Append("\"direction\":\"").Append(p.TradeType == TradeType.Buy ? "buy" : "sell").Append("\",") .Append("\"lots\":").Append((p.VolumeInUnits / 100000.0).ToString("0.#####", System.Globalization.CultureInfo.InvariantCulture)).Append(",") .Append("\"entry\":").Append(Num(p.EntryPrice)).Append(",") .Append("\"exit\":").Append(Num(exitPx)).Append(",") .Append("\"sl\":").Append(Num(p.StopLoss ?? 0)).Append(",") .Append("\"tp\":").Append(Num(p.TakeProfit ?? 0)).Append(",") .Append("\"profit\":").Append(Num(p.NetProfit)).Append(",") .Append("\"openTime\":\"").Append(p.EntryTime.ToString("yyyy-MM-dd HH:mm:ss")).Append("\",") .Append("\"openUtc\":").Append(openUtc).Append(",") .Append("\"closeUtc\":").Append(closeUtc).Append(",") .Append("\"source\":\"Auto-Sync cTrader\"") .Append("}]}"); Post(sb.ToString()); } private void Post(string json) { try { var content = new StringContent(json, Encoding.UTF8, "application/json"); var r = Http.PostAsync(Endpoint, content).Result; Print("MTP sync → " + (int)r.StatusCode + " " + r.ReasonPhrase); } catch (Exception ex) { Print("MTP sync error: " + ex.Message); } } private static string Num(double v) { return v.ToString("0.#####", System.Globalization.CultureInfo.InvariantCulture); } private static string Esc(string s) { return (s ?? "").Replace("\\", "\\\\").Replace("\"", "\\\""); } private static long ToUnix(DateTime dt) { return (long)(dt.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; } } }