Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.novosky.app/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Go binary (novosky_go) is a compiled, dependency-free runtime of the NOVOSKY trading bot. It reads config.json and .env from disk at startup, but everything else β€” ML models, scalers, metadata, ml_config.json, strategy_params.json, and the license β€” is baked into the binary at build time. What customers receive:
FileDescription
novosky_goThe compiled binary (contains all models + license)
config.jsonUser-editable runtime configuration
.envSecrets and external service credentials
The repo includes env.customer.example as a minimal template for the customer .env β€” it only contains the fields a customer needs (MT5 API, Telegram, optional AI assistant). The developer .env.example contains additional fields for HF Hub, Supabase, GitHub, and other owner-only services. No Python, no models/ directory, no Hugging Face Hub, no pip install.

Prerequisites

RequirementPurpose
Go 1.24+Build the binary
Python + trained modelsRequired before packing (make train)
onnxruntime pip packageAuto-detects libonnxruntime.so at runtime
onnxmltools + skl2onnxExport risk/SLTP models to ONNX

Build flow

Every binary build follows the same two-step process.
1

Pack embedded assets

Copy model files, configs, and optionally the license into internal/embedded/ for //go:embed:
bash scripts/pack_embedded.sh            # dev build (placeholder license)
bash scripts/pack_embedded.sh --license  # production (copies license.json)
This populates internal/embedded/models/ with all .onnx and scaler JSON files, plus ml_config.json and strategy_params.json.
2

Build the binary

# Dev build (no license key β€” license check skipped automatically)
go build -o novosky_go ./cmd/novosky/

# Production build (license key embedded at compile time)
go build \
  -ldflags="-X github.com/mokatific/novosky/internal/license.masterKey=YOUR_SECRET" \
  -o novosky_go ./cmd/novosky/

Running

./novosky_go --dry      # dry-run β€” no real orders, logs only
./novosky_go            # live trading
./novosky_go --dir /path/to/config   # explicit directory for config.json and .env
The binary reads config.json and .env from the same directory as the executable by default, or from --dir.

Embedded assets

Model files and configs are embedded at compile time using Go’s //go:embed. The scripts/pack_embedded.sh script copies files from the repo into internal/embedded/ before each build.

What is embedded

Embedded fileSource
models/ensemble_rf/xgb/lgb.onnxmodels/ (auto-exported by trainer)
models/position_rf/xgb/lgb.onnxmodels/ (auto-exported by trainer)
models/risk_lgb.onnxmodels/ (via export_onnx_regression.py)
models/sltp_sl_lgb.onnx, sltp_tp_lgb.onnxmodels/ (via export_onnx_regression.py)
models/*_scaler.jsonmodels/ (via export_scalers.py)
models/*_metadata.jsonmodels/ (feature names, training metadata)
ml_config.jsonRepo root
strategy_params.jsonRepo root
license.jsonGenerated by cmd/licgen

What stays on disk (user-editable)

FileWhy on disk
config.jsonUser tunes risk profile, SL/TP, filters per account
.envSecrets (MT5 API token, Telegram, Supabase)

Model format

Model groupInput nameOutput name(s)Type
Ensemble / Position"X""label", "probabilities"Classification
Risk / SLTP"float_input""variable" (shape [1,1])Regression
The leaves library is not used β€” it only supports LightGBM format v3, and trained models are v4. All models are converted to ONNX for Go inference.

ONNX runtime library

The binary loads libonnxruntime.so dynamically at startup. Use the --bundle-ort flag and bundle_ort build tag to embed libonnxruntime.so directly into the binary (~22 MB extra). Customers need zero external files:
bash scripts/pack_embedded.sh --license --bundle-ort
go build -tags bundle_ort \
  -ldflags="-X github.com/mokatific/novosky/internal/license.masterKey=YOUR_SECRET" \
  -o novosky_go ./cmd/novosky/
pack_embedded.sh --bundle-ort auto-discovers the .so from the Python onnxruntime pip package. Override with ONNXRUNTIME_LIB=/path/to/libonnxruntime.so if needed.

Standard build (unbundled)

In standard builds (no bundle_ort tag), the binary searches at startup:
  1. ONNXRUNTIME_LIB environment variable
  2. Same directory as the binary (libonnxruntime.so next to novosky_go)
  3. System LD_LIBRARY_PATH
  4. Python’s onnxruntime pip package (auto-glob, dev convenience)
For distributing a standard binary, ship libonnxruntime.so next to novosky_go, or set ONNXRUNTIME_LIB in the customer’s .env.

License system

The license controls which MT5 account numbers can trade and until when. It is embedded in the binary at build time β€” customers cannot inspect or modify it.

How it works

  1. Owner creates an accounts.json with MT5 account numbers and expiry dates
  2. Owner runs licgen to produce a signed license.json
  3. Owner runs pack_embedded.sh --license to embed it
  4. Owner builds novosky_go with the production key
  5. Customer receives novosky_go β€” the license is inside the binary

License format

{
  "key": "NOVA-2026-XYZ",
  "accounts": {
    "123456": { "start": "2026-05-13", "end": "2026-08-13" },
    "1234567": { "start": "2026-05-13", "end": "2027-05-13" }
  },
  "signature": "<hmac-sha256-hex>"
}
The HMAC-SHA256 signature covers key + all account entries (sorted). Any edit to dates or accounts invalidates the signature β€” customers cannot extend their own license. Omit "end" for an account entry to make it never expire.

Generating a license

# 1. Build licgen with the production key
SECRET="your-secret-here"
go build \
  -ldflags="-X github.com/mokatific/novosky/internal/license.masterKey=$SECRET" \
  -o licgen ./cmd/licgen/

# 2. Create accounts.json (keep private β€” never ship this file)
cat > accounts.json <<'EOF'
{
  "123456":  {"start": "2026-05-13", "end": "2026-08-13"},
  "1234567": {"start": "2026-05-13", "end": "2027-05-13"}
}
EOF

# 3. Generate signed license.json
./licgen -key "NOVA-2026-XYZ" -f accounts.json -o license.json
The licgen output:
license.json written β†’ license.json
Key: NOVA-2026-XYZ
Accounts (2):
  123456   2026-05-13 β†’ 2026-08-13
  1234567  2026-05-13 β†’ 2027-05-13

License expiry behavior

When a customer’s license expires, the bot refuses to start:
license for account 123456 expired on 2026-08-13 β€” renew at novosky.app
To renew: generate a new license.json with updated dates, run pack_embedded.sh --license, rebuild, and send the customer a new binary.

Dev builds

In dev builds (no -ldflags key), license validation is skipped automatically. The placeholder license.json ({}) committed to git is harmless β€” the bypass happens before the file is even read.

Post-retrain workflow

After make train or python scripts/retrain.py:
1

Export scalers and regression models

python scripts/export_scalers.py          # PKL scalers β†’ JSON
python scripts/export_onnx_regression.py  # risk/SLTP .txt boosters β†’ .onnx
2

Re-pack embedded assets

bash scripts/pack_embedded.sh             # dev
bash scripts/pack_embedded.sh --license   # production (with license.json)
3

Rebuild binary

go build -o novosky_go ./cmd/novosky/
# or with production key:
go build -ldflags="..." -o novosky_go ./cmd/novosky/
4

Verify

./novosky_go --dry
Ensemble and position ONNX files are auto-exported by the Python trainer. You only need to manually run the two export scripts for the risk and SLTP regression models.

Telegram commands

The Go binary supports the same Telegram commands as the Python bot:
CommandDescription
/statusAccount balance, equity, daily P/L
/positionsOpen positions with ticket, direction, lot, P/L
/pnlWeekly P/L summary
/newsUSD economic calendar (medium/high impact)
/latencyBroker API round-trip latency
/pauseBlock new trade entries
/resumeRe-enable trading
/close <ticket>Close one position by ticket number
/closeallClose all open positions
/closeprofitClose all positions in profit
/closelossClose all positions at a loss
/helpShow all commands
Free-text messages (not commands) are routed to the AI assistant if assistant.enabled is set in config.json.

AI assistant

The AI assistant is an OpenAI-compatible tool-calling agent configured via .env. It can query account status, list positions, close trades, fetch news, and run MT5 API calls directly.
AI_BASE_URL=https://models.github.ai/inference   # or OPENAI_BASE_URL
AI_API_KEY=your_api_key                          # or OPENAI_API_KEY or GITHUB_TOKEN
If AI_BASE_URL is not set, it defaults to GitHub Models. The model can be overridden per-account in config.json:
"assistant": { "enabled": true, "model": "gpt-4o" }

Source layout

PathPurpose
cmd/novosky/main.goEntry point β€” signal handling, retry loop
cmd/licgen/main.goLicense generator (owner only, never shipped)
internal/bot/bot.goMain trading loop
internal/ml/ONNX ensemble, position, risk, SLTP predictors
internal/embedded/embed.go//go:embed declarations for all model assets
internal/config/config.json, ml_config.json, strategy_params.json loaders
internal/api/MT5 REST API client
internal/telegram/Telegram command bot
internal/assistant/AI assistant (OpenAI-compatible, tool-calling)
internal/license/HMAC-SHA256 license validation
internal/supabase/Supabase REST client
internal/logger/Trade, signal, and daily CSV logger
scripts/pack_embedded.shCopy models + configs into internal/embedded/
scripts/export_scalers.pyExport PKL scalers β†’ JSON
scripts/export_onnx_regression.pyExport risk/SLTP LGB β†’ ONNX