428-backtester/scripts/apply_hyperopt_params.sh
Artemii Peretiachenko 99de26e7f0 Add private Freqtrade scaffold for partner backtesting.
Ship SampleStrategy and Integral workflow scripts without proprietary V15 logic, Pine, or run results.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-02 23:55:44 +02:00

83 lines
2.4 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# shellcheck disable=SC1091
source "$(dirname "$0")/_env.sh"
# Export best (or N-th) hyperopt epoch into strategy params JSON so backtesting
# picks them up: user_data/strategies/<Strategy>.json
STRATEGY="${STRATEGY:-SampleStrategy}"
EPOCH="${EPOCH:--1}"
OUT="${OUT:-user_data/strategies/${STRATEGY}.json}"
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT
freqtrade hyperopt-show \
--config user_data/config.json \
-n "${EPOCH}" \
--print-json \
--no-header >"$TMP"
PYTHON_BIN="${ROOT}/.venv/bin/python"
if [[ ! -x "${PYTHON_BIN}" ]]; then
PYTHON_BIN="$(command -v python3)"
fi
"${PYTHON_BIN}" - "$TMP" "$STRATEGY" "$OUT" <<'PY'
import json, sys
from pathlib import Path
src, strategy, out = sys.argv[1], sys.argv[2], sys.argv[3]
raw = Path(src).read_text().strip()
# hyperopt-show may print log noise; keep the last JSON object
start = raw.rfind("{")
if start < 0:
raise SystemExit(f"No JSON found in hyperopt-show output:\n{raw[:500]}")
payload = json.loads(raw[start:])
KNOWN = ("buy", "sell", "roi", "stoploss", "trailing", "protection")
def expand_tp_combo(sell: dict) -> dict:
"""If sell has tp_rr_combo 'a,b,c', mirror into tp1_rr/tp2_rr/tp3_rr."""
combo = sell.get("tp_rr_combo")
if combo is None:
return sell
if isinstance(combo, (list, tuple)) and len(combo) == 3:
a, b, c = (float(x) for x in combo)
sell["tp_rr_combo"] = f"{a},{b},{c}"
elif isinstance(combo, str) and "," in combo:
a, b, c = (float(x) for x in combo.split(","))
else:
return sell
sell["tp1_rr"] = a
sell["tp2_rr"] = b
sell["tp3_rr"] = c
return sell
def as_params(obj: dict) -> dict:
if "params" in obj and isinstance(obj["params"], dict):
raw_params = obj["params"]
if any(k in raw_params for k in KNOWN):
params = {k: v for k, v in raw_params.items() if k in KNOWN}
else:
params = {"buy": raw_params} if raw_params else {}
elif any(k in obj for k in KNOWN):
params = {k: v for k, v in obj.items() if k in KNOWN}
else:
params = {"buy": obj} if obj else {}
if "sell" in params and isinstance(params["sell"], dict):
params["sell"] = expand_tp_combo(dict(params["sell"]))
return params
params = as_params(payload)
doc = {
"strategy_name": strategy,
"params": params,
}
Path(out).write_text(json.dumps(doc, indent=2) + "\n")
print(f"Wrote {out}")
print(json.dumps(params, indent=2))
PY