Skip to content

Releases

meta-docker 1.0.1

Choose a tag to compare

@marketcalls marketcalls released this 15 Aug 11:36

Fixes a real gap raised right after the 1.0.0 announcement: what happens
when the terminal restarts underneath a running bridge.

The bug

connect_loop returned after the first successful attach. If the
terminal then died and came back, the bridge kept answering 503 to
every request until someone called POST /initialize by hand. That is
not an edge case. The container watchdog revives terminal64.exe on its
own, which produces exactly this state.

The fix

The connect loop supervises instead of returning. It watches the
connection, re-attaches when it drops, and treats MT5_INIT_RETRIES as a
bound on consecutive failures within one attach cycle rather than on the
lifetime of the bridge, so a terminal that dies again later gets the full
retry budget again.

Telling a reconnect from an idle gap

A client previously had no way to know whether it had missed data. There
is now a session counter that increments only when the bridge attaches to
a terminal it was not attached to a moment ago, reported by GET /health
and the gRPC Health RPC:

{"status": "ok", "connected": true, "session": 2, "connected_since": 1781227214.6}

Record it alongside your data. After a reconnect, read it again:
unchanged means you were merely idle, higher means the terminal restarted
and the gap has to be backfilled. This matters because a resumed lossless
tick stream skips backlog older than BRIDGE_TICK_MAX_BACKFILL_MS, so
the changed session is the only signal your client gets.

docs/API.md has a new section, "Recovering after a terminal restart",
covering the full sequence and a gap-detection example.

Also in this release

  • GET /health is served from cached state rather than a live IPC call,
    so an unauthenticated caller can no longer make the terminal do work on
    every poll.
  • New MT5_WATCH_SECONDS (default 5) for the supervisor interval.
  • The declared grpcio and protobuf floors now match what the
    committed gRPC stubs actually require. They were understated before.

Behaviour on terminal loss is unchanged and still explicit: WebSocket
streams close with 1011 and a reason, gRPC streams end UNAVAILABLE,
and requests return 503 rather than stale data. Open positions are
never affected by any of this, since they live on the broker's server.

Verified with 235 checks, 20 of them driving the restart path end to end.

meta-docker 1.0.0

Choose a tag to compare

@marketcalls marketcalls released this 15 Aug 07:30

Headless MetaTrader 5 with a REST, WebSocket and gRPC API. Run the
terminal on a Linux server or a Mac, and trade it from any language.

Why

MetaTrader 5 is a Windows desktop program and its official Python API
only talks to a terminal on the same machine. meta-docker puts an HTTP
API in front of that terminal, so a strategy written in Go, Node, Rust or
Python, running anywhere, can read market data and place orders.

What is in this release

Three transports over one core

  • REST and WebSocket on port 8001: account, symbols, candles on 21
    timeframes, tick history, positions, working orders, trade history,
    market orders with automatic filling-mode fallback, and a raw
    order_send passthrough
  • gRPC on port 8002: the same operations plus server-streaming
    StreamTicks, StreamAccount and StreamPositions
  • A browser console at /portal: live account telemetry, a lossless
    price stream, open positions with a close button, an order ticket and
    API key management

Security, sized for a service that can move real money

  • Authentication is on by default. If no key is configured the bridge
    mints an admin key on first boot and prints it once to the log.
  • Keys are stored as SHA-256 digests and compared in constant time. Only
    an admin key can issue or revoke keys, and revocation takes an opaque
    id so it cannot be widened into disabling authentication.
  • Brute-force lockout, per-client rate limiting, a request body cap,
    strict symbol and trade-request validation, and Origin checks on
    WebSockets and cross-origin requests.
  • REST, gRPC and the published Docker ports all bind to 127.0.0.1 by
    default. Exposing the bridge is a deliberate act.
  • BRIDGE_READ_ONLY=1 serves market data and rejects every order.
  • The portal ships its own CSS and JS, loads no third-party asset and
    renders every server value as text, so responses carry a strict
    default-src 'self' policy.
  • The container runs as an unprivileged user with capabilities dropped
    and no-new-privileges. Terminal DLL imports are off. The VNC desktop
    stays on loopback unless a password is set.

Documentation

  • docs/API.md is the contract: every endpoint, parameter bound, status
    code and environment variable, checked against a running bridge
  • SECURITY.md covers safe deployment and how to report a problem
  • README.md explains the problem in trader terms and who this is for

Getting started

git clone https://github.com/marketcalls/meta-docker
cd meta-docker/docker
cp .env.example .env
docker compose up --build -d
docker compose logs mt5 | grep -A2 "X-API-Key"

On Windows the bridge runs natively next to an installed terminal, with
no Docker and no Wine. See the README for both paths.

Before you expose it

The bridge speaks plain HTTP, so an API key travels in a readable header.
Keep it on 127.0.0.1 behind a TLS-terminating reverse proxy, or on a
private network. Start with BRIDGE_READ_ONLY=1 and a demo account.
Read SECURITY.md first.

Trading involves risk. This software is provided as-is and is not
investment advice.