# app.py from flask import Flask, render_template, jsonify, request import pandas as pd from longshort_core import load_mt5_csv, make_features, FEATURES, auto_thresholds, load_or_train_model, build_payload_for_chart CSV_PATH = "data/XAUUSD_M15.csv" SUMMARY_PATH = "data/wf_summary_longshort.csv" app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") # nến + signal @app.route("/equity") def equity(): return render_template("equity.html") @app.route("/api/candles") def api_candles(): n = int(request.args.get("n", 500)) df = load_mt5_csv(CSV_PATH) feat = make_features(df) # y để train nhanh nếu chưa có model y = (feat['Close'].shift(-1)/feat['Close'] - 1.0 > 0).astype(int) data = feat.join(y.rename('y')).dropna() X = data[FEATURES]; y = data['y'] thrL, thrS, dz = auto_thresholds(SUMMARY_PATH) model = load_or_train_model(X, y, model_path="models/live_lgb.txt") prob = pd.Series(model.predict(X), index=X.index) payload = build_payload_for_chart(df.loc[X.index], prob, thrL, thrS, dz, n_last=n) return jsonify(payload) @app.route("/api/latest") def api_latest(): from datetime import datetime df = load_mt5_csv(CSV_PATH) feat = make_features(df) y = (feat['Close'].shift(-1)/feat['Close'] - 1.0 > 0).astype(int) data = feat.join(y.rename('y')).dropna() X = data[FEATURES]; y = data['y'] thrL, thrS, dz = auto_thresholds(SUMMARY_PATH) model = load_or_train_model(X, y, model_path="models/live_lgb.txt") prob = model.predict(X.iloc[[-1]])[0] ts = X.index[-1].strftime("%Y-%m-%d %H:%M:%S") sig = 0 if abs(prob-0.5) < dz: sig = 0 elif prob > thrL: sig = 1 elif prob < thrS: sig = -1 return jsonify(dict(time=ts, close=float(data['Close'].iloc[-1]), prob_up=float(prob), thrL=thrL, thrS=thrS, dz=dz, signal=int(sig))) @app.route("/api/equity") def api_equity(): try: eq = pd.read_csv("data/wf_equity_curve_longshort.csv") except: eq = pd.read_csv("data/wf_equity_curve.csv") # fallback return jsonify(dict(time=eq.iloc[:,0].tolist(), equity=eq.iloc[:,1].round(4).tolist())) if __name__ == "__main__": app.run(debug=True)