feat: expand quant templates to fifty projects

This commit is contained in:
root
2026-04-06 12:08:29 +00:00
parent 6976a0a528
commit 61a0d5b596
128 changed files with 5226 additions and 32 deletions
+52 -12
View File
@@ -26,20 +26,60 @@ Every project includes:
## Templates
This repository currently contains 50 PyP Quant strategy templates.
| Template | Pair | Timeframe | Model family | Use case |
| --- | --- | --- | --- | --- |
| `eurusd-logistic-15m` | EURUSD | 15m | sklearn | Baseline directional classifier |
| `eurusd-xgboost-1h` | EURUSD | 1h | XGBoost | Feature-rich trend classifier |
| `gbpusd-breakout-rf` | GBPUSD | 30m | sklearn RandomForest | Range breakout classifier |
| `usdjpy-mean-reversion` | USDJPY | 1h | sklearn | Mean reversion baseline |
| `xauusd-regime-xgboost-v11` | XAUUSD | 1h | XGBoost | Less restrictive Au-79-style gold model |
| `xauusd-atr-breakout` | XAUUSD | 15m | custom Python | ATR breakout rules |
| `btcusdt-lightgbm-1h` | BTCUSDT | 1h | LightGBM | Crypto trend classifier |
| `ethusdt-volatility-classifier` | ETHUSDT | 30m | sklearn | Volatility regime classifier |
| `solusdt-scalp-baseline` | SOLUSDT | 1m | custom Python | High-volatility scalp baseline |
| `onnx-export-sklearn-starter` | EURUSD | 1h | sklearn to ONNX | ONNX export starter |
| `statsmodels-arima-direction` | EURUSD | 1h | statsmodels | Statistical direction baseline |
| `lightgbm-fx-multifeature` | EURUSD | 30m | LightGBM | Multi-feature FX classifier |
| `adausdt-volatility-rf-15m` | ADAUSDT | 15m | sklearn RandomForest | sklearn RandomForest PyP Quant template for ADAUSDT 15m. |
| `audjpy-randomforest-1h` | AUDJPY | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for AUDJPY 1h. |
| `audusd-logistic-30m` | AUDUSD | 30m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for AUDUSD 30m. |
| `avaxusdt-volatility-rf-30m` | AVAXUSDT | 30m | sklearn RandomForest | sklearn RandomForest PyP Quant template for AVAXUSDT 30m. |
| `bnbusdt-trend-rf-30m` | BNBUSDT | 30m | sklearn RandomForest | sklearn RandomForest PyP Quant template for BNBUSDT 30m. |
| `brentoil-trend-rf-1h` | BRENTUSD | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for BRENTUSD 1h. |
| `btcusdt-breakout-rf-15m` | BTCUSDT | 15m | sklearn RandomForest | sklearn RandomForest PyP Quant template for BTCUSDT 15m. |
| `btcusdt-lightgbm-1h` | BTCUSDT | 1h | LightGBM | BTCUSDT LightGBM crypto trend classifier |
| `btcusdt-mean-reversion-5m` | BTCUSDT | 5m | custom Python | custom Python PyP Quant template for BTCUSDT 5m. |
| `cadjpy-breakout-1h` | CADJPY | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for CADJPY 1h. |
| `chfjpy-mean-reversion-1h` | CHFJPY | 1h | custom Python | custom Python PyP Quant template for CHFJPY 1h. |
| `copperusd-mean-reversion-1h` | COPPERUSD | 1h | custom Python | custom Python PyP Quant template for COPPERUSD 1h. |
| `dogeusdt-scalp-logistic-1m` | DOGEUSDT | 1m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for DOGEUSDT 1m. |
| `dotusdt-mean-reversion-30m` | DOTUSDT | 30m | custom Python | custom Python PyP Quant template for DOTUSDT 30m. |
| `ethusdt-volatility-classifier` | ETHUSDT | 30m | sklearn RandomForest | ETHUSDT volatility-aware directional classifier |
| `eurgbp-range-classifier-30m` | EURGBP | 30m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for EURGBP 30m. |
| `eurjpy-trend-rf-1h` | EURJPY | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for EURJPY 1h. |
| `eurnzd-volatility-rf-4h` | EURNZD | 4h | sklearn RandomForest | sklearn RandomForest PyP Quant template for EURNZD 4h. |
| `eurusd-logistic-15m` | EURUSD | 15m | sklearn LogisticRegression | EURUSD logistic regression baseline classifier |
| `eurusd-xgboost-1h` | EURUSD | 1h | XGBoost | EURUSD feature-rich XGBoost trend classifier |
| `gbpjpy-breakout-rf-1h` | GBPJPY | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for GBPJPY 1h. |
| `gbpusd-breakout-rf` | GBPUSD | 30m | sklearn RandomForest | GBPUSD range breakout random forest classifier |
| `gbpusd-logistic-15m` | GBPUSD | 15m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for GBPUSD 15m. |
| `ger40-breakout-rf-30m` | GER40 | 30m | sklearn RandomForest | sklearn RandomForest PyP Quant template for GER40 30m. |
| `lightgbm-fx-multifeature` | EURUSD | 30m | LightGBM | Multi-feature FX LightGBM classifier |
| `linkusdt-trend-logistic-30m` | LINKUSDT | 30m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for LINKUSDT 30m. |
| `ltcusdt-trend-rf-1h` | LTCUSDT | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for LTCUSDT 1h. |
| `maticusdt-scalp-baseline-5m` | MATICUSDT | 5m | custom Python | custom Python PyP Quant template for MATICUSDT 5m. |
| `nas100-breakout-rf-15m` | NAS100 | 15m | sklearn RandomForest | sklearn RandomForest PyP Quant template for NAS100 15m. |
| `naturalgas-volatility-rf-4h` | NATGAS | 4h | sklearn RandomForest | sklearn RandomForest PyP Quant template for NATGAS 4h. |
| `nzdusd-mean-reversion-1h` | NZDUSD | 1h | custom Python | custom Python PyP Quant template for NZDUSD 1h. |
| `oilwtico-atr-breakout-1h` | WTICOUSD | 1h | custom Python | custom Python PyP Quant template for WTICOUSD 1h. |
| `onnx-export-sklearn-starter` | EURUSD | 1h | sklearn to ONNX | Sklearn classifier starter for ONNX export |
| `solusdt-scalp-baseline` | SOLUSDT | 1m | custom Python | SOLUSDT high-volatility scalp baseline |
| `spx500-trend-logistic-1h` | SPX500 | 1h | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for SPX500 1h. |
| `statsmodels-arima-direction` | EURUSD | 1h | statsmodels | ARIMA-style statistical direction baseline |
| `uk100-range-logistic-1h` | UK100 | 1h | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for UK100 1h. |
| `us30-mean-reversion-30m` | US30 | 30m | custom Python | custom Python PyP Quant template for US30 30m. |
| `usdcad-trend-rf-1h` | USDCAD | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for USDCAD 1h. |
| `usdchf-range-logistic-1h` | USDCHF | 1h | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for USDCHF 1h. |
| `usdjpy-mean-reversion` | USDJPY | 1h | custom Python | USDJPY mean-reversion baseline |
| `usdmxn-volatility-rf-4h` | USDMXN | 4h | sklearn RandomForest | sklearn RandomForest PyP Quant template for USDMXN 4h. |
| `xagusd-atr-breakout-1h` | XAGUSD | 1h | custom Python | custom Python PyP Quant template for XAGUSD 1h. |
| `xagusd-mean-reversion-30m` | XAGUSD | 30m | custom Python | custom Python PyP Quant template for XAGUSD 30m. |
| `xauusd-atr-breakout` | XAUUSD | 15m | custom Python | XAUUSD ATR breakout rule baseline |
| `xauusd-london-breakout-15m` | XAUUSD | 15m | custom Python | custom Python PyP Quant template for XAUUSD 15m. |
| `xauusd-regime-xgboost-v11` | XAUUSD | 1h | XGBoost | Less restrictive Au-79-style XAUUSD regime classifier |
| `xauusd-scalp-logistic-5m` | XAUUSD | 5m | sklearn LogisticRegression | sklearn LogisticRegression PyP Quant template for XAUUSD 5m. |
| `xptusd-trend-rf-1h` | XPTUSD | 1h | sklearn RandomForest | sklearn RandomForest PyP Quant template for XPTUSD 1h. |
| `xrpusdt-breakout-rf-15m` | XRPUSDT | 15m | sklearn RandomForest | sklearn RandomForest PyP Quant template for XRPUSDT 15m. |
## Use With PyP
@@ -0,0 +1,29 @@
# adausdt-volatility-rf-15m
ADA volatility classifier for PyP Quant Mode.
This is an educational starter template for `ADAUSDT` on the `15m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `ADAUSDT`
- Timeframe: `15m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "adausdt-volatility-rf-15m",
"description": "sklearn RandomForest PyP Quant template for ADAUSDT 15m.",
"symbol": "ADAUSDT",
"timeframe": "15m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "ADAUSDT"
MODEL_NAME = "adausdt-volatility-rf-15m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.004))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 100)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# audjpy-randomforest-1h
AUDJPY carry-risk classifier for PyP Quant Mode.
This is an educational starter template for `AUDJPY` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `AUDJPY`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "audjpy-randomforest-1h",
"description": "sklearn RandomForest PyP Quant template for AUDJPY 1h.",
"symbol": "AUDJPY",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0018,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "AUDJPY"
MODEL_NAME = "audjpy-randomforest-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.0018))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# audusd-logistic-30m
AUDUSD momentum classifier for PyP Quant Mode.
This is an educational starter template for `AUDUSD` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `AUDUSD`
- Timeframe: `30m`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "audusd-logistic-30m",
"description": "sklearn LogisticRegression PyP Quant template for AUDUSD 30m.",
"symbol": "AUDUSD",
"timeframe": "30m",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.0012,
"min_confidence": 0.48,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+73
View File
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "AUDUSD"
MODEL_NAME = "audusd-logistic-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0012))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# avaxusdt-volatility-rf-30m
AVAX volatility classifier for PyP Quant Mode.
This is an educational starter template for `AVAXUSDT` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `AVAXUSDT`
- Timeframe: `30m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "avaxusdt-volatility-rf-30m",
"description": "sklearn RandomForest PyP Quant template for AVAXUSDT 30m.",
"symbol": "AVAXUSDT",
"timeframe": "30m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "AVAXUSDT"
MODEL_NAME = "avaxusdt-volatility-rf-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.004))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# bnbusdt-trend-rf-30m
BNB trend classifier for PyP Quant Mode.
This is an educational starter template for `BNBUSDT` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `BNBUSDT`
- Timeframe: `30m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "bnbusdt-trend-rf-30m",
"description": "sklearn RandomForest PyP Quant template for BNBUSDT 30m.",
"symbol": "BNBUSDT",
"timeframe": "30m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "BNBUSDT"
MODEL_NAME = "bnbusdt-trend-rf-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.004))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# brentoil-trend-rf-1h
Brent crude trend classifier for PyP Quant Mode.
This is an educational starter template for `BRENTUSD` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `BRENTUSD`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "brentoil-trend-rf-1h",
"description": "sklearn RandomForest PyP Quant template for BRENTUSD 1h.",
"symbol": "BRENTUSD",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.003,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "BRENTUSD"
MODEL_NAME = "brentoil-trend-rf-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.003))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# btcusdt-breakout-rf-15m
BTC breakout classifier for PyP Quant Mode.
This is an educational starter template for `BTCUSDT` on the `15m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `BTCUSDT`
- Timeframe: `15m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "btcusdt-breakout-rf-15m",
"description": "sklearn RandomForest PyP Quant template for BTCUSDT 15m.",
"symbol": "BTCUSDT",
"timeframe": "15m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,69 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
SYMBOL = "BTCUSDT"
MODEL_NAME = "btcusdt-breakout-rf-15m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
h = df["high"]
l = df["low"]
f = pd.DataFrame(index=df.index)
high_break = h.rolling(36).max().shift()
low_break = l.rolling(36).min().shift()
f["breakout_up"] = (c - high_break) / c
f["breakout_down"] = (c - low_break) / c
f["ret4"] = c.pct_change(4)
f["ret12"] = c.pct_change(12)
f["volatility"] = c.pct_change().rolling(24).std()
f["range_pct"] = (h - l) / c
f["ema_slope"] = c.ewm(span=12, adjust=False).mean().pct_change(6)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.004))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
clf = RandomForestClassifier(n_estimators=300, max_depth=7, min_samples_leaf=6, class_weight="balanced_subsample", random_state=42, n_jobs=-1)
clf.fit(x.values.astype(np.float32), y.values)
pred = clf.predict(x.values.astype(np.float32))
return {"model": clf, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 100)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1 +1,30 @@
{"pair":"BTCUSDT","timeframe":"1h","model_family":"lightgbm","runtime_target":"modal","artifact_format":"joblib_bundle","parameters":{"lookback":120,"horizon":3,"threshold":0.006,"min_confidence":0.46},"training_requirements":["numpy","pandas","scikit-learn","lightgbm","joblib"],"inference_requirements":["numpy","pandas","scikit-learn","lightgbm","joblib"]}
{
"pair": "BTCUSDT",
"timeframe": "1h",
"model_family": "LightGBM",
"runtime_target": "modal",
"artifact_format": "joblib_bundle",
"parameters": {
"lookback": 120,
"horizon": 3,
"threshold": 0.006,
"min_confidence": 0.46
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"lightgbm",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"lightgbm",
"joblib"
],
"symbol": "BTCUSDT",
"description": "BTCUSDT LightGBM crypto trend classifier",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,29 @@
# btcusdt-mean-reversion-5m
BTC mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `BTCUSDT` on the `5m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `BTCUSDT`
- Timeframe: `5m`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "btcusdt-mean-reversion-5m",
"description": "custom Python PyP Quant template for BTCUSDT 5m.",
"symbol": "BTCUSDT",
"timeframe": "5m",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "BTCUSDT"
MODEL_NAME = "btcusdt-mean-reversion-5m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 100))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# cadjpy-breakout-1h
CADJPY breakout classifier for PyP Quant Mode.
This is an educational starter template for `CADJPY` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `CADJPY`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "cadjpy-breakout-1h",
"description": "sklearn RandomForest PyP Quant template for CADJPY 1h.",
"symbol": "CADJPY",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0018,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+69
View File
@@ -0,0 +1,69 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
SYMBOL = "CADJPY"
MODEL_NAME = "cadjpy-breakout-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
h = df["high"]
l = df["low"]
f = pd.DataFrame(index=df.index)
high_break = h.rolling(36).max().shift()
low_break = l.rolling(36).min().shift()
f["breakout_up"] = (c - high_break) / c
f["breakout_down"] = (c - low_break) / c
f["ret4"] = c.pct_change(4)
f["ret12"] = c.pct_change(12)
f["volatility"] = c.pct_change().rolling(24).std()
f["range_pct"] = (h - l) / c
f["ema_slope"] = c.ewm(span=12, adjust=False).mean().pct_change(6)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0018))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
clf = RandomForestClassifier(n_estimators=300, max_depth=7, min_samples_leaf=6, class_weight="balanced_subsample", random_state=42, n_jobs=-1)
clf.fit(x.values.astype(np.float32), y.values)
pred = clf.predict(x.values.astype(np.float32))
return {"model": clf, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# chfjpy-mean-reversion-1h
CHFJPY mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `CHFJPY` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `CHFJPY`
- Timeframe: `1h`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "chfjpy-mean-reversion-1h",
"description": "custom Python PyP Quant template for CHFJPY 1h.",
"symbol": "CHFJPY",
"timeframe": "1h",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0018,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "CHFJPY"
MODEL_NAME = "chfjpy-mean-reversion-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 140))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# copperusd-mean-reversion-1h
Copper mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `COPPERUSD` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `COPPERUSD`
- Timeframe: `1h`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "copperusd-mean-reversion-1h",
"description": "custom Python PyP Quant template for COPPERUSD 1h.",
"symbol": "COPPERUSD",
"timeframe": "1h",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.003,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "COPPERUSD"
MODEL_NAME = "copperusd-mean-reversion-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 140))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# dogeusdt-scalp-logistic-1m
DOGE high-volatility scalp classifier for PyP Quant Mode.
This is an educational starter template for `DOGEUSDT` on the `1m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `DOGEUSDT`
- Timeframe: `1m`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "dogeusdt-scalp-logistic-1m",
"description": "sklearn LogisticRegression PyP Quant template for DOGEUSDT 1m.",
"symbol": "DOGEUSDT",
"timeframe": "1m",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.003,
"min_confidence": 0.48,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "DOGEUSDT"
MODEL_NAME = "dogeusdt-scalp-logistic-1m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.003))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# dotusdt-mean-reversion-30m
DOT mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `DOTUSDT` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `DOTUSDT`
- Timeframe: `30m`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "dotusdt-mean-reversion-30m",
"description": "custom Python PyP Quant template for DOTUSDT 30m.",
"symbol": "DOTUSDT",
"timeframe": "30m",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "DOTUSDT"
MODEL_NAME = "dotusdt-mean-reversion-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 120))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1 +1,28 @@
{"pair":"ETHUSDT","timeframe":"30m","model_family":"sklearn","runtime_target":"edge","artifact_format":"weights_bundle","parameters":{"lookback":120,"horizon":4,"threshold":0.005,"min_confidence":0.5},"training_requirements":["numpy","pandas","scikit-learn","joblib"],"inference_requirements":["numpy","pandas","scikit-learn","joblib"]}
{
"pair": "ETHUSDT",
"timeframe": "30m",
"model_family": "sklearn RandomForest",
"runtime_target": "edge",
"artifact_format": "weights_bundle",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.005,
"min_confidence": 0.5
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"symbol": "ETHUSDT",
"description": "ETHUSDT volatility-aware directional classifier",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,29 @@
# eurgbp-range-classifier-30m
EURGBP range classifier for PyP Quant Mode.
This is an educational starter template for `EURGBP` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `EURGBP`
- Timeframe: `30m`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "eurgbp-range-classifier-30m",
"description": "sklearn LogisticRegression PyP Quant template for EURGBP 30m.",
"symbol": "EURGBP",
"timeframe": "30m",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.0012,
"min_confidence": 0.48,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "EURGBP"
MODEL_NAME = "eurgbp-range-classifier-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0012))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# eurjpy-trend-rf-1h
EURJPY trend classifier for PyP Quant Mode.
This is an educational starter template for `EURJPY` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `EURJPY`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "eurjpy-trend-rf-1h",
"description": "sklearn RandomForest PyP Quant template for EURJPY 1h.",
"symbol": "EURJPY",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0018,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+72
View File
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "EURJPY"
MODEL_NAME = "eurjpy-trend-rf-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.0018))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# eurnzd-volatility-rf-4h
EURNZD volatility classifier for PyP Quant Mode.
This is an educational starter template for `EURNZD` on the `4h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `EURNZD`
- Timeframe: `4h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "eurnzd-volatility-rf-4h",
"description": "sklearn RandomForest PyP Quant template for EURNZD 4h.",
"symbol": "EURNZD",
"timeframe": "4h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 180,
"horizon": 6,
"threshold": 0.0012,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "EURNZD"
MODEL_NAME = "eurnzd-volatility-rf-4h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.0012))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 180)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1,7 +1,7 @@
{
"pair": "EURUSD",
"timeframe": "15m",
"model_family": "sklearn",
"model_family": "sklearn LogisticRegression",
"runtime_target": "edge",
"artifact_format": "weights_bundle",
"parameters": {
@@ -10,6 +10,19 @@
"threshold": 0.0008,
"min_confidence": 0.48
},
"training_requirements": ["numpy", "pandas", "scikit-learn", "joblib"],
"inference_requirements": ["numpy", "pandas", "scikit-learn", "joblib"]
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"symbol": "EURUSD",
"description": "EURUSD logistic regression baseline classifier",
"disclaimer": "Educational template only. Not financial advice."
}
+30 -1
View File
@@ -1 +1,30 @@
{"pair":"EURUSD","timeframe":"1h","model_family":"xgboost","runtime_target":"modal","artifact_format":"joblib_bundle","parameters":{"lookback":160,"horizon":3,"threshold":0.001,"min_confidence":0.48},"training_requirements":["numpy","pandas","scikit-learn","xgboost","joblib"],"inference_requirements":["numpy","pandas","scikit-learn","xgboost","joblib"]}
{
"pair": "EURUSD",
"timeframe": "1h",
"model_family": "XGBoost",
"runtime_target": "modal",
"artifact_format": "joblib_bundle",
"parameters": {
"lookback": 160,
"horizon": 3,
"threshold": 0.001,
"min_confidence": 0.48
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"xgboost",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"xgboost",
"joblib"
],
"symbol": "EURUSD",
"description": "EURUSD feature-rich XGBoost trend classifier",
"disclaimer": "Educational template only. Not financial advice."
}
+29
View File
@@ -0,0 +1,29 @@
# gbpjpy-breakout-rf-1h
GBPJPY breakout classifier for PyP Quant Mode.
This is an educational starter template for `GBPJPY` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `GBPJPY`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "gbpjpy-breakout-rf-1h",
"description": "sklearn RandomForest PyP Quant template for GBPJPY 1h.",
"symbol": "GBPJPY",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0018,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,69 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
SYMBOL = "GBPJPY"
MODEL_NAME = "gbpjpy-breakout-rf-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
h = df["high"]
l = df["low"]
f = pd.DataFrame(index=df.index)
high_break = h.rolling(36).max().shift()
low_break = l.rolling(36).min().shift()
f["breakout_up"] = (c - high_break) / c
f["breakout_down"] = (c - low_break) / c
f["ret4"] = c.pct_change(4)
f["ret12"] = c.pct_change(12)
f["volatility"] = c.pct_change().rolling(24).std()
f["range_pct"] = (h - l) / c
f["ema_slope"] = c.ewm(span=12, adjust=False).mean().pct_change(6)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0018))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
clf = RandomForestClassifier(n_estimators=300, max_depth=7, min_samples_leaf=6, class_weight="balanced_subsample", random_state=42, n_jobs=-1)
clf.fit(x.values.astype(np.float32), y.values)
pred = clf.predict(x.values.astype(np.float32))
return {"model": clf, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+28 -1
View File
@@ -1 +1,28 @@
{"pair":"GBPUSD","timeframe":"30m","model_family":"sklearn","runtime_target":"edge","artifact_format":"weights_bundle","parameters":{"lookback":120,"horizon":4,"threshold":0.0012,"min_confidence":0.5},"training_requirements":["numpy","pandas","scikit-learn","joblib"],"inference_requirements":["numpy","pandas","scikit-learn","joblib"]}
{
"pair": "GBPUSD",
"timeframe": "30m",
"model_family": "sklearn RandomForest",
"runtime_target": "edge",
"artifact_format": "weights_bundle",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.0012,
"min_confidence": 0.5
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib"
],
"symbol": "GBPUSD",
"description": "GBPUSD range breakout random forest classifier",
"disclaimer": "Educational template only. Not financial advice."
}
+29
View File
@@ -0,0 +1,29 @@
# gbpusd-logistic-15m
GBPUSD directional baseline for PyP Quant Mode.
This is an educational starter template for `GBPUSD` on the `15m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `GBPUSD`
- Timeframe: `15m`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "gbpusd-logistic-15m",
"description": "sklearn LogisticRegression PyP Quant template for GBPUSD 15m.",
"symbol": "GBPUSD",
"timeframe": "15m",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.0012,
"min_confidence": 0.48,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+73
View File
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "GBPUSD"
MODEL_NAME = "gbpusd-logistic-15m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0012))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 100)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# ger40-breakout-rf-30m
DAX breakout classifier for PyP Quant Mode.
This is an educational starter template for `GER40` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `GER40`
- Timeframe: `30m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "ger40-breakout-rf-30m",
"description": "sklearn RandomForest PyP Quant template for GER40 30m.",
"symbol": "GER40",
"timeframe": "30m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.0025,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,69 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
SYMBOL = "GER40"
MODEL_NAME = "ger40-breakout-rf-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
h = df["high"]
l = df["low"]
f = pd.DataFrame(index=df.index)
high_break = h.rolling(36).max().shift()
low_break = l.rolling(36).min().shift()
f["breakout_up"] = (c - high_break) / c
f["breakout_down"] = (c - low_break) / c
f["ret4"] = c.pct_change(4)
f["ret12"] = c.pct_change(12)
f["volatility"] = c.pct_change().rolling(24).std()
f["range_pct"] = (h - l) / c
f["ema_slope"] = c.ewm(span=12, adjust=False).mean().pct_change(6)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0025))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
clf = RandomForestClassifier(n_estimators=300, max_depth=7, min_samples_leaf=6, class_weight="balanced_subsample", random_state=42, n_jobs=-1)
clf.fit(x.values.astype(np.float32), y.values)
pred = clf.predict(x.values.astype(np.float32))
return {"model": clf, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1 +1,30 @@
{"pair":"EURUSD","timeframe":"30m","model_family":"lightgbm","runtime_target":"modal","artifact_format":"joblib_bundle","parameters":{"lookback":140,"horizon":4,"threshold":0.001,"min_confidence":0.48},"training_requirements":["numpy","pandas","scikit-learn","lightgbm","joblib"],"inference_requirements":["numpy","pandas","scikit-learn","lightgbm","joblib"]}
{
"pair": "EURUSD",
"timeframe": "30m",
"model_family": "LightGBM",
"runtime_target": "modal",
"artifact_format": "joblib_bundle",
"parameters": {
"lookback": 140,
"horizon": 4,
"threshold": 0.001,
"min_confidence": 0.48
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"lightgbm",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"scikit-learn",
"lightgbm",
"joblib"
],
"symbol": "EURUSD",
"description": "Multi-feature FX LightGBM classifier",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,29 @@
# linkusdt-trend-logistic-30m
LINK trend classifier for PyP Quant Mode.
This is an educational starter template for `LINKUSDT` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `LINKUSDT`
- Timeframe: `30m`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "linkusdt-trend-logistic-30m",
"description": "sklearn LogisticRegression PyP Quant template for LINKUSDT 30m.",
"symbol": "LINKUSDT",
"timeframe": "30m",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.003,
"min_confidence": 0.48,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "LINKUSDT"
MODEL_NAME = "linkusdt-trend-logistic-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.003))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 120)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# ltcusdt-trend-rf-1h
LTC trend classifier for PyP Quant Mode.
This is an educational starter template for `LTCUSDT` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `LTCUSDT`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "ltcusdt-trend-rf-1h",
"description": "sklearn RandomForest PyP Quant template for LTCUSDT 1h.",
"symbol": "LTCUSDT",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+72
View File
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "LTCUSDT"
MODEL_NAME = "ltcusdt-trend-rf-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.004))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# maticusdt-scalp-baseline-5m
MATIC scalp baseline for PyP Quant Mode.
This is an educational starter template for `MATICUSDT` on the `5m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `MATICUSDT`
- Timeframe: `5m`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "maticusdt-scalp-baseline-5m",
"description": "custom Python PyP Quant template for MATICUSDT 5m.",
"symbol": "MATICUSDT",
"timeframe": "5m",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.004,
"min_confidence": 0.5,
"sl_percent": 0.4,
"tp_percent": 0.8
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,53 @@
import numpy as np
import pandas as pd
SYMBOL = "MATICUSDT"
MODEL_NAME = "maticusdt-scalp-baseline-5m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _atr(df, n=14):
h, l, c = df["high"], df["low"], df["close"]
tr = pd.concat([(h - l), (h - c.shift()).abs(), (l - c.shift()).abs()], axis=1).max(axis=1)
return tr.ewm(span=n, adjust=False).mean()
def train(data, config):
p = config.get("parameters", {})
return {"atr_window": int(p.get("atr_window", 14)), "breakout_window": int(p.get("breakout_window", 36)), "atr_mult": float(p.get("atr_mult", 0.25)), "symbol": SYMBOL}, {"model_family": "rule_based_atr_breakout", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 100))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
atr_window = int(model.get("atr_window", p.get("atr_window", 14)))
breakout_window = int(model.get("breakout_window", p.get("breakout_window", 36)))
atr_mult = float(model.get("atr_mult", p.get("atr_mult", 0.25)))
atr = _atr(df, atr_window)
close = float(df["close"].iloc[-1])
upper = float(df["high"].rolling(breakout_window).max().shift().iloc[-1] + atr.iloc[-1] * atr_mult)
lower = float(df["low"].rolling(breakout_window).min().shift().iloc[-1] - atr.iloc[-1] * atr_mult)
signal = "HOLD"
distance = 0.0
if close > upper:
signal = "UP"
distance = (close - upper) / max(atr.iloc[-1], 1e-9)
elif close < lower:
signal = "DOWN"
distance = (lower - close) / max(atr.iloc[-1], 1e-9)
confidence = min(max(distance, 0.0), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"upper": round(upper, 6), "lower": round(lower, 6), "close": round(close, 6), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# nas100-breakout-rf-15m
NASDAQ index breakout classifier for PyP Quant Mode.
This is an educational starter template for `NAS100` on the `15m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `NAS100`
- Timeframe: `15m`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "nas100-breakout-rf-15m",
"description": "sklearn RandomForest PyP Quant template for NAS100 15m.",
"symbol": "NAS100",
"timeframe": "15m",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 100,
"horizon": 4,
"threshold": 0.0025,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,69 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
SYMBOL = "NAS100"
MODEL_NAME = "nas100-breakout-rf-15m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
h = df["high"]
l = df["low"]
f = pd.DataFrame(index=df.index)
high_break = h.rolling(36).max().shift()
low_break = l.rolling(36).min().shift()
f["breakout_up"] = (c - high_break) / c
f["breakout_down"] = (c - low_break) / c
f["ret4"] = c.pct_change(4)
f["ret12"] = c.pct_change(12)
f["volatility"] = c.pct_change().rolling(24).std()
f["range_pct"] = (h - l) / c
f["ema_slope"] = c.ewm(span=12, adjust=False).mean().pct_change(6)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0025))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
clf = RandomForestClassifier(n_estimators=300, max_depth=7, min_samples_leaf=6, class_weight="balanced_subsample", random_state=42, n_jobs=-1)
clf.fit(x.values.astype(np.float32), y.values)
pred = clf.predict(x.values.astype(np.float32))
return {"model": clf, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 100)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# naturalgas-volatility-rf-4h
Natural gas volatility classifier for PyP Quant Mode.
This is an educational starter template for `NATGAS` on the `4h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `NATGAS`
- Timeframe: `4h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "naturalgas-volatility-rf-4h",
"description": "sklearn RandomForest PyP Quant template for NATGAS 4h.",
"symbol": "NATGAS",
"timeframe": "4h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 180,
"horizon": 6,
"threshold": 0.003,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "NATGAS"
MODEL_NAME = "naturalgas-volatility-rf-4h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.003))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 180)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# nzdusd-mean-reversion-1h
NZDUSD mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `NZDUSD` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `NZDUSD`
- Timeframe: `1h`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "nzdusd-mean-reversion-1h",
"description": "custom Python PyP Quant template for NZDUSD 1h.",
"symbol": "NZDUSD",
"timeframe": "1h",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0012,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "NZDUSD"
MODEL_NAME = "nzdusd-mean-reversion-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 140))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# oilwtico-atr-breakout-1h
WTI crude oil ATR breakout baseline for PyP Quant Mode.
This is an educational starter template for `WTICOUSD` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `WTICOUSD`
- Timeframe: `1h`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "oilwtico-atr-breakout-1h",
"description": "custom Python PyP Quant template for WTICOUSD 1h.",
"symbol": "WTICOUSD",
"timeframe": "1h",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.003,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,53 @@
import numpy as np
import pandas as pd
SYMBOL = "WTICOUSD"
MODEL_NAME = "oilwtico-atr-breakout-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _atr(df, n=14):
h, l, c = df["high"], df["low"], df["close"]
tr = pd.concat([(h - l), (h - c.shift()).abs(), (l - c.shift()).abs()], axis=1).max(axis=1)
return tr.ewm(span=n, adjust=False).mean()
def train(data, config):
p = config.get("parameters", {})
return {"atr_window": int(p.get("atr_window", 14)), "breakout_window": int(p.get("breakout_window", 36)), "atr_mult": float(p.get("atr_mult", 0.25)), "symbol": SYMBOL}, {"model_family": "rule_based_atr_breakout", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 140))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
atr_window = int(model.get("atr_window", p.get("atr_window", 14)))
breakout_window = int(model.get("breakout_window", p.get("breakout_window", 36)))
atr_mult = float(model.get("atr_mult", p.get("atr_mult", 0.25)))
atr = _atr(df, atr_window)
close = float(df["close"].iloc[-1])
upper = float(df["high"].rolling(breakout_window).max().shift().iloc[-1] + atr.iloc[-1] * atr_mult)
lower = float(df["low"].rolling(breakout_window).min().shift().iloc[-1] - atr.iloc[-1] * atr_mult)
signal = "HOLD"
distance = 0.0
if close > upper:
signal = "UP"
distance = (close - upper) / max(atr.iloc[-1], 1e-9)
elif close < lower:
signal = "DOWN"
distance = (lower - close) / max(atr.iloc[-1], 1e-9)
confidence = min(max(distance, 0.0), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"upper": round(upper, 6), "lower": round(lower, 6), "close": round(close, 6), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1 +1,28 @@
{"pair":"EURUSD","timeframe":"1h","model_family":"sklearn","runtime_target":"container","artifact_format":"onnx","parameters":{"lookback":120,"horizon":3,"threshold":0.001,"min_confidence":0.5},"training_requirements":["numpy","pandas","scikit-learn","joblib","skl2onnx","onnx"],"inference_requirements":["numpy","onnxruntime"]}
{
"pair": "EURUSD",
"timeframe": "1h",
"model_family": "sklearn to ONNX",
"runtime_target": "container",
"artifact_format": "onnx",
"parameters": {
"lookback": 120,
"horizon": 3,
"threshold": 0.001,
"min_confidence": 0.5
},
"training_requirements": [
"numpy",
"pandas",
"scikit-learn",
"joblib",
"skl2onnx",
"onnx"
],
"inference_requirements": [
"numpy",
"onnxruntime"
],
"symbol": "EURUSD",
"description": "Sklearn classifier starter for ONNX export",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -1,7 +1,7 @@
{
"pair": "SOLUSDT",
"timeframe": "1m",
"model_family": "custom_python",
"model_family": "custom Python",
"runtime_target": "edge",
"artifact_format": "python_bundle",
"parameters": {
@@ -11,6 +11,15 @@
"vol_window": 20,
"min_move": 0.0006
},
"training_requirements": ["numpy", "pandas"],
"inference_requirements": ["numpy", "pandas"]
"training_requirements": [
"numpy",
"pandas"
],
"inference_requirements": [
"numpy",
"pandas"
],
"symbol": "SOLUSDT",
"description": "SOLUSDT high-volatility scalp baseline",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,29 @@
# spx500-trend-logistic-1h
S&P 500 trend classifier for PyP Quant Mode.
This is an educational starter template for `SPX500` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `SPX500`
- Timeframe: `1h`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "spx500-trend-logistic-1h",
"description": "sklearn LogisticRegression PyP Quant template for SPX500 1h.",
"symbol": "SPX500",
"timeframe": "1h",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0025,
"min_confidence": 0.48,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "SPX500"
MODEL_NAME = "spx500-trend-logistic-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0025))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -1 +1,26 @@
{"pair":"EURUSD","timeframe":"1h","model_family":"statsmodels","runtime_target":"modal","artifact_format":"joblib_bundle","parameters":{"lookback":96,"entry_threshold":0.0004},"training_requirements":["numpy","pandas","statsmodels","joblib"],"inference_requirements":["numpy","pandas","statsmodels","joblib"]}
{
"pair": "EURUSD",
"timeframe": "1h",
"model_family": "statsmodels",
"runtime_target": "modal",
"artifact_format": "joblib_bundle",
"parameters": {
"lookback": 96,
"entry_threshold": 0.0004
},
"training_requirements": [
"numpy",
"pandas",
"statsmodels",
"joblib"
],
"inference_requirements": [
"numpy",
"pandas",
"statsmodels",
"joblib"
],
"symbol": "EURUSD",
"description": "ARIMA-style statistical direction baseline",
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,29 @@
# uk100-range-logistic-1h
FTSE range classifier for PyP Quant Mode.
This is an educational starter template for `UK100` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `UK100`
- Timeframe: `1h`
- Family: `sklearn LogisticRegression`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "uk100-range-logistic-1h",
"description": "sklearn LogisticRegression PyP Quant template for UK100 1h.",
"symbol": "UK100",
"timeframe": "1h",
"model_family": "sklearn LogisticRegression",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0025,
"min_confidence": 0.48,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
SYMBOL = "UK100"
MODEL_NAME = "uk100-range-logistic-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
rng = (df["high"] - df["low"]).replace(0, np.nan)
f = pd.DataFrame(index=df.index)
for n in [1, 3, 6, 12, 24]:
f[f"ret{n}"] = c.pct_change(n)
f["range_pct"] = rng / c
f["body_pct"] = (c - df["open"]) / (rng + 1e-9)
f["close_pos"] = (c - df["low"]) / (rng + 1e-9)
f["ema_8_21"] = (c.ewm(span=8, adjust=False).mean() - c.ewm(span=21, adjust=False).mean()) / c
f["ema_21_55"] = (c.ewm(span=21, adjust=False).mean() - c.ewm(span=55, adjust=False).mean()) / c
f["volatility"] = c.pct_change().rolling(24).std()
f["volume_ratio"] = df["volume"] / (df["volume"].rolling(24).mean() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 4))
threshold = float(p.get("threshold", 0.0025))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000, class_weight="balanced")),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.48)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}
@@ -0,0 +1,29 @@
# us30-mean-reversion-30m
Dow index mean-reversion baseline for PyP Quant Mode.
This is an educational starter template for `US30` on the `30m` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `US30`
- Timeframe: `30m`
- Family: `custom Python`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,21 @@
{
"name": "us30-mean-reversion-30m",
"description": "custom Python PyP Quant template for US30 30m.",
"symbol": "US30",
"timeframe": "30m",
"model_family": "custom Python",
"artifact_target": "python",
"parameters": {
"lookback": 120,
"horizon": 4,
"threshold": 0.0025,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas"
],
"disclaimer": "Educational template only. Not financial advice."
}
@@ -0,0 +1,46 @@
import numpy as np
import pandas as pd
SYMBOL = "US30"
MODEL_NAME = "us30-mean-reversion-30m"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _zscore(close, window):
mean = close.rolling(window).mean()
std = close.rolling(window).std()
return (close - mean) / (std + 1e-9)
def train(data, config):
p = config.get("parameters", {})
return {"window": int(p.get("window", 48)), "entry_z": float(p.get("entry_z", 1.4)), "exit_z": float(p.get("exit_z", 0.3)), "symbol": SYMBOL}, {"model_family": "rule_based_mean_reversion", "training_bars": int(len(data))}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
lookback = int(p.get("lookback", 120))
if len(candles) < lookback:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
window = int(model.get("window", p.get("window", 48)))
z = float(_zscore(df["close"], window).iloc[-1])
entry_z = float(model.get("entry_z", p.get("entry_z", 1.4)))
signal = "HOLD"
if z <= -entry_z:
signal = "UP"
elif z >= entry_z:
signal = "DOWN"
confidence = min(abs(z) / max(entry_z, 1e-9), 1.0)
return {"signal": signal, "confidence": round(float(confidence), 4), "metadata": {"zscore": round(z, 4), "window": window, "model": MODEL_NAME, "symbol": SYMBOL}}
+29
View File
@@ -0,0 +1,29 @@
# usdcad-trend-rf-1h
USDCAD trend classifier for PyP Quant Mode.
This is an educational starter template for `USDCAD` on the `1h` timeframe. It implements the PyP Quant contract:
```python
train(data, config)
predict(model, market_data, config)
```
Use it as a baseline, then validate with PPE before any live deployment.
## Model
- Symbol: `USDCAD`
- Timeframe: `1h`
- Family: `sklearn RandomForest`
- Output: `UP`, `DOWN`, or `HOLD`
## PyP Links
- Quant docs: https://pyp.stanl.ink/docs/quant/what-is-quant-mode
- Quant landing page: https://pyp.stanl.ink/for-quant-traders
- Create project: https://pyp.stanlink.online/projects/quant/new
## Risk
This is not financial advice and is not a verified profitable strategy.
@@ -0,0 +1,22 @@
{
"name": "usdcad-trend-rf-1h",
"description": "sklearn RandomForest PyP Quant template for USDCAD 1h.",
"symbol": "USDCAD",
"timeframe": "1h",
"model_family": "sklearn RandomForest",
"artifact_target": "joblib",
"parameters": {
"lookback": 140,
"horizon": 6,
"threshold": 0.0012,
"min_confidence": 0.5,
"sl_percent": 0.25,
"tp_percent": 0.5
},
"requirements": [
"numpy",
"pandas",
"scikit-learn"
],
"disclaimer": "Educational template only. Not financial advice."
}
+72
View File
@@ -0,0 +1,72 @@
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
SYMBOL = "USDCAD"
MODEL_NAME = "usdcad-trend-rf-1h"
def _prep(data):
df = data.copy()
df.columns = [str(c).strip().lower() for c in df.columns]
if "volume" not in df.columns:
df["volume"] = 1.0
for col in ["open", "high", "low", "close", "volume"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
def _features(df):
c = df["close"]
v = df["volume"]
f = pd.DataFrame(index=df.index)
for n in [1, 4, 8, 16, 32, 64]:
f[f"ret{n}"] = c.pct_change(n)
f["ema_12_48"] = (c.ewm(span=12, adjust=False).mean() - c.ewm(span=48, adjust=False).mean()) / c
f["ema_24_96"] = (c.ewm(span=24, adjust=False).mean() - c.ewm(span=96, adjust=False).mean()) / c
f["volatility_fast"] = c.pct_change().rolling(16).std()
f["volatility_slow"] = c.pct_change().rolling(64).std()
f["volatility_ratio"] = f["volatility_fast"] / (f["volatility_slow"] + 1e-9)
f["volume_z"] = (v - v.rolling(48).mean()) / (v.rolling(48).std() + 1e-9)
return f.replace([np.inf, -np.inf], np.nan).dropna()
def train(data, config):
p = config.get("parameters", {})
df = _prep(data)
x = _features(df)
horizon = int(p.get("horizon", 6))
threshold = float(p.get("threshold", 0.0012))
fwd = df["close"].pct_change(horizon).shift(-horizon)
y = pd.Series(1, index=df.index)
y[fwd > threshold] = 2
y[fwd < -threshold] = 0
y = y.reindex(x.index).fillna(1).astype(int)
model = Pipeline([
("scaler", StandardScaler()),
("clf", RandomForestClassifier(n_estimators=350, max_depth=8, min_samples_leaf=8, class_weight="balanced_subsample", random_state=42, n_jobs=-1)),
])
model.fit(x.values.astype(np.float32), y.values)
pred = model.predict(x.values.astype(np.float32))
return {"model": model, "features": list(x.columns), "symbol": SYMBOL}, {"training_bars": int(len(x)), "feature_count": int(x.shape[1]), "buy_signals": int((pred == 2).sum()), "sell_signals": int((pred == 0).sum()), "hold_signals": int((pred == 1).sum())}
def predict(model, market_data, config):
p = config.get("parameters", {})
candles = market_data.get("candles", [])
if len(candles) < int(p.get("lookback", 140)):
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "not_enough_candles", "model": MODEL_NAME}}
df = _prep(pd.DataFrame(candles, columns=["open", "high", "low", "close", "volume"]))
row = _features(df).tail(1)
if row.empty:
return {"signal": "HOLD", "confidence": 0.0, "metadata": {"reason": "no_features", "model": MODEL_NAME}}
prob = model["model"].predict_proba(row[model["features"]].values.astype(np.float32))[0]
klass = int(np.argmax(prob))
conf = float(np.max(prob))
signal = {0: "DOWN", 1: "HOLD", 2: "UP"}[klass]
if conf < float(p.get("min_confidence", 0.5)):
signal = "HOLD"
return {"signal": signal, "confidence": round(conf, 4), "metadata": {"p_sell": round(float(prob[0]), 4), "p_hold": round(float(prob[1]), 4), "p_buy": round(float(prob[2]), 4), "model": MODEL_NAME, "symbol": SYMBOL}}

Some files were not shown because too many files have changed in this diff Show More