Cara Kirim Emoticon dari EA MQL5 ke Telegram
Cara Mengirim Emoji/Emoticon dari EA MQL5 ke Telegram yang Benar (Terbukti Berhasil)
Solusi tuntas untuk masalah emoji muncul sebagai ??
atau \U0001F916
saat dikirim dari Expert Advisor MetaTrader 5 ke bot Telegram.
Jika Anda pernah mencoba mengirim notifikasi dari Expert Advisor (EA) MetaTrader 5 ke Telegram dengan emoji cantik seperti π€, π, atau π — dan hasilnya malah muncul karakter aneh seperti ?? atau bahkan teks literal \U0001F916 — Anda tidak sendirian. Ini adalah masalah encoding yang sangat umum di komunitas trader MQL5.
Artikel ini menjelaskan mengapa hal itu terjadi, pendekatan yang gagal, dan satu-satunya teknik yang terbukti bekerja: URL-encode emoji sebagai %F0%9F...
Mengapa Emoji Rusak di MQL5?
Masalah ini berakar dari perbedaan cara MQL5 dan protokol HTTP menangani karakter Unicode:
Setiap karakter di dalam string MQL5 disimpan dalam format UTF-16 internal. Emoji seperti π€ (U+1F916) memerlukan dua unit 16-bit (surrogate pair).
Fungsi bawaan MQL5 ini mengkonversi string ke byte array, namun hanya untuk
karakter ASCII/Latin-1 (0–255). Karakter di luar range ini dipotong menjadi ?.
Berbeda dengan C++ atau Python, penulisan "\U0001F916" dalam MQL5
tidak diinterpretasi sebagai karakter emoji — string tersebut dikirim mentah-mentah
sebagai 10 karakter teks biasa.
\U escape,
atau JSON body dengan emoji — selama melewati StringToCharArray(),
hasilnya tetap rusak di Telegram.
Perbandingan Metode yang Gagal vs yang Berhasil
| Metode | Contoh Kode | Hasil di Telegram |
|---|---|---|
| Emoji literal di string | string msg = "π€ Hello"; |
GAGAL — muncul ?? |
| Unicode escape \U | string e = "\U0001F916"; |
GAGAL — teks literal \U0001F916 |
| JSON body + Content-Type: application/json | headers = "Content-Type: application/json";body dengan emoji |
GAGAL — masih lewat StringToCharArray |
| URL-encode %XX (pre-encoded) | string e = "%F0%9F%A4%96"; |
BERHASIL ✓ — π€ tampil sempurna |
Teknik yang Benar: URL-Encode Emoji sebagai %XX
Kunci solusinya sederhana: karena StringToCharArray() aman untuk karakter ASCII,
kita konversi emoji ke representasi ASCII-nya terlebih dahulu dalam format URL-encode
(%F0%9F%A4%96 untuk π€). String yang dikirim sepenuhnya ASCII,
sehingga tidak ada yang rusak — dan Telegram otomatis men-decode %XX
menjadi emoji yang benar.
%F0%9F... langsung di string.Nilai dinamis (waktu, harga, nama simbol) → lewatkan fungsi
UrlEncodeValue()
sebelum di-concat ke pesan.
Referensi Cepat: Kode Emoji yang Sering Dipakai Trader
Kode Lengkap: EA Testing Emoticon Telegram
Berikut adalah kode EA MQL5 lengkap yang mendemonstrasikan teknik URL-encode emoji. EA ini mengirim notifikasi ke Telegram setiap awal candle baru, menampilkan informasi OHLC dengan emoji yang tampil sempurna.
BotToken dan ChatID dengan milik Anda sendiri.
Pastikan URL api.telegram.org sudah ditambahkan di
Tools → Options → Expert Advisors → Allow WebRequest di MetaTrader 5.
//+------------------------------------------------------------------+ //| Emoticon Telegram.mq5 | //| TESTING EMOTICON - URL ENCODED EMOJI | //| Copyright 7 Mei 2026, ARMAILA.com. | //+------------------------------------------------------------------+ #property copyright "Copyright 7 Mei 2026, ARMAILA.com." #property link "https://www.armaila.com" #property version "1.00" input string BotToken = "ISI_BOT_TOKEN_ANDA"; input string ChatID = "ISI_CHAT_ID_ANDA"; datetime lastCandleTime = 0; // ───────────────────────────────────────────────────────────────── // UrlEncodeValue: encode nilai dinamis (waktu, harga, nama simbol) // Karakter aman: A-Z a-z 0-9 - _ . ~ → langsung pakai // Spasi → + // Lainnya → %XX (hex) // ───────────────────────────────────────────────────────────────── string UrlEncodeValue(string s) { string result = ""; int len = StringLen(s); for(int i = 0; i < len; i++) { ushort c = StringGetCharacter(s, i); if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') result += ShortToString(c); else if(c == ' ') result += "+"; else { string hex = StringFormat("%%%02X", c); result += hex; } } return result; } // ───────────────────────────────────────────────────────────────── // SendToTelegram: kirim pesan yang sudah di-encode ke Telegram Bot // Pesan harus berupa string URL-encoded (seluruhnya ASCII) // ───────────────────────────────────────────────────────────────── bool SendToTelegram(string encodedText) { string url = "https://api.telegram.org/bot" + BotToken + "/sendMessage"; string params = "chat_id=" + ChatID + "&text=" + encodedText; char postData[]; char result[]; string resultHeaders; StringToCharArray(params, postData, 0, StringLen(params)); int res = WebRequest( "POST", url, "Content-Type: application/x-www-form-urlencoded\r\n", 5000, postData, result, resultHeaders ); string resp = CharArrayToString(result); Print("HTTP: ", res, " | ", resp); return (res == 200); } // ───────────────────────────────────────────────────────────────── // BuildEncoded: bangun pesan lengkap dengan emoji dan data candle // // Emoji pre-encoded (hardcode sebagai %XX): // π€ = %F0%9F%A4%96 π = %F0%9F%93%85 π° = %F0%9F%92%B0 // π = %F0%9F%9B%91 π = %F0%9F%9A%80 π = %F0%9F%93%88 // π = %F0%9F%93%89 π’ = %F0%9F%9F%A2 π΄ = %F0%9F%94%B4 // π’ = %F0%9F%93%A2 π‘️ = %F0%9F%9B%A1%EF%B8%8F // ─ = %E2%94%80 \n = %0A // // Nilai dinamis (waktu, harga) di-encode via UrlEncodeValue() // ───────────────────────────────────────────────────────────────── string BuildEncoded(bool isBullish, string waktu, string harga, string high, string low) { string wEnc = UrlEncodeValue(waktu); string hEnc = UrlEncodeValue(harga); string hiEnc = UrlEncodeValue(high); string loEnc = UrlEncodeValue(low); string line = "%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80" "%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80" "%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80"; string nl = "%0A"; string sp = "%20"; // Header: identitas + waktu + harga string header = "%F0%9F%A4%96" + sp + UrlEncodeValue(Symbol()) + sp + UrlEncodeValue(EnumToString(Period())) + sp + "INFO" + sp + "CANDLE" + sp + "%F0%9F%A4%96" + nl + "%F0%9F%93%85" + sp + "Waktu%3A" + sp + wEnc + nl + "%F0%9F%92%B0" + sp + "Harga" + sp + "Close%3A" + sp + hEnc + nl + line + nl; // Body: arah candle bullish atau bearish string body = ""; if(isBullish) body = "%F0%9F%9B%91" + sp + "MODE" + sp + "SELL" + sp + "BERAKHIR%21" + nl + "%F0%9F%9A%80" + sp + "MODE" + sp + "BUY" + sp + "DIMULAI" + nl + line + nl + "%F0%9F%93%88" + sp + "Candle%3A" + sp + "%F0%9F%9F%A2" + sp + "BULLISH" + nl + sp + sp + sp + "High" + sp + "%3A" + sp + hiEnc + nl + sp + sp + sp + "Low" + sp + sp + "%3A" + sp + loEnc + nl; else body = "%F0%9F%9A%80" + sp + "MODE" + sp + "BUY" + sp + "BERAKHIR%21" + nl + "%F0%9F%9B%91" + sp + "MODE" + sp + "SELL" + sp + "DIMULAI" + nl + line + nl + "%F0%9F%93%89" + sp + "Candle%3A" + sp + "%F0%9F%94%B4" + sp + "BEARISH" + nl + sp + sp + sp + "High" + sp + "%3A" + sp + hiEnc + nl + sp + sp + sp + "Low" + sp + sp + "%3A" + sp + loEnc + nl; // Footer: instruksi string footer = line + nl + "%F0%9F%93%A2" + sp + "Instruksi%3A" + sp + "Tetap" + sp + "disiplin" + sp + "dengan" + sp + "Money" + sp + "Management%2E" + sp + "%F0%9F%9B%A1%EF%B8%8F"; return header + body + footer; } // ───────────────────────────────────────────────────────────────── int OnInit() { string initMsg = "%F0%9F%A4%96%20EA%20AKTIF%20-%20TESTING%20EMOTICON%20%F0%9F%A4%96%0A" "%E2%9C%85%20Koneksi%20Telegram%20berhasil%21%0A" "%F0%9F%92%B9%20" + UrlEncodeValue(Symbol()); SendToTelegram(initMsg); return INIT_SUCCEEDED; } void OnTick() { datetime currentCandleTime = iTime(Symbol(), PERIOD_CURRENT, 0); if(currentCandleTime == lastCandleTime) return; lastCandleTime = currentCandleTime; double open1 = iOpen (Symbol(), PERIOD_CURRENT, 1); double close1 = iClose(Symbol(), PERIOD_CURRENT, 1); double high1 = iHigh (Symbol(), PERIOD_CURRENT, 1); double low1 = iLow (Symbol(), PERIOD_CURRENT, 1); if(open1 == 0 || close1 == 0) return; bool isBullish = (close1 >= open1); string waktu = TimeToString(iTime(Symbol(), PERIOD_CURRENT, 1), TIME_DATE|TIME_MINUTES); string harga = DoubleToString(close1, _Digits); string high = DoubleToString(high1, _Digits); string low = DoubleToString(low1, _Digits); string encoded = BuildEncoded(isBullish, waktu, harga, high, low); SendToTelegram(encoded); } void OnDeinit(const int reason) { string msg = "%E2%9B%94%20EA%20Dinonaktifkan%20di%20" + UrlEncodeValue(Symbol()); SendToTelegram(msg); }
Cara Menerapkan ke EA Anda Sendiri
Untuk mengadaptasi teknik ini ke EA yang sudah ada, ikuti langkah berikut:
Fungsi ini wajib ada. Semua nilai dinamis (waktu, harga, nama simbol, level risiko) harus dilewatkan ke fungsi ini sebelum di-concat ke string pesan.
Gunakan tabel referensi di atas. Hardcode langsung sebagai string:
string eBuy = "%F0%9F%9A%80"; — tidak perlu encode lagi karena sudah ASCII.
Dalam URL-encoded body, newline ditulis %0A dan spasi bisa
ditulis %20 atau +. Karakter khusus seperti
: → %3A, ! → %21.
Pastikan header WebRequest menggunakan application/x-www-form-urlencoded\r\n,
bukan application/json. Ini penting agar Telegram mendecode %XX dengan benar.
Masuk ke Tools → Options → Expert Advisors, centang
Allow WebRequest for listed URL, dan tambahkan
https://api.telegram.org.
Mengapa Tidak Pakai parse_mode Markdown/HTML?
Banyak sumber di internet menyarankan menambahkan parse_mode=MarkdownV2
atau parse_mode=HTML ke request Telegram untuk mendukung formatting.
Namun perlu dipahami: parse_mode tidak ada hubungannya dengan emoji.
Parse mode hanya mempengaruhi formatting teks seperti bold, italic,
dan monospace. Emoji bekerja di semua mode — masalahnya bukan di sisi Telegram,
melainkan di sisi MQL5 yang tidak bisa mengirim byte UTF-8 emoji dengan benar
melalui StringToCharArray().
&parse_mode=HTML ke string params dan gunakan tag HTML yang sudah di-encode:
%3Cb%3E untuk <b> dan %3C%2Fb%3E untuk </b>.
π Selamat Mencoba!
Dengan teknik URL-encode ini, notifikasi EA Anda ke Telegram akan tampil profesional dan informatif — lengkap dengan emoji yang terbaca sempurna di semua perangkat.
