Desarrollo de un gestor de terminales (Parte 1): Planteamiento del problema
Introducción
Si queremos utilizar un único asesor experto en nuestra cuenta de trading, no hay ningún problema: iniciamos el terminal, instalamos el asesor experto y esperamos el resultado. Imaginemos una situación en la que las operaciones van bien y surge el deseo de probar a añadir uno o varios asesores expertos más. Si pueden trabajar sin interferir entre sí, estupendo. Si no es así, hay que iniciar copias independientes del terminal para ellos. Estas copias también serán necesarias si hay que operar en diferentes cuentas.
Aquí empiezan a surgir poco a poco las primeras dificultades organizativas y técnicas. ¿Cómo podemos facilitarnos la vida y controlar cómodamente varios terminales en los que operan asesores expertos? Además, los terminales pueden estar ubicados físicamente en diferentes computadoras (servidores). ¿Qué se puede hacer al respecto?
Antes, para algo así se podía utilizar MultiTerminal. Sin embargo, solo permitía realizar operaciones manuales en varias cuentas. Y solo en MetaTrader 4. Después dejó de recibir soporte por completo, y nunca llegó a lanzarse un equivalente para MetaTrader 5. Las herramientas de terceros que existen actualmente solo ofrecen funciones de supervisión, pero no una gestión completa.
Por eso queremos crear una interfaz web para gestionar el inicio de los terminales de trading MetaTrader 5 en las computadoras disponibles. A través de la página web local desarrollada, se podrá ver la lista de instancias en ejecución, consultar información más detallada sobre el funcionamiento de cada instancia, añadir nuevas instancias o eliminar las que estén en ejecución. En principio, esta lista se podría ampliar bastante. Esto no solo facilitará las cosas, sino que también aumentará la fiabilidad del sistema de trading en su conjunto.
Arquitectura
Para crear un sistema de gestión de terminales distribuidos, necesitamos una arquitectura modular y escalable. Se puede dividir en tres componentes clave que interactúan entre sí.
- Servidor web principal. Es el núcleo del sistema, que ofrece al usuario una interfaz y coordina su funcionamiento. Se encargará de recibir los comandos del usuario (inicio, parada, supervisión), de enviarlos a los servidores web correspondientes de los terminales y de agregar toda la información disponible para mostrarla en un único panel.
- Servidor(es) web de los terminales. Se trata de un componente que funciona directamente en cada computadora en la que estén instalados los terminales de trading. Para ejecutar los comandos recibidos del servidor web principal, supervisar el estado de los terminales MetaTrader 5 ejecutados localmente y proporcionar información actualizada, utilizaremos Python con la biblioteca de MetaTrader 5.
- Almacenamiento de datos. Para almacenar la información sobre los servidores, los terminales, las cuentas y sus configuraciones, utilizaremos SQLite en una primera fase. Es una base de datos ligera, ideal para prototipos y despliegues sencillos. Además, se puede acceder a ella tanto desde Python como desde programas en MQL5, lo que abre nuevas posibilidades de integración. En el futuro, a medida que aumente la carga y el sistema esté más distribuido, se podrá sustituir SQLite por un SGBD más potente, como PostgreSQL, pero antes habrá que llegar a ese momento.
Quizá necesitemos también un agente auxiliar en los propios terminales —un asesor experto o un servicio—, aunque todavía no está claro cuál de los dos.
Publicaremos todo el código en uno o varios proyectos públicos en el repositorio MQL5 Algo Forge.
Trazamos el camino
Se trata, sin duda, de una tarea muy amplia y, por eso, requiere un cierto esfuerzo para, al menos, empezar a trabajar en su resolución. Pero ya hemos recurrido en numerosas ocasiones a un principio sencillo que resulta muy útil en este tipo de situaciones. Una de las formas de enunciarlo podría ser esta: «¿Cómo se come un elefante? — Bocado a bocado». Esto significa que hay que dividir cualquier tarea compleja en partes pequeñas y realizables, y resolverlas una tras otra hasta alcanzar el objetivo general. Esto le ayudará a evitar la sobrecarga, a mantener la motivación y a conseguir resultados más rápidamente.
Por eso, empezaremos por desarrollar un servidor web simplificado para terminales. De momento, se encargará de una tarea sencilla: iniciar y detener, a petición del cliente, el terminal que se ejecuta en el servidor y está conectado a una cuenta de trading concreta. Entre una solicitud y otra, el cliente puede enviar solicitudes para obtener información actualizada sobre el estado de la cuenta. ¿Quién es el cliente en este contexto? Ahora seremos nosotros quienes actuemos principalmente como clientes, usando un navegador u otras herramientas que permitan enviar una solicitud HTTP al servidor web. En el futuro, el servidor web principal podrá actuar como cliente si mantenemos la arquitectura prevista inicialmente.
Veamos qué necesitamos para ello y cómo podemos aprovecharlo para obtener un producto mínimo viable (Minimum Viable Product, MVP).
Repasemos los conceptos
Ya hemos mencionado que vamos a desarrollar un servidor web. Así se podría denominar a una aplicación que espera recibir un determinado tipo de solicitudes a través de la red y es capaz de responder a ellas enviando los datos necesarios. El conjunto de tipos de solicitudes que nuestro servidor web podrá procesar constituye su API.
En términos más estrictos, una API (Application Programming Interface, es decir, interfaz de programación de aplicaciones) es un conjunto de reglas específicas que permite que una aplicación interactúe con otra. Establece qué datos se pueden solicitar o enviar entre programas, servicios o componentes del sistema y de qué manera. En pocas palabras, una API es un conjunto de reglas que permite que un programa se comunique con otro para intercambiar datos.
Para que resulte cómodo utilizar este conjunto de reglas, las solicitudes y las respuestas deben ajustarse a un formato concreto, que se documentará de forma rigurosa. Es decir, los desarrolladores describen qué solicitudes están disponibles, qué parámetros se aceptan y qué se devuelve en las respuestas.En nuestro proyecto, enviaremos solicitudes HTTP al servidor web y recibiremos como respuesta, bien datos en formato JSON, bien el texto de una página web en formato HTML.
Cualquier solicitud HTTP consta de las siguientes partes:
- Método (por ejemplo, GET, POST, PUT, DELETE): define la acción. También se le puede llamar «verbo»;
- URL: la dirección de un recurso en el servidor (por ejemplo, /start);
- Encabezados (headers): metadatos de la solicitud (por ejemplo, Content-Type, Authorization);
- Cuerpo de la solicitud (body): datos que se envían al servidor (por ejemplo, JSON o datos de un formulario de una página web).
Aunque solemos decir que el método «define la acción», en realidad es el servidor web el que determina el conjunto de acciones concretas que se llevan a cabo al recibir una solicitud. Como desarrollamos nosotros mismos este servidor web, podemos implementar cualquier comportamiento al procesar una solicitud con cualquier método. Sin embargo, por regla general, los desarrolladores se atienen a ciertas convenciones comúnmente aceptadas.
Por ejemplo, las solicitudes cuyo resultado principal sea obtener cierta información del servidor suelen comenzar con la palabra GET. Por eso se llaman así: solicitudes GET. Si, por el contrario, la solicitud debe enviar al servidor algunos datos para que se almacenen en él, normalmente se utiliza el verbo POST o PUT. Sin embargo, queremos subrayar una vez más que la decisión recae en el desarrollador. Se puede utilizar únicamente el método GET para ejecutar todas las solicitudes, por ejemplo. O solo POST.
La siguiente parte —la URL— especifica la solicitud, lo que permite al servidor web comprender qué se le pide. Las URL dirigidas a un servidor web concreto suelen indicarse sin el nombre de dicho servidor, es decir, comenzando por la barra «/», que indica la carpeta raíz en el árbol de recursos. Una URL puede constar de varias partes, separadas por barras «/».
Si acordamos que, para que el servidor web realice una acción concreta, hay que enviarle una solicitud con un verbo y una URL determinados, se dice que hemos definido un «punto de conexión» (endpoint) o una «ruta» (route).
Por ejemplo, así podría ser el punto de conexión que debe hacer que el servidor web devuelva una página HTML con el nombre del proyecto y una breve descripción del mismo:
De esta forma, se puede seleccionar un punto de conexión para obtener del servidor web una lista en formato JSON de todas las instancias de MetaTrader 5 que se están ejecutando en él:
GET /instances
Para algunos puntos de conexión, es posible que necesitemos enviar parámetros adicionales. En este caso, es imprescindible que se incluya en algún lugar una descripción de los nombres y los posibles valores de cada parámetro. Los parámetros pueden transmitirse bien como parte de la URL, bien en los encabezados, o bien en el cuerpo de la solicitud.
Por ejemplo, podemos seleccionar este punto de conexión para obtener información resumida sobre una instancia de MetaTrader 5 en ejecución:
GET /instance/<name>
En este caso, «<name>» es la parte variable de la solicitud que se sustituye por el nombre de la instancia deseada antes de enviarla.
El conjunto de todos los puntos de conexión seleccionados (rutas), junto con su descripción detallada, constituirá precisamente la API de nuestro servidor web.
Existen diferentes tipos de API. La que tenemos previsto utilizar en este proyecto se denomina API REST (siglas de «Representational State Transfer Application Programming Interface»). Es un estilo arquitectónico de interacción entre el cliente y el servidor a través de Internet mediante solicitudes HTTP estándar. Este estilo se caracteriza precisamente por los aspectos que vamos a usar:
-
El estado no se almacena en el servidor. Cada solicitud contiene toda la información necesaria para generar la respuesta, por lo que el servidor no necesita «recordar» la cadena de solicitudes anteriores. Sin embargo, esto no significa que el servidor no pueda almacenar ninguna información obtenida durante el procesamiento de solicitudes anteriores. Esta es la principal característica distintiva de esta API.
-
Los métodos HTTP indican el tipo de acción. En las API REST, por lo general, se utilizan distintos métodos HTTP para realizar diferentes operaciones con unidades de datos en el servidor: GET, para obtener datos; POST, para crear nuevos registros; PUT / PATCH, para actualizar los existentes; y DELETE, para eliminarlos. Pero esto es solo una recomendación.
-
Estructura de recursos. Todos los datos de los que dispone el servidor se presentan en forma de recursos con URL únicas. Por ejemplo, como hemos mencionado anteriormente:
- /instances: lista de todos los terminales,
- /instance/4428341: información sobre un terminal concreto denominado 4428341.
La lista de recursos puede ampliarse con el tiempo; es decir, se puede iniciar el proyecto proporcionando información sobre un número reducido de recursos y, posteriormente, ir añadiendo otros nuevos de forma gradual.
En resumen, la API REST de nuestro proyecto es un conjunto de puntos de conexión (rutas HTTP) a través de los cuales se podrán gestionar las instancias de MetaTrader 5 (iniciarlas, detenerlas y consultar su estado) en el servidor (computadora) en el que se ejecutará el servidor web que estamos desarrollando. Por lo tanto, para crear un servidor web de este tipo, debemos definir un conjunto de puntos de conexión y crear un programa que sea capaz de procesar correctamente las solicitudes correspondientes.
Para crear este programa, también utilizaremos dos soluciones listas para usar:
- Uvicorn es un servidor para Python que procesa de forma rápida y eficaz las solicitudes HTTP y es compatible con la asincronía. Se usa para ejecutar aplicaciones web, incluidas las creadas con FastAPI;
- FastAPI es un framework que permite describir la lógica de la aplicación (el procesamiento de solicitudes para todos los puntos de conexión).
Un framework es, por lo general, un código fuente ya preparado que contiene la implementación de acciones típicas que pueden resultar útiles a los desarrolladores a la hora de trabajar en sus proyectos. ¿En qué se diferencia un framework de una biblioteca? Quizá solo en que el código de un framework admite una gama más limitada de casos de uso; es decir, el framework establece unos límites más claros sobre cómo debe llevarse a cabo el desarrollo.
Uso de FastAPI
Los principios generales del desarrollo con el framework FastAPI pueden resumirse de la siguiente manera:
- La aplicación web consta de un conjunto de funciones: los manejadores de solicitudes para cada punto de conexión. Estas funciones pueden ser tanto síncronas como asíncronas. El desarrollador solo escribe estas funciones.
- Encima de cada manejador se coloca un decorador que vincula dicha función a un punto de conexión concreto. En él (el decorador) se especifican el método HTTP correspondiente, la URL y otros parámetros necesarios.
- En la función se pueden obtener parámetros del cuerpo de la solicitud, de los encabezados, de la URL, etc., usando tipos especiales del framework FastAPI (por ejemplo, Form, Query, Path, Body).
- La función devuelve una respuesta que FastAPI convierte automáticamente a JSON o a HTML.
Además de resolver la tarea principal, el framework FastAPI comprueba automáticamente que los tipos sean correctos y que los parámetros estén presentes en las solicitudes, genera documentación sobre todos los puntos de conexión y gestiona los errores devolviendo un JSON con su descripción. Más adelante veremos cómo funciona en la práctica.
Creamos la primera versión del servidor web
Para trabajar en el proyecto, hemos creado un nuevo repositorio vacío llamado mt5-manager en la plataforma MQL5 Algo Forge. Lo clonamos en la carpeta que prefiramos y añadimos un nuevo archivo para nuestra aplicación web, main.py:
mt5-manager/
│
└── main.py # Archivo principal de FastAPI
Para trabajar con el framework y el servidor seleccionados, tendremos que instalar los módulos de Python necesarios mediante el gestor pip:
pip install fastapi uvicorn jinja2 psutil
Vamos a elaborar una lista de los puntos de conexión (rutas) que necesitamos. Por ahora, añadiremos una ruta:
| # | Método | URL | Descripción, parámetros | Formato de respuesta |
|---|---|---|---|---|
| 1 | GET | / | Muestra la página principal con la interfaz web para gestionar las instancias de MetaTrader 5 Por ahora, que solo se muestre el título del proyecto. | HTML |
Así, crearemos una aplicación web mínima que gestione esta ruta. Para ello, lo primero que haremos será importar la clase principal de la aplicación desde el framework FastAPI. Esta clase se llama precisamente FastAPI:
from fastapi import FastAPI
A continuación, crearemos un objeto de esta clase. Este será el objeto de nuestra aplicación web. Llamémoslo, por ejemplo, app:
app = FastAPI()
Luego añadiremos una función llamada index(), que devolverá un encabezado de primer nivel con el nombre del proyecto. La convertiremos en asíncrona añadiendo la palabra clave async:
async def index(): return '<h1>MT5 Manager</h1>'
Ahora solo queda dar el último paso, aunque muy importante: añadir el decorador de enlace. Pero, antes de nada, vamos a explicar con un poco más de detalle en qué consiste.
Los decoradores en Python son funciones que modifican el comportamiento de otras funciones (o clases) sin alterar directamente su código. La modificación se lleva a cabo creando una nueva función que, en su interior, utiliza de alguna manera la función original. Si a continuación se guarda esta nueva función con el mismo nombre que la original, todas las llamadas posteriores se dirigirán ya a la función modificada. De este modo, se puede añadir lógica adicional (por ejemplo, comprobaciones, registro o almacenamiento en caché) antes o después de la ejecución del código de la función principal original.
Para aplicar un decorador a una función, hay que llamarlo directamente:
# Función original def my_function(): pass # Llamamos a la función decoradora, pasándole la función original # Guardamos la nueva función devuelta bajo el mismo nombre my_function = my_decorator(my_function)
O bien, como se hace siempre, basta con indicar el nombre del decorador deseado delante del encabezado de la función, precedido del símbolo @:
# Creación de una nueva función con el decorador my_decorator aplicado @my_decorator def my_function(): pass
Añadamos ahora el decorador que necesitamos:
@app.get('/') async def index(): return '<h1>MT5 Manager</h1>'
Es decir, @app.get('/') es un decorador que indica a FastAPI que la función index() debe gestionar las solicitudes GET en la ruta /.
Vamos a reunir todo en el archivo main.py:
# Importamos las clases necesarias de las bibliotecas from fastapi import FastAPI # Creamos un objeto de aplicación app = FastAPI() # Manejador de solicitudes GET en la dirección / (directorio raíz) @app.get('/') async def index(): return '<h1>MT5 Manager</h1>'
La aplicación web mínima está lista para ponerse en marcha. Ahora tendremos que recurrir al servidor Uvicorn, ejecutándolo en la consola e indicando nuestra aplicación web como fuente de las reglas de procesamiento de solicitudes:
uvicorn main:app --reload --no-use-colors
Aquí, main:app significa que nuestra aplicación web se encuentra en un archivo llamado main.py en la carpeta actual, y que el objeto de la aplicación en el código fuente se llama app. El parámetro --reload hace que el servidor se reinicie automáticamente cuando se realizan cambios en el código fuente de la aplicación web. El parámetro --no-use-colors desactiva la visualización de texto en la consola con diferentes colores (es necesario si el servidor se ejecuta en una consola que no admite esta función).
Una vez ejecutado, veremos algo parecido a esto:

Por defecto, el servidor web utilizará el puerto 8000, por lo que, para ver el resultado de su funcionamiento, abriremos en el navegador la dirección http://127.0.0.1:8000. Esto es lo que saldrá:

Como se puede ver, en la página se muestra efectivamente el texto que devolvemos desde la función index(). Pero, por alguna razón, el navegador no reconoce las etiquetas HTML del encabezado y las muestra simplemente como parte del texto de la página. Todo va bien, así es como debe ser. El caso es que, por defecto, el servidor devuelve el resultado acompañado de la indicación de que se trata de código JSON. Por eso, el navegador no interpretó el texto recibido como código HTML. Ahora lo vamos a arreglar.
Importamos otra clase del framework FastAPI, que representa la respuesta del servidor en formato HTML. En la línea de aplicación del decorador, añadiremos un parámetro adicional, response_class, a través del cual pasaremos el nombre de la clase HTMLResponse.
# Importamos las clases necesarias de las bibliotecas from fastapi import FastAPI from fastapi.responses import HTMLResponse # Creamos un objeto de aplicación app = FastAPI() # Manejador de solicitudes GET en la dirección / (directorio raíz) @app.get('/', response_class=HTMLResponse) async def index(): return '<h1>MT5 Manager</h1>'
Ahora, la cadena que devuelve nuestra función original se utilizará para crear un objeto de la clase HTMLResponse. Es precisamente un objeto de este tipo el que se devolverá al llamar a la función transformada por el decorador.
Una vez guardados estos cambios, el servidor Uvicorn que se había iniciado anteriormente se reiniciará automáticamente y veremos en el navegador lo que esperábamos:

La primera versión ya está lista; ahora podemos plantearnos ampliar la lista de rutas procesadas.
Ahora añadimos el inicio y la parada del terminal
No nos precipitaremos y, para empezar, trabajaremos en el inicio y la parada de una única instancia concreta del terminal. Supongamos que en la computadora en la que tenemos previsto ejecutar nuestro servidor web hay un terminal instalado, ubicado en la ruta
C:/Program Files/MetaTrader 5/terminal64.exe
Intentaremos conseguir que se inicie y se detenga al enviar las solicitudes correspondientes al servidor web. Para ello, añadiremos dos nuevas rutas a la tabla:
| # | Método | URL | Descripción, parámetros | Formato de respuesta |
|---|---|---|---|---|
| 1 | GET | / | Muestra la página principal con la interfaz web para gestionar las instancias de MetaTrader 5 Por ahora, que solo se muestre el título del proyecto. | HTML |
| 2 | POST | /start | Inicia una instancia del terminal MetaTrader 5 ubicado en la ruta especificada. | JSON |
| 3 | POST | /stop | Detiene el proceso de MetaTrader 5 que se está ejecutando | JSON |
Hemos establecido el formato de respuesta JSON para estas rutas, ya que no queremos que, como resultado de su procesamiento, se genere ninguna página HTML que vaya a mostrar el navegador. En principio, debería ser una página con un mensaje sobre el resultado del inicio, pero podremos ver esos resultados más adelante en la página principal, que se devuelve al procesar la primera ruta. Para que el código resulte más claro, podemos especificar explícitamente que el resultado será un objeto de respuesta en formato JSON.
Importamos otra clase del framework:
from fastapi.responses import HTMLResponse, JSONResponse
Ahora se puede usar de forma similar a como utilizábamos la clase HTMLResponse, o creando explícitamente un objeto de la clase deseada al devolver el valor desde el manejador de ruta. A continuación mostraremos cómo es la segunda opción.
Una buena práctica consiste en reducir al mínimo el código interno de los manejadores de rutas. Esto se consigue trasladando casi todas las acciones a funciones externas independientes. Así es como se podría escribir el código de dos nuevos manejadores de rutas teniendo en cuenta lo anterior:
# Manejador POST /start: inicio del terminal @app.post('/start') async def start_instance(): result = start_mt5() return JSONResponse(result) # Manejador POST /stop: parada del terminal @app.post('/stop', response_class=JSONResponse) async def stop_instance(): result = stop_mt5() return JSONResponse(result)
Las funciones start_mt5() y stop_mt5() las escribiremos un poco más abajo. Por sus nombres se deduce que estas funciones contendrán el código encargado directamente del inicio o la parada del terminal MetaTrader 5.
Pero primero crearemos una constante con la ruta completa al archivo ejecutable del terminal y un diccionario para almacenar la información sobre el proceso en ejecución:
# Ruta al archivo ejecutable del terminal MT5_PATH = 'C:/Program Files/MetaTrader 5/terminal64.exe' # Diccionario para almacenar información sobre el terminal en funcionamiento instances = {}
Para la función de inicio del terminal nos vendrá bien la biblioteca subprocess, así que primero la importaremos y, a continuación, implementaremos la función start_mt5() propiamente dicha. Por el momento, implementaremos el inicio mediante una llamada a la función Popen(), a la que hay que pasar una lista con los argumentos de la línea de comandos de inicio. En nuestro caso, esta lista estará compuesta por un único elemento: la ruta completa al archivo del terminal de MetaTrader 5.
import subprocess # Inicio del terminal def start_mt5(): # Iniciamos un nuevo proceso process = subprocess.Popen([MT5_PATH]) # Identificador del proceso en ejecución pid = process.pid # Guardamos el identificador y el estado del proceso instances['default'] = {'pid': pid, 'status': 'running'} # Devolvemos el resultado: inicio correcto return {'instance': 'default', 'pid': pid}
El uso de este método de inicio permite ahora implementar más fácilmente la función de parada del terminal. Como al iniciar el nuevo proceso guardamos su identificador (pid), para su parada podemos utilizar la biblioteca psutil, que contiene una clase que representa los procesos en ejecución. En la función stop_mt5(), creamos un objeto de esta clase a partir del identificador del proceso deseado y, a continuación, lo detenemos llamando al método terminate().
Si todo va bien, devolvemos un mensaje indicando que la parada se ha realizado correctamente; en caso contrario, indicamos que no se ha encontrado el proceso.
import psutil # Parada del terminal def stop_mt5(): # Si el terminal ya se había iniciado if 'default' in instances: # Obtenemos el identificador de su proceso pid = instances['default']['pid'] try: # Obtenemos el objeto del proceso del terminal p = psutil.Process(pid) # Detenemos el proceso p.terminate() # Eliminamos la información sobre el proceso iniciado anteriormente del instances['default'] # Devolvemos el resultado: parada realizada con éxito return {'status': 'stopped', 'instance': 'default'} except psutil.NoSuchProcess: # Si no se encuentra el proceso, entonces # eliminamos la información sobre el proceso iniciado anteriormente del instances['default'] # Devolvemos el resultado: no se ha encontrado el proceso return {'status': 'not found', 'instance': 'default'}
Guardemos los cambios realizados en el archivo main.py y veamos cómo podemos probar la funcionalidad añadida.
Documentación y pruebas
Si bien podemos probar la primera ruta simplemente introduciendo la URL correspondiente en la barra de direcciones, no es posible probar la segunda y la tercera de esa manera. Esto se debe a que, al enviar una solicitud desde la barra de direcciones, el navegador siempre utiliza solicitudes GET. Ahora tenemos que comprobar cómo funcionan los puntos de conexión a los que solo se puede acceder mediante una solicitud POST. Por suerte, el framework también nos ayudará en este caso.
FastAPI genera automáticamente documentación interactiva de la API basándose en los decoradores y las anotaciones de tipos del código. Además, FastAPI incluye compatibilidad integrada con Swagger UI (Swagger u OpenAPI es un estándar de descripción de API REST), lo que permite visualizar y probar todos los puntos de conexión directamente en el navegador. Esto resulta muy práctico, sobre todo si posteriormente vamos a utilizar esta API en otras aplicaciones web.
Para acceder a esta herramienta, basta con abrir la página http://127.0.0.1:8000/docs tras iniciar la aplicación del servidor web. Aunque nosotros no hayamos añadido ese punto de conexión, está disponible en cualquier aplicación web creada con el framework FastAPI.
Al acceder a esta página, veremos una lista de todos los puntos de conexión (rutas) de nuestro servidor web que se han añadido en la aplicación web:

Cada ruta se puede desplegar para ver la lista de parámetros con sus descripciones y el formato de la respuesta. Nuestras rutas aún no tienen parámetros, por lo que de momento solo vemos «No parameters»:

Pero lo más interesante es, sin duda, la posibilidad de enviar manualmente una solicitud a cada punto de conexión y ver el resultado. Para ello, hagamos clic en el botón «Try it out» de la ruta desplegada y, a continuación, en el botón «Execute» que aparecerá.

Como resultado, veremos la respuesta recibida del servidor web con el código 200 (OK) e información sobre la instancia en ejecución del terminal MetaTrader 5 con el identificador de proceso pid=16480. Al abrir el Administrador de tareas de Windows en nuestra computadora, podemos comprobar que ese proceso existe realmente y que se trata, efectivamente, del terminal MetaTrader 5:

Si ahora hacemos lo mismo con la ruta POST /stop, el terminal en ejecución se cerrará y el servidor web enviará una confirmación como respuesta:

Así pues, con ayuda de esta herramienta hemos comprobado que nuestro servidor web procesa correctamente las solicitudes dirigidas a todos los puntos de conexión, llevando a cabo las acciones necesarias.
Conclusión
Vamos a hacer una pausa aquí y veremos qué hemos conseguido hasta ahora en nuestro camino hacia el objetivo fijado. Hemos creado con éxito un prototipo funcional del sistema de gestión de terminales de MetaTrader 5. Nuestro servidor web mínimo en FastAPI ya es capaz de iniciar y detener el terminal mediante una simple solicitud HTTP. No solo hemos implementado la lógica básica, sino que también nos hemos asegurado de que funciona correctamente.
Este MVP es un primer paso fundamental que confirma que el camino elegido es el correcto. Hemos «dado el primer paso» y hemos sentado las bases sobre las que se puede desarrollar la funcionalidad futura. Los siguientes pasos lógicos serán:
- Incorporación de la posibilidad de registrar varias computadoras con terminales.
- Creación de una interfaz para vincular cuentas de trading a servidores y terminales concretos.
- Ampliación de la API para obtener información detallada sobre el estado de las cuentas, las posiciones abiertas y el funcionamiento de los asesores expertos.
El camino que nos espera es largo, pero ya hemos dado el primer bocado al elefante.
¡Gracias por su atención! ¡Hasta la próxima!
Contenido del archivo
| # | Nombre | Versión | Descripción | Últimas modificaciones |
|---|---|---|---|---|
| mt5-manager | Carpeta de trabajo del proyecto del servidor web de terminales | |||
| 1 | main.py | 1.00 | Aplicación web para el servidor web de terminales | Parte 1 |
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/19804
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.