Enviar un solo mensaje desde tu teléfono y verlo ejecutarse como una operación en vivo en múltiples terminales de MetaTrader 4 simultáneamente — eso es exactamente lo que hace ApexCopier. Esta publicación explica cómo lo construimos, las decisiones detrás de la arquitectura y el código clave que lo hace funcionar.
El Problema con las Soluciones Comerciales #
La mayoría de los copiadores de Telegram a MT4 en el mercado vienen como cajas negras compiladas — un conector .exe y un EA .ex4 sin código fuente, sin flexibilidad y sin comprensión real de lo que ocurre internamente. Si algo falla o quieres personalizar el formato de señales, estás atascado.
Nosotros queríamos algo diferente: un sistema completamente transparente y minimalista basado en un formato de señales claro que controlamos de principio a fin. Sin dependencias innecesarias, sin archivos misteriosos ejecutándose en segundo plano — solo un script de Python, un archivo CSV y un Expert Advisor de MQL4 haciendo exactamente lo que les indicamos.
Parte 1 — El Conector: De Telegram a un Archivo #
El conector es un script de Python que corre junto a MT4 y actúa como puente entre tu canal de Telegram y el terminal de trading. Utiliza la API de Bot de Telegram — un bot se crea a través de @BotFather, se agrega como Administrador a un canal privado, y a partir de ese momento recibe cada mensaje publicado en el canal en tiempo real.
@bot.channel_post_handler(func=lambda msg: True)
def on_channel_post(message):
text = message.text or message.caption or ""
signal = sig_parser.parse(text)
if signal is None:
print(f"[skip] Not a valid signal: {repr(text)}")
return
sig_id = writer.append(signal, MT4_FILES_PATHS, COUNTER_FILE)
Cuando llega un mensaje, se pasa al parser. Las señales válidas se escriben como una fila en signals.csv directamente dentro de la carpeta MQL4/Files/ de MT4. Los mensajes inválidos se omiten silenciosamente.
El formato de señales fue diseñado para ser fácil de usar y rápido de escribir, y puede personalizarse para diversas necesidades:
| Mensaje | Acción |
|---|---|
L |
Posición larga |
S |
Posición corta |
C |
Cerrar todas las posiciones |
EURUSD BUY MARKET TP:1.0950 SL:1.0800 |
Orden de mercado completa |
EURUSD SELL LIMIT 1.0820 TP:1.0750 SL:1.0870 |
Orden pendiente |
Nuestro parser maneja tanto señales de una letra como señales estructuradas completas con símbolo, dirección, tipo de entrada y niveles de precio — todo en una sola función sin dependencias externas más allá del texto del mensaje.
Una nota arquitectónica importante: cada máquina que ejecuta MT4 tiene su propio token de bot dedicado. La API de Telegram solo permite una conexión de polling activa por token, por lo que ejecutar el conector en dos máquinas con el mismo token genera un conflicto 409. La solución es simple — crea un segundo bot, agrégalo como administrador al mismo canal y asígnalo a la segunda máquina. Ambos bots reciben cada señal de forma independiente.
Parte 2 — El Puente IPC: Señales como Archivo CSV #
MT4 es un entorno aislado. Los Expert Advisors solo pueden leer y escribir archivos dentro de su propia carpeta MQL4/Files/ — no hay forma directa de que un proceso externo envíe datos a un EA en ejecución. La solución estándar es la comunicación entre procesos basada en archivos, y CSV es el formato más legible para ello.
Cada señal escrita por el conector se convierte en una fila:
id, timestamp, type, symbol, direction, entry_type, entry_price, sl, tp
1, 2026-04-20 23:15:00, SIMPLE, , BUY, MARKET, 0.00000, 0.00000, 0.00000
2, 2026-04-20 23:31:00, FULL, EURUSD, SELL, MARKET, 0.00000, 1.08700, 1.07500
El conector agrega filas y nunca modifica las existentes. El EA rastrea el último ID de señal procesado en un archivo separado last_processed.txt — en cada tick del temporizador lee solo las filas que no ha visto aún, las ejecuta y actualiza el puntero. Esto significa que los reinicios en cualquiera de los lados son seguros: el EA nunca ejecutará una señal dos veces, y el conector nunca sobrescribirá el historial.
Para múltiples instancias de MT4 en la misma máquina, el conector simplemente escribe la misma fila en múltiples rutas simultáneamente:
for path in MT4_FILES_PATHS:
signals_file = os.path.join(path, "signals.csv")
try:
_write_row(signals_file, row, header)
except OSError as e:
print(f"[warn] Could not write to {signals_file}: {e}")
Cada terminal lee desde su propia copia del archivo, de forma completamente independiente.
Parte 3 — El Expert Advisor: Ejecución Dentro de MT4 #
El EA es intencionalmente ligero. No tiene lógica de trading propia — solo lee señales y las ejecuta. Un temporizador de un segundo reemplaza a OnTick() para minimizar el uso de CPU y evitar procesamiento innecesario en cada actualización de precio.
void OnTimer() { ProcessSignals(); }
El dimensionamiento de lotes admite tres modos controlados por las entradas del EA: lote fijo, porcentaje del equity de la cuenta o un monto de riesgo fijo en dólares. Cuando un modo basado en riesgo está activo, el lote se calcula para que un golpe al stop loss cueste exactamente el monto especificado:
double slPoints = MathAbs(entryPrice - sl) / MarketInfo(symbol, MODE_POINT);
double tickValue = MarketInfo(symbol, MODE_TICKVALUE);
double lot = NormalizeDouble(riskAmount / (slPoints * tickValue), lotDecimals);
El EA también aplica un tema de gráfico personalizado en la inicialización — fondo negro, velas alcistas blancas y el azul característico de Telegram (#2AABEE) para velas bajistas — para que cada gráfico tenga un aspecto oscuro consistente sin configuración manual.
Los tipos de señales son individualmente activables mediante las entradas del EA, lo que significa que el mismo canal puede servir a terminales configurados de manera diferente: una instancia operando señales completas con riesgo basado en porcentaje, otra respondiendo solo a los comandos simples L/S/C con un lote fijo. Cada terminal es independiente, con su propio número mágico, configuración de lotes e interruptores de activación.
ApexCopier terminó siendo aproximadamente 200 líneas de Python y 150 líneas de MQL4 — lo suficientemente pequeño para entenderlo completamente, lo suficientemente flexible para crecer.