Build a Go‑Powered Stock Trend Predictor with ONNX Runtime in Minutes
This guide walks you through setting up an Ubuntu environment, training a LightGBM stock‑movement model in Python, exporting it to ONNX, and deploying fast, cross‑platform inference in Go using ONNX Runtime, complete with code snippets and project structure.
1. Ubuntu environment setup
Install the required build tools, CMake, Git, wget, curl, unzip, Python 3 development headers, pip, and protobuf development libraries.
sudo apt update
sudo apt install -y build-essential cmake git wget curl unzip
sudo apt install -y python3-dev python3-pip
sudo apt install -y libprotobuf-dev protobuf-compilerDownload ONNX Runtime 1.22 for Linux x64, extract it, move the directory to $HOME/onnxruntime, and add the library path to LD_LIBRARY_PATH so that the runtime can be located.
cd ~
wget https://github.com/microsoft/onnxruntime/releases/download/v1.22/onnxruntime-linux-x64-1.22.tgz
tar -xzf onnxruntime-linux-x64-1.22.tgz
mv onnxruntime-linux-x64-1.22 $HOME/onnxruntime
echo 'export LD_LIBRARY_PATH=$HOME/onnxruntime/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc2. Train a LightGBM stock‑price direction model in Python and export to ONNX
The training script expects a CSV file data/stock_history.csv containing at least the columns Date, Open, High, Low, Close, Volume. Feature engineering creates:
Percentage return of the close price.
5‑day and 10‑day moving averages of the close price.
Relative Strength Index (RSI) computed over a 14‑day window.
The label is binary: 1 if the next day’s closing price is higher than today’s, otherwise 0.
# /predict/train_lightgbm_to_onnx.py
import os, sys
import pandas as pd, numpy as np, joblib
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from onnxmltools import convert_lightgbm, save_model
from onnxmltools.utils import FloatTensorType
def make_features(df):
df = df.copy()
df["return"] = df["Close"].pct_change()
df["ma5"] = df["Close"].rolling(5).mean()
df["ma10"] = df["Close"].rolling(10).mean()
delta = df["Close"].diff()
up = delta.clip(lower=0).rolling(14).mean()
down = (-delta.clip(upper=0)).rolling(14).mean()
df["rsi"] = 100 - 100 / (1 + (up / (down + 1e-9)))
return df.dropna().reset_index(drop=True)
def main(csv_path="data/stock_history.csv"):
if not os.path.exists(csv_path):
raise SystemExit(f"Data file not found: {csv_path}")
df = pd.read_csv(csv_path).sort_values("Date").reset_index(drop=True)
df = make_features(df)
df["label"] = (df["Close"].shift(-1) > df["Close"]).astype(int)
df = df.dropna().reset_index(drop=True)
feature_cols = ["Open","High","Low","Close","Volume","ma5","ma10","rsi","return"]
X = df[feature_cols].astype(float)
y = df["label"].astype(int)
X_train, X_test, y_train, y_test = train_test_split(
X, y, shuffle=False, test_size=0.2)
train_data = lgb.Dataset(X_train, label=y_train)
valid_data = lgb.Dataset(X_test, label=y_test)
params = {
"objective": "binary",
"metric": "binary_error",
"learning_rate": 0.05,
"num_leaves": 31,
"verbose": -1,
}
model = lgb.train(params, train_data, valid_sets=[valid_data], num_boost_round=200)
y_pred = (model.predict(X_test) > 0.5).astype(int)
acc = accuracy_score(y_test, y_pred)
print(f"Test accuracy: {acc:.4f}")
os.makedirs("model", exist_ok=True)
model.save_model("model/lgb_stock_model.txt")
joblib.dump(model, "model/lgb_stock_model.joblib")
n_features = X_train.shape[1]
initial_types = [("input", FloatTensorType([None, n_features]))]
onnx_model = convert_lightgbm(
model,
name="LGBMClassifier",
initial_types=initial_types,
target_opset=15,
)
onnx_path = "model/lgb_stock_model.onnx"
save_model(onnx_model, onnx_path)
print(f"Exported ONNX -> {onnx_path}")
if __name__ == "__main__":
csv = sys.argv[1] if len(sys.argv) > 1 else "data/stock_history.csv"
main(csv)The script stores the native LightGBM model ( .txt), a .joblib serialization, and an ONNX model compatible with ONNX Runtime 1.22.
3. Perform inference in Go using the ONNX Runtime Go binding
Install the Go binding: go get github.com/yalue/onnxruntime_go Inference program ( predict/predict_onnx.go) loads the shared library libonnxruntime.so.1.22.0, creates a tensor for the nine input features, runs the model, and reads the binary output.
// File: predict/predict_onnx.go
package main
import (
"fmt"
"log"
ort "github.com/yalue/onnxruntime_go"
)
func main() {
// Path to the ONNX Runtime shared library
ort.SetSharedLibraryPath("/home/sun/onnxruntime/lib/libonnxruntime.so.1.22.0")
// Initialise the runtime environment
if err := ort.InitializeEnvironment(); err != nil {
log.Fatal("Failed to initialize ONNX Runtime environment:", err)
}
defer ort.DestroyEnvironment()
// Example input: [Open, High, Low, Close, Volume, ma5, ma10, rsi, return]
inputData := []float32{100.0, 101.0, 99.5, 100.5, 1e6, 100.2, 100.3, 50.0, 0.005}
inputShape := ort.NewShape(1, 9) // batch size 1, 9 features
inputTensor, err := ort.NewTensor(inputShape, inputData)
if err != nil {
log.Fatal("Failed to create input tensor:", err)
}
defer inputTensor.Destroy()
// Output tensor for binary classification (int64)
outputShape := ort.NewShape(1)
outputTensor, err := ort.NewEmptyTensor[int64](outputShape)
if err != nil {
log.Fatal("Failed to create output tensor:", err)
}
defer outputTensor.Destroy()
// Build an advanced session with explicit I/O node names.
// Node names can be obtained from a Python ONNX Runtime session:
// sess.get_inputs()[0].name -> "input"
// sess.get_outputs()[0].name -> "label"
session, err := ort.NewAdvancedSession(
"./model/lgb_stock_model.onnx",
[]string{"input"},
[]string{"label"},
[]ort.Value{inputTensor},
[]ort.Value{outputTensor},
nil,
)
if err != nil {
log.Fatal("Failed to create session:", err)
}
defer session.Destroy()
// Run inference
if err := session.Run(); err != nil {
log.Fatal("Inference failed:", err)
}
// Retrieve and print the prediction (0 = down, 1 = up)
pred := outputTensor.GetData()
fmt.Println("Prediction result:", pred)
}Run the program: go run ./predict/predict_onnx.go Typical output:
Prediction result: [1]4. Project layout
go-stock-analyzer/
├── data/
│ └── stock_history.csv
├── model/
│ └── lgb_stock_model.onnx
├── predict/
│ ├── predict_onnx.go
│ └── train_lightgbm_to_onnx.py
└── go.modPython handles data preprocessing, model training and ONNX export; Go loads the exported model and performs low‑latency inference, providing a mixed‑language pipeline.
GitHub https://github.com/louis-xie-programmer/go-stock-analyzer
Gitee (mirror) https://gitee.com/louis_xie/go-stock-analyzer
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Wrench
Focuses on code debugging, performance optimization, and real-world engineering, sharing efficient development tips and pitfall guides. We break down technical challenges in a down-to-earth style, helping you craft handy tools so every line of code becomes a problem‑solving weapon. 🔧💻
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
