Skip to the page
On this page

Documentation

How to read and edit the Python file QuantifyMe writes for a strategy, and how to drive the whole platform over HTTP. One call takes a sentence to a live model.

Start here

Get an API key

Every authenticated call sends an X-API-Key header. A trial key needs no account and no email: it is temporary, carries 10,000 credits and is kept in this browser. Sign in for a permanent personal key.

No key yet

No account needed. One click makes a temporary key.

A script or an agent mints its own key the same way, with one request and no body.

curl
curl -X POST https://api.quantifyme.ai/api/v1/key/trial
# {"api_key": "qm_...", "username": "trial_...", "is_trial": true}

Deploy from one sentence

Describe a strategy in one line. QuantifyMe writes the code, trains a model on recent prices, and deploys it live. It usually takes under a minute.

Free to try, no signup

    The four steps the server reports. Usually under a minute.

    Stop only stops watching. The run finishes on the server and its model appears in your Backtesting list.

    Open the live model

    Training and validation

    TrainingValidation
    • A market named in the sentence wins. "EURUSD 1min RSI reversal" moves the two pickers to EURUSD and 1 min before the run starts, so you can see what is about to train.
    • How much history a run trains on depends on the timeframe. On a free or trial key it is the last 40 days at 15 min and 1 h, 18 days at 5 min and 4 days at 1 min.
    • A link can fill the box: /docs?prompt=Buy+when+RSI+hits+30#quick-deploy. Add run=1 and the deploy starts by itself, which is how an AI assistant hands a strategy over in one click.

    The same request over the API

    This is what ChatGPT, Claude or your own script sends. The sample follows what you type above and the market you pick.

    POST https://api.quantifyme.ai/api/v1/one_shot
    X-API-Key: qm_YOUR_KEY
    Content-Type: application/json
    
    {
      "prompt": "Buy when RSI hits 30, sell when RSI hits 70",
      "symbol": "EURUSD",
      "timeframe": "15min",
      "deliver_to": { "webhook": "https://example.com/hook" }
    }

    The response is a stream of server-sent events. Field by field: POST /api/v1/one_shot.

    For AI agents

    /llms.txt is a plain-text version of this documentation written for AI assistants such as ChatGPT, Claude and Gemini. Paste the URL into any AI chat and it can help you write or change your strategy code: it already knows the signal convention, the file structure and the common patterns.

    It follows the llms.txt standard, a plain-text file at the root of the domain that an assistant can read. The same contract is published in two more machine-readable forms.

    FileWhat it is
    /llms.txtThis documentation as plain text, at quantifyme.ai/llms.txt
    /openapi.jsonThe full catalogue of paths, as OpenAPI
    /api/v1/docsThe core endpoints as JSON, with examples

    Strategy code

    Every strategy QuantifyMe generates is one self-contained Python file. This part explains how to read it, what each section does, and how to make the common edits, with a map for anyone coming from PineScript.

    How it works

    A generated strategy file has exactly two functions: feature_engineering() and strategy_config(). You describe the strategy through those two, and the framework does everything else. It builds and trains the model, turns its probabilities into buy, sell and flat signals, applies your position, session and trend filters, runs the walk-forward backtest with your stop loss, take profit and cooldown, and computes every metric.

    There is no build_model, generate_signals, apply_risk or train_and_backtest to edit any more. Older docs that mention "7 numbered sections" describe the framework before 2026.

    You writeWhat it does
    feature_engineering(df, close, open_, high, low)Add indicator and pattern columns to df and return it. Every new column becomes an ML feature. No look-ahead, end with .bfill().ffill(), and do not drop rows.
    strategy_config(), returns a dictOne dict: model_type and model_params, signal_threshold, direction, stop_loss, take_profit, cooldown, max_positions, on_opposite, session_filter, min_atr, trend_filter, target_horizon, plus title, objective and notes.

    Backtest basics. Walk-forward, with no look-ahead. Entry is on the next bar's open after a signal. Stop loss and take profit are checked inside the bar against its high and low. Commission is charged on every position change. Data is forex OHLC for any of 7 majors (EUR/USD, GBP/USD, USD/JPY, USD/CHF, AUD/USD, NZD/USD, USD/CAD) at 1 min, 5 min, 15 min and 1 h. Pick it with the symbol and timeframe fields.

    The strategy file

    The whole file is two functions and a small header. You add features in the first function and set the knobs in the second.

    Python
    # SECTION 0 - IMPORTS AND CONSTANTS  (do not change these)
    import numpy as np
    import pandas as pd
    DATA_PATH = "..."; START_DATE = "..."; END_DATE = "..."; VALIDATION_DATE = ""; TRAIN_SPLIT = 0.7
    
    # SECTION 1 - FEATURE ENGINEERING  (add columns here; each one becomes an ML feature)
    def feature_engineering(df, close, open_, high, low):
        df['rsi_14'] = _rsi(close, 14)
        df['ema_20'] = close.ewm(span=20, adjust=False).mean()
        df['ema_50'] = close.ewm(span=50, adjust=False).mean()
        df['ret_1']  = close.pct_change()
        df = df.bfill().ffill()   # fill indicator warm-up NaNs: required
        return df
    
    # SECTION 2 - STRATEGY CONFIG  (every key required)
    def strategy_config():
        return {
            "model_type":       "XGBClassifier",
            "model_params":     {"n_estimators": 300, "max_depth": 4, "learning_rate": 0.05},
            "signal_threshold": 0.55,         # predict_proba cutoff for a signal
            "direction":        "both",       # "both" | "long" | "short"
            "stop_loss":        0.005,        # 0.5%, a decimal ratio, or None
            "take_profit":      0.01,         # 1.0%, a decimal ratio, or None
            "cooldown":         0,            # bars to wait after a close before re-entry
            "max_positions":    1,
            "on_opposite":      "reverse",    # "reverse" (flip) | "close_only" (go flat)
            "session_filter":   None,         # [start_hour, end_hour] UTC, e.g. [7, 16]
            "min_atr":          None,         # minimum NATR to allow entries
            "trend_filter":     None,         # e.g. "sma_50": longs above, shorts below
            "target_horizon":   4,            # bars ahead the model predicts (4 is about 1 h on 15 min)
            "title":            "EUR/USD Momentum (RSI+EMA, XGBoost)",
            "objective":        "capture intraday momentum continuation",
            "notes":            "shallow trees + low LR for noisy FX",
        }

    What you do not write. No build_model, generate_signals, apply_risk, train_and_backtest, or any backtest or metric code. The framework loads the OHLC, calls your feature_engineering(), strips the warm-up rows, builds the target (sign(close.shift(-target_horizon) - close)), splits train and test, fits the model, thresholds predict_proba to -1, 0 or 1, applies your filters, runs the backtest with your stop loss, take profit and cooldown, and returns all the metrics.

    Common edits

    All of these are one key in strategy_config().

    GoalChange
    Long only, or short onlydirection = "long" or "short"
    Add or change the stop loss and take profitstop_loss = 0.005 (0.5%), take_profit = 0.01 (1.0%). Decimal ratios: on EUR/USD 0.005 is about 50 pips. None turns one off.
    Trade less oftenA stricter cutoff, which is a different thing from a more reliable oneRaise signal_threshold (0.60 to 0.70), set cooldown above 0, or both
    Trade more oftenLower signal_threshold toward 0.50
    Trade only in a session, in UTC hourssession_filter = [7, 16] (London), [13, 17] (London and New York overlap), [0, 9] (Tokyo)
    Skip dead, low-volatility periodsmin_atr = 0.0003 (the minimum NATR)
    Trade only with the trendtrend_filter = "sma_50"
    Predict further or nearer aheadtarget_horizon = N. On 15 min bars, 1 is the next bar, 4 is about 1 h and 16 is about 4 h.
    Reverse, or go flat, on the opposite signalon_opposite = "reverse" or "close_only"
    Use a different modelmodel_type: XGBClassifier, RandomForestClassifier, GradientBoostingClassifier, ExtraTreesClassifier or LogisticRegression, with matching model_params
    Add an indicator or a candle patternAdd the column inside feature_engineering() and the model learns it. See Add an indicator.

    Add an indicator

    Put it in feature_engineering(). Every new column on df becomes an ML feature by itself. No look-ahead, which means no negative shifts. Do not drop rows, and finish with .bfill().ffill().

    Python
    def feature_engineering(df, close, open_, high, low):
        # MACD
        ema12 = close.ewm(span=12).mean(); ema26 = close.ewm(span=26).mean()
        df['macd']      = ema12 - ema26
        df['macd_sig']  = df['macd'].ewm(span=9).mean()
        df['macd_hist'] = df['macd'] - df['macd_sig']
        # Bollinger position
        mid = close.rolling(20).mean(); sd = close.rolling(20).std()
        df['bb_pos'] = (close - (mid - 2*sd)) / ((mid + 2*sd) - (mid - 2*sd) + 1e-9)
        # ATR / NATR (for volatility context)
        tr = pd.concat([high-low, (high-close.shift(1)).abs(), (low-close.shift(1)).abs()], axis=1).max(axis=1)
        df['natr_14'] = tr.rolling(14).mean() / close
        # Candle pattern: hammer
        body = (close-open_).abs()
        lower_wick = pd.concat([close, open_], axis=1).min(axis=1) - low
        upper_wick = high - pd.concat([close, open_], axis=1).max(axis=1)
        df['hammer'] = ((lower_wick > 2*body) & (upper_wick < 0.3*body) & (close > open_)).astype(float)
        # Time of day (cyclical)
        df['hour_sin'] = np.sin(2*np.pi*df.index.hour/24)
        df['hour_cos'] = np.cos(2*np.pi*df.index.hour/24)
        return df.bfill().ffill()

    For a custom indicator from Pine Script or plain English, POST /api/v1/indicators/custom writes the feature code for you. The full indicator catalogue is at GET /api/v1/indicator-schema.

    PineScript and Python

    There is no PineScript here: the generated code is Python. The logic is the same, with entries, exits, signals and indicators, and only the syntax differs. If you know PineScript, this is how the concepts map across.

    ConceptPineScriptPython
    Go longstrategy.entry("L", strategy.long)signal = 1
    Go shortstrategy.entry("S", strategy.short)signal = -1
    Close, or stay flatstrategy.close_all()signal = 0
    Current closecloseclose or ohlc['close']
    Previous closeclose[1]close.shift(1)
    Current openopenohlc['open']
    The bar's high and lowhigh, lowohlc['high'], ohlc['low']
    SMA(close, 20)ta.sma(close, 20)close.rolling(20).mean()
    EMA(close, 20)ta.ema(close, 20)close.ewm(span=20).mean()
    RSI(close, 14)ta.rsi(close, 14)See Add an indicator
    Crossover(fast, slow)ta.crossover(fast, slow)(fast > slow) & (fast.shift(1) <= slow.shift(1))
    Bar indexbar_indexdf.index (a datetime)
    Day of weekdayofweekdf.index.dayofweek (0 is Monday, 4 is Friday)
    Hour of dayhourdf.index.hour
    Minuteminutedf.index.minute

    API reference

    Overview and auth

    All endpoints live under /api/v1/. Authenticated endpoints need an X-API-Key header.

    HTTP
    # Base URL
    https://api.quantifyme.ai/api/v1/
    
    # Auth header
    X-API-Key: qm_xxxxxxxxxxxxxxxx

    Signed in, this copies your personal key. Otherwise it makes a trial key. It is the same key as in Get an API key.

    Quick start. The Full example is one script you can copy and run that covers generate, train and results.

    POST /api/v1/one_shot

    One streamed call from a sentence to a live model: it writes the strategy, trains and backtests it, deploys it, and shares it to the community. Deploy from one sentence shows the request as raw HTTP, curl, Python and Node.js.

    Body fieldMeaning
    promptThe strategy in plain English. A vague request deploys the best curated preset for the market, or writes a new strategy when there is none, and a specific rule writes a new one. A community strategy deploys only when you name it with community_id.
    symbol, timeframeThe market to train on, for example "EURUSD" and "15min". A market named in the prompt wins.
    codeYour own strategy code. Generation is skipped.
    preset, community_idDeploy a preset, or a strategy from the community, in place of a prompt
    claude_model"sonnet" or "haiku", the model that writes the strategy
    start_date, end_dateOptional. Left out, the server picks the default window.
    deliver_toWhere live signals go: Telegram, Email, Discord or Webhook. A channel counts only when it carries its address, so send the URL itself as "webhook". With no address the model still goes live, with no delivery set up.

    The stream

    Four event names arrive: token carries the strategy code as it is written, step reports progress, done closes a good run and error closes a failed one. A step names one of four stages, in this order.

    StageWhat is happening
    generateWriting the strategy
    trainTraining and backtesting the model
    deployDeploying it
    shareSharing it to the community, when the result qualifies
    Response, as server-sent events
    event: step   data: {"stage": "generate", "pct": 10, "msg": "..."}
    event: token  data: {"text": "def feature_engineering("}
    event: step   data: {"stage": "train", "pct": 60, "msg": "..."}
    event: step   data: {"stage": "deploy", "pct": 85, "msg": "Deploying model..."}
    event: step   data: {"stage": "share", "pct": 97, "msg": "Auto-shared to /community ..."}
    event: done   data: {"live_url": "...", "model": "...", "stem": "...", "channels": [],
                         "start_date": "...", "end_date": "...", "source": "generated",
                         "train_stats": {"trades": 0, "win_rate": 0, "profit_factor": 0,
                                         "return": 0, "sharpe": 0, "max_drawdown": 0}}

    The done event carries live_url, model, stem, channels, the start_date and end_date that were really trained, source ("generated", "preset" or "community") and train_stats. A community deploy adds author and community_id.

    POST /api/v1/generate

    Generate a full Python strategy from plain English. Each field takes a free-text description: features, signals, model, optimization, risk and risk_function. Pass structured indicators as well when you want exact parameters.

    Python
    import requests
    
    resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
        "features":      "MACD histogram slope, RSI divergence",
        "signals":       "Long when MACD crosses above zero with RSI confirmation",
        "model":         "XGBoost",
        "optimization":  "Maximize Sharpe ratio",
        "risk":          "Stop loss 0.3%, scale by ATR",
        "risk_function": "Skip trades on Fridays after 18:00 UTC",
        "indicators": {
            "macd_enabled": True, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
            "rsi_enabled":  True, "rsi_period": 14,
            "atr_enabled":  True, "atr_period": 14,
        },
        "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 0},
        "start_date":   "2025-01-01",
        "end_date":     "2026-04-01",
        "train_split":  0.7,
        "claude_model": "sonnet",
    }, headers={"X-API-Key": "qm_xxx"})
    
    code = resp.json()["code"]

    indicators is optional. When you send it, the model that writes the code receives exact parameters, for example "RSI with period=14", and does not have to parse free text. GET /api/v1/indicator-schema lists every indicator.

    Options for pos_rules

    FieldOptionsDefault
    max_pos1, 2, 31
    on_oppositereverse, close_only, ignorereverse
    directionboth, long, shortboth
    cooldown0 to 100, in bars0

    POST /api/v1/generate/from-template

    Generate strategy code from a curated template. You can override any field: a text field replaces the template's, and a dict field (indicators, pos_rules) merges into it.

    Python
    resp = requests.post("https://api.quantifyme.ai/api/v1/generate/from-template", json={
        "template":    "scalper",
        "start_date":  "2025-01-01",
        "end_date":    "2026-04-01",
        "pos_rules":   {"direction": "long"},   # override: long only
        "indicators":  {"rsi_period": 21},      # override: RSI 21 instead of 14
        "claude_model": "sonnet",
    }, headers={"X-API-Key": "qm_xxx"})

    Available templates

    KeyNameDescription
    macd_momentumMACD MomentumTrend following with MACD crossovers and RSI confirmation
    mean_reversionMean ReversionFade extremes with Bollinger Bands and RSI
    trend_followingTrend FollowingEMA crossovers and ATR position sizing
    scalperScalperHigh frequency with Stochastic and Bollinger Bands
    conservative_longConservative Long-OnlySMA trend and strict drawdown control

    POST /api/v1/indicators

    Compute built-in indicators on OHLC data without training a model. The values come back as JSON.

    Python
    resp = requests.post("https://api.quantifyme.ai/api/v1/indicators", json={
        "indicators": {"rsi_enabled": True, "rsi_period": 14, "macd_enabled": True},
        "symbol":     "EURUSD",
        "timeframe":  "15min",
        "start":      "2026-04-01",
        "limit":      100,
        "format":     "columns",   # or "rows"
    }, headers={"X-API-Key": "qm_xxx"})
    
    data = resp.json()
    # data["ind_rsi14"]  -> [45.2, 48.1, 52.3, ...]
    # data["timestamps"] -> ["2026-04-01 00:00:00", ...]

    Available indicators

    IndicatorParamsFeatures
    SMAsma_periods = "20,50,200"sma_{P}, dm_sma_{P}
    EMAema_periods = "9,21,50"ema_{P}, dm_ema_{P}
    Bollinger Bandsbb_period = 20, bb_std = 2.0bb_width, bb_pct
    RSIrsi_period = 14rsi_{P}
    MACDmacd_fast = 12, macd_slow = 26, macd_signal = 9macd_line, macd_hist
    Stochasticstoch_k = 14, stoch_d = 3stoch_k, stoch_d
    ATRatr_period = 14atr_{P}, natr_{P}

    WMA is in the schema too. Its parameters are in GET /api/v1/indicator-schema.

    POST /api/v1/indicators/custom

    Convert Pine Script or plain English into a computed indicator. It returns overlays, panels, signals and ML features.

    Python
    # Natural language
    resp = requests.post("https://api.quantifyme.ai/api/v1/indicators/custom", json={
        "source":    "Supertrend indicator with ATR period 10 and multiplier 3",
        "timeframe": "15min",
        "fe_mode":   "basic",    # "full" | "basic" | "none"
    }, headers={"X-API-Key": "qm_xxx"})
    
    # Pine Script
    resp = requests.post("https://api.quantifyme.ai/api/v1/indicators/custom", json={
        "source": "//@version=5\nindicator('My RSI')\nplot(ta.rsi(close, 14))",
        "provider": "anthropic",  # "anthropic" | "groq" | "ollama"
    }, headers={"X-API-Key": "qm_xxx"})
    
    result = resp.json()
    # result["name"]     -> "Supertrend"
    # result["overlays"] -> [{id, color, data}]
    # result["panels"]   -> [{id, title, lines, h_lines}]
    # result["signals"]  -> [{time, type: "buy"|"sell"}]
    # result["features"] -> {col_name: [{time, value}]}

    Discovery

    These endpoints are public and need no API key. Use them to find the available options before you call an authenticated endpoint.

    EndpointReturns
    GET /api/v1/indicator-schemaAll 8 indicators with parameter names, types, defaults and the feature columns they generate
    GET /api/v1/presetsThe chip presets the website uses, the pos_rules schema and the 5 strategy templates
    GET /api/v1/docsMachine-readable JSON docs: the core endpoints, with examples. The full path catalogue is /openapi.json.
    GET /api/v1/examplesEvery example in the Example library, with its full runnable code
    Python
    # Discover available indicators
    schema = requests.get("https://api.quantifyme.ai/api/v1/indicator-schema").json()
    
    # Discover templates + presets
    presets = requests.get("https://api.quantifyme.ai/api/v1/presets").json()
    # presets["templates"]["macd_momentum"]["config"] -> ready for /generate

    Scripts and tools

    Full example

    One script from start to finish: generate a strategy, train the model, poll until it is done, and print the results. Replace API_KEY with yours.

    The same key as in Get an API key.

    Python
    # QuantifyMe API - Full Example
    # 1. Generate strategy code from natural language
    # 2. Submit for training
    # 3. Poll until complete
    # 4. View results
    import requests, time
    
    # CONFIG: paste your API key here
    BASE    = "https://api.quantifyme.ai"
    API_KEY = "qm_PASTE_YOUR_KEY_HERE"   # from "Get an API key" on this page
    HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
    
    # STEP 1: Generate strategy code
    print("Generating strategy...")
    
    resp = requests.post(f"{BASE}/api/v1/generate", json={
        # Natural language: describe your strategy
        "features":      "MACD (12,26,9), RSI 14, ATR 14, Volume Z-score",
        "signals":       "Buy when MACD crosses above zero and RSI < 60",
        "model":         "XGBoost",
        "optimization":  "Maximize Sharpe ratio, keep max drawdown under 15%",
        "risk":          "Stop loss 0.3%, fixed 1% risk per trade",
    
        # Structured indicators: exact params (optional, overrides NL)
        "indicators": {
            "macd_enabled": True, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
            "rsi_enabled":  True, "rsi_period": 14,
            "atr_enabled":  True, "atr_period": 14,
        },
    
        # Position rules
        "pos_rules": {
            "max_pos": 1, "direction": "both",
            "on_opposite": "reverse", "cooldown": 0,
        },
    
        # Date range + model
        "start_date":   "2025-06-01",
        "end_date":     "2026-04-01",
        "train_split":  0.7,
        "claude_model": "sonnet",
    }, headers=HEADERS)
    
    code = resp.json()["code"]
    print(f"Strategy generated ({len(code)} chars)")
    
    # STEP 2: Submit for training
    print("Submitting for training...")
    
    resp = requests.post(f"{BASE}/api/v1/train", json={
        "code":         code,
        "model_name":   "API Test Model",
        "start_date":   "2025-06-01",
        "end_date":     "2026-04-01",
        "train_split":  0.7,
        "timeframe":   "15min",
    }, headers=HEADERS)
    
    job = resp.json()
    job_id = job["job_id"]
    print(f"Job {job_id} queued")
    
    # STEP 3: Poll until done
    while True:
        resp = requests.get(f"{BASE}/api/v1/train/{job_id}", headers=HEADERS)
        status = resp.json()
        print(f"  Status: {status['status']}")
        if status["status"] in ("done", "failed"):
            break
        time.sleep(3)
    
    # STEP 4: View results
    if status["status"] == "done":
        m = status.get("metrics", {})
        print("Training complete!")
        print(f"  Return:   {m.get('total_ret', 0):.2%}")
        print(f"  Sharpe:   {m.get('sharpe_strat', 0):.2f}")
        print(f"  Drawdown: {m.get('mdd', 0):.2%}")
        print(f"  Trades:   {m.get('n_trades', 0)}")
    else:
        print(f"Training failed: {status.get('error', 'unknown')}")
    
    # BONUS: Use a template instead (no NL needed)
    # resp = requests.post(f"{BASE}/api/v1/generate/from-template", json={
    #     "template":    "scalper",
    #     "start_date":  "2025-06-01",
    #     "end_date":    "2026-04-01",
    #     "claude_model": "sonnet",
    # }, headers=HEADERS)
    
    # BONUS: Compute indicators without training
    # resp = requests.post(f"{BASE}/api/v1/indicators", json={
    #     "indicators": {"rsi_enabled": True, "macd_enabled": True},
    #     "timeframe": "15min", "limit": 100,
    # }, headers=HEADERS)
    # print(resp.json()["ind_rsi14"][:5])  # first 5 RSI values

    How long it takes. About 10 to 30 seconds in all. Step 1, generation, takes about 5 seconds. Step 3, training, takes 5 to 15 seconds depending on how much data there is. The while True loop polls every 3 seconds until the job is done.

    Command-line bot

    If you would rather not write the HTTP layer, qm-bot-template is a Python command-line tool that wraps every endpoint on this page and uses only the standard library. It mints its own trial key, retries on transient errors and gives every failure its own exception type.

    Shell
    qmbot mint                                          # trial key with 10,000 credits, cached
    qmbot one-shot "Buy when RSI<30 on EURUSD 15m"      # generate, train, deploy
    qmbot fork --publish                                # fork the top of /community, retrain, republish if profitable
    qmbot watch --kind FORKED                           # live tail of every other bot's activity

    What is in it

    • Subcommands: mint, whoami, one-shot, generate, train, fork and watch.
    • Typed exceptions, so a wrapper can branch on how a call failed: AuthError, RateLimitError (with .retry_after), BudgetError and NetworkError.
    • Automatic retry with exponential backoff. It honours Retry-After on a 429 or a 503.
    • Typed exit codes for shell scripts: 2 is auth, 3 is a rate limit, 4 is budget, 5 is validation and 6 is network.
    • No runtime dependencies. Python 3.9 or later. It runs on any VPS.

    Build and run from this page

    Put examples together into one strategy, then train it and deploy it without leaving the docs. Each block is also a script you can copy.

    Build and test

    Generate a strategy from the seven slots, train it, and see the backtest. The script below follows the slots as you fill them, and it is the same script you would run yourself.

    Sign in to save models across sessions and get a personal API key.

    Strategy composerFilled from the Example library below
    1. 1FeaturesEmpty
    2. 2SignalsEmpty
    3. 3ModelEmpty
    4. 4OptimisationEmpty
    5. 5RiskEmpty
    6. 6Position rulesEmpty
    7. 7FilterEmpty
    Runs on a trial key, no account needed
    Python, follows the composer
    import requests, time, json
    
    BASE = "https://api.quantifyme.ai"
    API_KEY = "qm_YOUR_KEY"  # from "Get an API key" on this page
    H = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
    
    # Step 1: Generate strategy code (streaming)
    # Tokens stream live as Claude writes the code
    body = {
        "features": "",
        "signals": "",
        "model": "",
        "optimization": "",
        "risk": "",
        "risk_function": "",
        "indicators": {},
        "pos_rules": {},
        # start_date/end_date are optional: omitted here so the server picks
        # the same default window /landing and Quick Deploy use
        "train_split": 0.7, "claude_model": "sonnet"
    }
    
    code = ""
    with requests.post(f"{BASE}/api/v1/generate/stream", json=body,
                       headers=H, stream=True, timeout=120) as r:
        for line in r.iter_lines():
            if line and line.startswith(b"data: "):
                d = json.loads(line[6:])
                if d["type"] == "token":
                    print(d["text"], end="", flush=True)  # live streaming!
                    code += d["text"]
                elif d["type"] == "done":
                    code = d["code"]
                elif d["type"] == "error":
                    print(f"Error: {d['error']}")
    print(f"Generated {len(code)} chars")
    if not code:
        raise RuntimeError("No code generated: check API key and credits")
    
    # Step 2: Train
    resp = requests.post(f"{BASE}/api/v1/train", json={
        "code": code, "model_name": "My Strategy",
        # start_date/end_date are optional: omitted here so the server picks
        # the same default window /landing and Quick Deploy use
        "train_split": 0.7, "symbol": "EURUSD", "timeframe": "15min"
    }, headers=H).json()
    if "error" in resp:
        raise RuntimeError(resp["error"])
    job_id = resp["job_id"]
    print(f"Job {job_id} submitted | model: {resp.get('model_name', 'My Strategy')}")
    
    # Step 3: Poll
    while True:
        s = requests.get(f"{BASE}/api/v1/train/{job_id}", headers=H).json()
        print(s["status"])
        if s["status"] in ("done", "failed"): break
        time.sleep(3)
    
    # Step 4: Results
    if s["status"] == "done":
        tr = s.get("train_stats", {})
        te = s.get("test_stats", {})
        def p(v, w=13): return str(v).rjust(w)
        def pct(v): return f"{v*100:.2f}%"
        def pct4(v): return f"{v*100:.4f}%"
        def dol(v): return f"${v:+,.2f}"
        B = "│"; T = "─"; TL = "┌"; TR = "┐"; BL = "└"; BR = "┘"
        ML = "├"; MR = "┤"; TM = "┬"; BM = "┴"; X = "┼"
        top = f"  {TL}{T*20}{TM}{T*14}{TM}{T*14}{TR}"
        mid = f"  {ML}{T*20}{X}{T*14}{X}{T*14}{MR}"
        bot = f"  {BL}{T*20}{BM}{T*14}{BM}{T*14}{BR}"
        row = lambda l, a, b: f"  {B}  {l:<18}{B}{p(a)} {B}{p(b)} {B}"
        print()
        print(top)
        print(f"  {B}{' ':20}{B}{'    TRAIN     ':14}{B}{'     TEST     ':14}{B}")
        print(mid)
        print(row("Net Profit", dol(tr.get("np",0)), dol(te.get("np",0))))
        print(row("Total Return", pct(tr.get("ret",0)), pct(te.get("ret",0))))
        print(row("Profit Factor", f"{tr.get('pf',0):.2f}", f"{te.get('pf',0):.2f}"))
        print(row("Max Drawdown", pct(abs(tr.get("mdd",0))), pct(abs(te.get("mdd",0)))))
        print(mid)
        print(row("Total Trades", tr.get("n",0), te.get("n",0)))
        print(row("Winning Trades", tr.get("wins",0), te.get("wins",0)))
        print(row("Losing Trades", tr.get("losses",0), te.get("losses",0)))
        print(row("Win Rate", pct(tr.get("wr",0)), pct(te.get("wr",0))))
        print(mid)
        print(row("Risk:Reward", f"{tr.get('rr',0):.2f}", f"{te.get('rr',0):.2f}"))
        print(row("Expectancy", dol(tr.get("expect",0)), dol(te.get("expect",0))))
        print(row("Largest Win", pct4(tr.get("best",0)), pct4(te.get("best",0))))
        print(row("Largest Loss", pct4(tr.get("worst",0)), pct4(te.get("worst",0))))
        print(row("Avg Trade Return", pct4(tr.get("avg",0)), pct4(te.get("avg",0))))
        print(bot)
    else:
        print("Failed:", s.get("error", "unknown"))

    Already have strategy code?

    Paste it here and generation is skipped: Build and test goes straight to training.

    Deploy and automate

    Deploy a trained model so its live signals are delivered, by Telegram, Email, Discord or Webhook. The script lists your models, keeps the ones that pass your criteria, deploys them and prints what is live. The button deploys the model you just trained in Build and test.

    Sign in to deploy under your account and not under a trial.

    No model trained yet. Run Build and test first.
    import requests, json, webbrowser
    from IPython.display import display, HTML
    
    BASE = "https://api.quantifyme.ai"
    API_KEY = "qm_YOUR_KEY"  # from "Get an API key" on this page
    H = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
    
    # Deploy criteria
    DEPLOY = True            # deploy models that pass criteria
    MIN_RETURN = 0.01        # 1% minimum test return
    MIN_PROFIT_FACTOR = 1.0  # minimum profit factor
    WEBHOOK_URL = ""         # your webhook endpoint (optional)
    OPEN_IN_BROWSER = True   # auto-open hub prediction tab after deploy
    SHOW_EMPTY = False       # show models with 0 trades
    
    # Helper: check what is currently deployed
    def get_deployed():
        return requests.get(f"{BASE}/api/v1/deployed", headers=H).json()
    
    # Fetch models, sort newest-first
    resp = requests.get(f"{BASE}/api/v1/models", headers=H).json()
    if "error" in resp:
        raise RuntimeError(f"API error: {resp['error']}: check API_KEY")
    all_models = resp.get("models", [])
    all_models.sort(key=lambda m: m.get("trained_at", "") or "", reverse=True)
    runs = [m for m in all_models if m.get("test_stats", {}).get("n", 0) > 0 or SHOW_EMPTY]
    hidden = len(all_models) - len(runs)
    
    tail = f"  (hidden {hidden} with no backtest)" if hidden and not SHOW_EMPTY else ""
    print(f"Found {len(all_models)} model(s){tail}")
    print("─" * 84)
    print(f"  {'Status':6s} {'Model':24s} {'Trained':17s} {'Return':>8s} {'PF':>6s} {'WR':>6s} {'Trades':>7s}")
    print("─" * 84)
    
    _opened = False   # open only the first deployed URL
    for m in runs:
        test = m.get("test_stats", {})
        ret, pf, wr, n = test.get("ret", 0), test.get("pf", 0), test.get("wr", 0), test.get("n", 0)
        stem = m["name"]
        display_name = (m.get("model_name") or stem)[:24]
        trained = ((m.get("trained_at") or "").replace("T", " "))[:16]
        passed = ret > MIN_RETURN and pf > MIN_PROFIT_FACTOR
        flag = "PASS" if passed else "SKIP"
        print(f"  [{flag}] {display_name:24s} {trained:17s} {ret:>7.2%} {pf:>6.2f} {wr:>5.1%} {n:>7d}")
    
        if DEPLOY and passed:
            body = {"model_name": display_name, "channels": ["webhook"]}
            if WEBHOOK_URL:
                body["webhook_url"] = WEBHOOK_URL
            r = requests.post(f"{BASE}/api/v1/deploy", json=body, headers=H).json()
            if "error" in r:
                print(f"         ✗ Error: {r['error']}")
                continue
            dep_stem = r.get("model", stem)
            live = get_deployed()
            confirmed = dep_stem in [d["model"] for d in live.get("deployed", [])]
            url = f"{BASE}/hfthub?tab=backtesting&model={dep_stem}&api_key={API_KEY}"
            print()   # blank line before deploy message
            if confirmed:
                chans = ", ".join(r.get("channels", []))
                print(f"         ✓ DEPLOYED (live): {dep_stem}  (channels: {chans})")
                display(HTML(f'<pre style="margin:0;font-family:monospace">         → <a href="{url}" target="_blank">Open live signal dashboard</a></pre>'))
                if OPEN_IN_BROWSER and not _opened:
                    webbrowser.open(url)
                    _opened = True
            else:
                print(f"         ⚠ Deploy OK but not showing as live yet")
            print()   # blank line after deploy message
    
    print("─" * 84)
    print()
    print("Currently deployed")
    live = get_deployed()
    if live.get("count", 0) == 0:
        print("  (none)")
    else:
        for d in live["deployed"]:
            chans = ", ".join(d.get("channels", [])) or "-"
            print(f"  • {d['model']:30s} | channels: {chans:20s} | since: {d.get('created_at', '')[:19]}")

    The sign-in helper, qm_login(), tries four things in order: the QUANTIFYME_API_KEY environment variable, a cached key in ~/.quantifyme/credentials.json, a browser sign-in, and last a trial key, which is what works for an AI agent, an anonymous user or Colab.

    Community script

    A strategy shared on the community page, as one script: the first row of the leaderboard today. It was published on USDCAD 1 h data. Run it to see the result for yourself.

    USD/CAD Signal Mix: Z-score 20 + ADX 20 (XGBoost, 1h)Shared by @silver-bull-130

    Signal Mix strategy on USD/CAD 1h. A compact, machine-selected indicator set; the classifier learns the entry rule directly from the features. Features: Z-score 20, ADX 20, Session/time features, RSI 14, Williams %R 21, CCI 14. Model: XGBoost; label horizon 1 bars, confidence threshold 0.52, direction short. Risk: 25 pip stop / 50 pip target (1:2 R/R), 1.0 lot on $10k, $6 round-trip commission. Trained on the last 40 days with a 70/30 holdout; the published numbers are the out-of-sample 30%.

    Net return
    Sharpe
    Max drawdown
    Trades
    Python
    import requests, time
    
    BASE = "https://api.quantifyme.ai"
    API_KEY = "qm_YOUR_KEY"  # from "Get an API key" on this page, or POST /api/v1/key/trial
    H = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
    
    # Strategy: USD/CAD Signal Mix: Z-score 20 + ADX 20 (XGBoost, 1h) by @silver-bull-130
    code = requests.get(f"{BASE}/api/v1/community/269/code", timeout=30).json()["code"]
    
    train = requests.post(f"{BASE}/api/v1/train", json={
        "code": code, "model_name": "Community Demo",
        "train_split": 0.7, "symbol": "EURUSD", "timeframe": "15min"
    }, headers=H)
    job_id = train.json()["job_id"]
    
    while True:
        s = requests.get(f"{BASE}/api/v1/train/{job_id}", headers=H).json()
        print(s["status"])
        if s["status"] == "done":
            m = s["metrics"]
            print(f"Return: {m['total_ret']:.2%}, Sharpe: {m['sharpe_strat']:.2f}")
            break
        elif s["status"] == "failed":
            print(s.get("error", ""))
            break
        time.sleep(3)

    Example library

    All 275 API examples, by section. Open one to read it. An example from a strategy builder section has an Add to composer button, which puts it in the matching slot of Build and test above.

    Strategy builder

    Feature engineering70
    RSI
    • RSI 14 onlySingle indicator, RSI default period 14
      # FE: RSI 14 only
      "features": "RSI 14",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14}   # exact params enforced
    • RSI 7 (fast)Fast RSI for scalping
      # FE: RSI 7 (fast)
      "features": "RSI 7",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 7}   # exact params enforced
    • RSI 21 (slow)Slow RSI for swing trading
      # FE: RSI 21 (slow)
      "features": "RSI 21",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 21}   # exact params enforced
    • RSI 5 (ultra-fast)Ultra-fast RSI
      # FE: RSI 5 (ultra-fast)
      "features": "RSI 5",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 5}   # exact params enforced
    MACD
    • MACD standard (12,26,9)Standard MACD
      # FE: MACD standard (12,26,9)
      "features": "MACD (12,26,9)",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9}   # exact params enforced
    • MACD fast (8,21,5)Faster MACD
      # FE: MACD fast (8,21,5)
      "features": "MACD (8,21,5)",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 8, "macd_slow": 21, "macd_signal": 5}   # exact params enforced
    • MACD slow (19,39,9)Slow MACD
      # FE: MACD slow (19,39,9)
      "features": "MACD (19,39,9)",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 19, "macd_slow": 39, "macd_signal": 9}   # exact params enforced
    • MACD ultra-fast (5,13,3)Ultra-fast MACD
      # FE: MACD ultra-fast (5,13,3)
      "features": "MACD (5,13,3)",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 5, "macd_slow": 13, "macd_signal": 3}   # exact params enforced
    Bollinger Bands
    • BB standard (20,2)Standard BB
      # FE: BB standard (20,2)
      "features": "Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • BB tight (20,1.5)Tighter bands
      # FE: BB tight (20,1.5)
      "features": "Bollinger Bands (20,1.5)",   # NL context for Claude
      "indicators": {"bb_enabled": true, "bb_period": 20, "bb_std": 1.5}   # exact params enforced
    • BB wide (20,2.5)Wider bands
      # FE: BB wide (20,2.5)
      "features": "Bollinger Bands (20,2.5)",   # NL context for Claude
      "indicators": {"bb_enabled": true, "bb_period": 20, "bb_std": 2.5}   # exact params enforced
    • BB fast (10,2)Fast BB
      # FE: BB fast (10,2)
      "features": "Bollinger Bands (10,2)",   # NL context for Claude
      "indicators": {"bb_enabled": true, "bb_period": 10, "bb_std": 2.0}   # exact params enforced
    • BB slow (50,2)Slow BB
      # FE: BB slow (50,2)
      "features": "Bollinger Bands (50,2)",   # NL context for Claude
      "indicators": {"bb_enabled": true, "bb_period": 50, "bb_std": 2.0}   # exact params enforced
    SMA
    • SMA 20/50/200Classic triple SMA
      # FE: SMA 20/50/200
      "features": "SMA 20, 50, 200",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "20,50,200"}   # exact params enforced
    • SMA 10/30Fast SMA pair
      # FE: SMA 10/30
      "features": "SMA 10/30",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "10,30"}   # exact params enforced
    • SMA 50/100/200Position trading SMA
      # FE: SMA 50/100/200
      "features": "SMA 50/100/200",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "50,100,200"}   # exact params enforced
    • SMA single 200SMA 200 trend king
      # FE: SMA single 200
      "features": "SMA 200",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "200"}   # exact params enforced
    EMA
    • EMA 9/21/50Fast EMA trio
      # FE: EMA 9/21/50
      "features": "EMA 9/21/50",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "9,21,50"}   # exact params enforced
    • EMA 50/200 (golden cross)Golden cross
      # FE: EMA 50/200 (golden cross)
      "features": "EMA 50/200",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200"}   # exact params enforced
    • EMA 5/13/34 (Fibonacci)Fibonacci EMA
      # FE: EMA 5/13/34 (Fibonacci)
      "features": "EMA 5/13/34",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "5,13,34"}   # exact params enforced
    • EMA 8/21 scalpingFast EMA scalping
      # FE: EMA 8/21 scalping
      "features": "EMA 8/21",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "8,21"}   # exact params enforced
    WMA
    • WMA 20Weighted MA
      # FE: WMA 20
      "features": "WMA 20",   # NL context for Claude
      "indicators": {"wma_enabled": true, "wma_periods": "20"}   # exact params enforced
    • WMA 10/30WMA crossover
      # FE: WMA 10/30
      "features": "WMA 10/30",   # NL context for Claude
      "indicators": {"wma_enabled": true, "wma_periods": "10,30"}   # exact params enforced
    Stochastic
    • Stochastic (14,3)Standard Stochastic
      # FE: Stochastic (14,3)
      "features": "Stochastic (14,3)",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3}   # exact params enforced
    • Stochastic fast (5,3)Fast Stochastic
      # FE: Stochastic fast (5,3)
      "features": "Stochastic (5,3)",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 5, "stoch_d": 3}   # exact params enforced
    • Stochastic slow (21,5)Slow Stochastic
      # FE: Stochastic slow (21,5)
      "features": "Stochastic (21,5)",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 21, "stoch_d": 5}   # exact params enforced
    ATR
    • ATR 14Average True Range
      # FE: ATR 14
      "features": "ATR 14",   # NL context for Claude
      "indicators": {"atr_enabled": true, "atr_period": 14}   # exact params enforced
    • ATR 7 (fast)Fast ATR
      # FE: ATR 7 (fast)
      "features": "ATR 7",   # NL context for Claude
      "indicators": {"atr_enabled": true, "atr_period": 7}   # exact params enforced
    • ATR 21 (slow)Slow ATR
      # FE: ATR 21 (slow)
      "features": "ATR 21",   # NL context for Claude
      "indicators": {"atr_enabled": true, "atr_period": 21}   # exact params enforced
    2-Indicator Combos
    • RSI + MACDMomentum + trend
      # FE: RSI + MACD
      "features": "RSI 14, MACD (12,26,9)",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9}   # exact params enforced
    • RSI + BBRSI + Bollinger
      # FE: RSI + BB
      "features": "RSI 14, Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • RSI + EMARSI + EMA trend
      # FE: RSI + EMA
      "features": "RSI 14, EMA 50/200",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "ema_enabled": true, "ema_periods": "50,200"}   # exact params enforced
    • RSI + ATRRSI + ATR sizing
      # FE: RSI + ATR
      "features": "RSI 14, ATR 14",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • RSI + StochasticDouble oscillator
      # FE: RSI + Stochastic
      "features": "RSI 14, Stochastic (14,3)",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3}   # exact params enforced
    • MACD + BBMACD + Bollinger
      # FE: MACD + BB
      "features": "MACD (12,26,9), Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • MACD + ATRMACD + ATR
      # FE: MACD + ATR
      "features": "MACD (12,26,9), ATR 14",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • MACD + EMAMACD + EMA
      # FE: MACD + EMA
      "features": "MACD (12,26,9), EMA 50/200",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "ema_enabled": true, "ema_periods": "50,200"}   # exact params enforced
    • EMA + BBEMA + Bollinger
      # FE: EMA + BB
      "features": "EMA 50/200, Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200", "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • EMA + ATREMA + ATR
      # FE: EMA + ATR
      "features": "EMA 50/200, ATR 14",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200", "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • SMA + RSISMA + RSI
      # FE: SMA + RSI
      "features": "SMA 50/200, RSI 14",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "50,200", "rsi_enabled": true, "rsi_period": 14}   # exact params enforced
    • Stoch + BBStochastic + BB
      # FE: Stoch + BB
      "features": "Stochastic (14,3), Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • Stoch + ATRStochastic + ATR
      # FE: Stoch + ATR
      "features": "Stochastic (14,3), ATR 14",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • SMA + EMA comboSMA trend+EMA entries
      # FE: SMA + EMA combo
      "features": "SMA 200, EMA 9/21",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "200", "ema_enabled": true, "ema_periods": "9,21"}   # exact params enforced
    3-4 Indicator Combos
    • RSI + MACD + BBTriple combo
      # FE: RSI + MACD + BB
      "features": "RSI 14, MACD (12,26,9), Bollinger Bands (20,2)",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • RSI + MACD + ATRMomentum+trend+vol
      # FE: RSI + MACD + ATR
      "features": "RSI 14, MACD (12,26,9), ATR 14",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • RSI + EMA + ATRRSI+EMA+ATR
      # FE: RSI + EMA + ATR
      "features": "RSI 14, EMA 50/200, ATR 14",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "ema_enabled": true, "ema_periods": "50,200", "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • MACD + BB + ATRTrend+vol+sizing
      # FE: MACD + BB + ATR
      "features": "MACD (12,26,9), BB (20,2), ATR 14",   # NL context for Claude
      "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • EMA + BB + RSITrend+vol+momentum
      # FE: EMA + BB + RSI
      "features": "EMA 50/200, BB (20,2), RSI 14",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200", "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "rsi_enabled": true, "rsi_period": 14}   # exact params enforced
    • Stoch + RSI + BBDouble osc+vol
      # FE: Stoch + RSI + BB
      "features": "Stochastic (14,3), RSI 14, BB (20,2)",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "rsi_enabled": true, "rsi_period": 14, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • Stoch + MACD + ATROsc+trend+vol
      # FE: Stoch + MACD + ATR
      "features": "Stochastic (14,3), MACD (12,26,9), ATR 14",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • RSI+MACD+BB+ATRFull quad
      # FE: RSI+MACD+BB+ATR
      "features": "RSI 14, MACD, BB, ATR",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • RSI+MACD+EMA+ATRMomentum+trend+vol
      # FE: RSI+MACD+EMA+ATR
      "features": "RSI 14, MACD, EMA 50/200, ATR 14",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "ema_enabled": true, "ema_periods": "50,200", "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • Stoch+RSI+MACD+ATRDouble osc+trend+vol
      # FE: Stoch+RSI+MACD+ATR
      "features": "Stoch, RSI, MACD, ATR",   # NL context for Claude
      "indicators": {"stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • EMA+SMA+BB+RSIDouble MA+vol+momentum
      # FE: EMA+SMA+BB+RSI
      "features": "EMA 9/21, SMA 50/200, BB, RSI",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "9,21", "sma_enabled": true, "sma_periods": "50,200", "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "rsi_enabled": true, "rsi_period": 14}   # exact params enforced
    All Indicators
    • All 5 coreRSI+MACD+BB+Stoch+ATR
      # FE: All 5 core
      "features": "All 5 core indicators",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • All 8 (kitchen sink)Every indicator
      # FE: All 8 (kitchen sink)
      "features": "All 8 indicators",   # NL context for Claude
      "indicators": {"sma_enabled": true, "sma_periods": "20,50,200", "ema_enabled": true, "ema_periods": "9,21,50", "wma_enabled": true, "wma_periods": "20", "bb_enabled": true, "bb_period": 20, "bb_std": 2.0, "rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    Strategy Sets
    • Fast scalping setAll fast-period
      # FE: Fast scalping set
      "features": "Fast scalping",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 5, "macd_enabled": true, "macd_fast": 5, "macd_slow": 13, "macd_signal": 3, "bb_enabled": true, "bb_period": 10, "bb_std": 1.5, "stoch_enabled": true, "stoch_k": 5, "stoch_d": 3, "ema_enabled": true, "ema_periods": "5,13", "atr_enabled": true, "atr_period": 7}   # exact params enforced
    • Slow swing setAll slow-period
      # FE: Slow swing set
      "features": "Slow swing",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 21, "macd_enabled": true, "macd_fast": 19, "macd_slow": 39, "macd_signal": 9, "bb_enabled": true, "bb_period": 50, "bb_std": 2.5, "stoch_enabled": true, "stoch_k": 21, "stoch_d": 5, "sma_enabled": true, "sma_periods": "50,100,200", "atr_enabled": true, "atr_period": 21}   # exact params enforced
    • Fibonacci setFibonacci periods
      # FE: Fibonacci set
      "features": "Fibonacci indicators",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 13, "ema_enabled": true, "ema_periods": "5,8,13,21,34", "bb_enabled": true, "bb_period": 21, "bb_std": 2.0, "stoch_enabled": true, "stoch_k": 13, "stoch_d": 3, "atr_enabled": true, "atr_period": 13}   # exact params enforced
    • Mean reversion setOscillators+bands
      # FE: Mean reversion set
      "features": "Mean reversion",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    • Trend following setMAs+MACD+ATR
      # FE: Trend following set
      "features": "Trend following",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200", "sma_enabled": true, "sma_periods": "200", "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    Natural Language
    • NL, price actionCandle patterns
      # FE: NL: price action
      "features": "Candle body ratio, wicks, engulfing, doji, hammer/shooting star, consecutive bull/bear count",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, volumeVolume features
      # FE: NL: volume
      "features": "Volume Z-score, volume momentum, OBV, volume spike detection",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, multi-timeframeMulti-TF
      # FE: NL: multi-timeframe
      "features": "15-min RSI 14, 1-hour SMA 50 trend, 4-hour support/resistance",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, returnsStatistical returns
      # FE: NL: returns
      "features": "Log returns (1,3,5,10,20 bar), momentum, volatility, z-score",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, sessionTime features
      # FE: NL: session
      "features": "Hour sin/cos, day of week, is_london, is_ny, is_overlap",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, S/R levelsPrice structure
      # FE: NL: S/R levels
      "features": "Distance from 20-bar high/low, pivot points, level touches",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    • NL, order flowOrder flow proxies
      # FE: NL: order flow
      "features": "CLV, A/D line, Chaikin Money Flow, buying/selling pressure",   # NL only: Claude interprets freely
      "indicators": {}   # no structured params
    NL + Structured
    • NL + structuredNL custom+structured
      # FE: NL + structured
      "features": "Volume Z-score, candle body ratio",   # NL context for Claude
      "indicators": {"rsi_enabled": true, "rsi_period": 14, "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9, "atr_enabled": true, "atr_period": 14}   # exact params enforced
    • NL + structured sessionSession NL+indicators
      # FE: NL + structured session
      "features": "Hour sin/cos, is_london, is_overlap",   # NL context for Claude
      "indicators": {"ema_enabled": true, "ema_periods": "50,200", "rsi_enabled": true, "rsi_period": 14, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0}   # exact params enforced
    Signal and entry41
    MACD
    • MACD crossoverBuy on MACD cross above signal, sell on cross below
      # SIG: MACD crossover
      "signals": "Buy when MACD line crosses above signal line, sell when crosses below"
    • MACD zero crossBuy on MACD crossing above zero, sell below
      # SIG: MACD zero cross
      "signals": "Buy when MACD histogram crosses above zero, sell when crosses below zero"
    • MACD histogram reversalTrade MACD histogram direction change
      # SIG: MACD histogram reversal
      "signals": "Buy when MACD histogram starts increasing (reversal from negative), sell when starts decreasing"
    • MACD divergenceTrade MACD divergence with price
      # SIG: MACD divergence
      "signals": "Buy on bullish divergence (price lower low but MACD higher low), sell on bearish divergence"
    RSI
    • RSI oversold/overboughtClassic RSI threshold signals
      # SIG: RSI oversold/overbought
      "signals": "Buy when RSI crosses above 30 (leaving oversold), sell when RSI crosses below 70 (leaving overbought)"
    • RSI extreme (20/80)Tighter RSI thresholds for stronger signals
      # SIG: RSI extreme (20/80)
      "signals": "Buy when RSI < 20, sell when RSI > 80"
    • RSI midline crossRSI 50 as trend filter
      # SIG: RSI midline cross
      "signals": "Buy when RSI crosses above 50, sell when crosses below 50"
    • RSI divergenceRSI divergence with price
      # SIG: RSI divergence
      "signals": "Buy on bullish RSI divergence (price new low, RSI higher low), sell on bearish divergence"
    Bollinger Bands
    • BB breakoutTrade Bollinger Band breakouts
      # SIG: BB breakout
      "signals": "Buy when price breaks above upper Bollinger Band, sell when breaks below lower band"
    • BB mean reversionFade BB extremes back to middle
      # SIG: BB mean reversion
      "signals": "Buy when price touches lower BB and starts rising, sell when touches upper BB and starts falling. Target: BB mid"
    • BB squeeze breakoutTrade BB squeeze (low volatility breakout)
      # SIG: BB squeeze breakout
      "signals": "Buy when BB width is at 20-bar low and price breaks above upper band, sell on break below lower band"
    • BB %B thresholdTrade based on BB percent B position
      # SIG: BB %B threshold
      "signals": "Buy when %B < 0.1 (near lower band), sell when %B > 0.9 (near upper band)"
    MA Crossover
    • EMA golden/death crossEMA 50/200 crossover
      # SIG: EMA golden/death cross
      "signals": "Buy on golden cross (EMA 50 crosses above EMA 200), sell on death cross (EMA 50 crosses below)"
    • EMA fast cross (8/21)Fast EMA crossover for scalping
      # SIG: EMA fast cross (8/21)
      "signals": "Buy when EMA 8 crosses above EMA 21, sell when crosses below"
    • SMA triple crossSMA 20/50/200 alignment
      # SIG: SMA triple cross
      "signals": "Buy when SMA 20 > SMA 50 > SMA 200 (all aligned bullish), sell when reversed"
    • Price above/below MA200Simple trend filter
      # SIG: Price above/below MA200
      "signals": "Buy when price closes above SMA 200, sell when closes below"
    • MA ribbon expansionTrade when MAs fan out
      # SIG: MA ribbon expansion
      "signals": "Buy when EMA 9 > EMA 21 > EMA 50 and gap between them is widening, sell when reversed"
    Stochastic
    • Stochastic crossK/D crossover in extreme zones
      # SIG: Stochastic cross
      "signals": "Buy when %K crosses above %D below 20 (oversold), sell when %K crosses below %D above 80 (overbought)"
    • Stochastic extremeSimple threshold
      # SIG: Stochastic extreme
      "signals": "Buy when Stochastic < 10, sell when > 90"
    • Stochastic midline50 level crossover
      # SIG: Stochastic midline
      "signals": "Buy when Stochastic K crosses above 50, sell when crosses below 50"
    Momentum
    • Momentum reversalTrade momentum shifts
      # SIG: Momentum reversal
      "signals": "Buy when momentum turns positive after being negative for 5+ bars, sell on opposite"
    • Price rejectionCandle wick rejection signals
      # SIG: Price rejection
      "signals": "Buy on hammer candle (long lower wick > 2x body, bullish close), sell on shooting star (long upper wick)"
    • Engulfing patternBullish/bearish engulfing
      # SIG: Engulfing pattern
      "signals": "Buy on bullish engulfing (current bar body fully engulfs previous bearish bar), sell on bearish engulfing"
    • BreakoutRange breakout
      # SIG: Breakout
      "signals": "Buy when price breaks above 50-bar high, sell when breaks below 50-bar low"
    Combined
    • MACD + RSI confirmMACD crossover confirmed by RSI
      # SIG: MACD + RSI confirm
      "signals": "Buy when MACD crosses above signal AND RSI < 60 (not overbought), sell when MACD crosses below AND RSI > 40"
    • RSI + BB confirmRSI oversold at lower BB
      # SIG: RSI + BB confirm
      "signals": "Buy when RSI < 30 AND price near lower Bollinger Band, sell when RSI > 70 AND price near upper BB"
    • MA cross + RSI filterMA crossover filtered by RSI
      # SIG: MA cross + RSI filter
      "signals": "Buy on EMA 50/200 golden cross only if RSI > 50, sell on death cross only if RSI < 50"
    • Stoch + BBStochastic in BB extremes
      # SIG: Stoch + BB
      "signals": "Buy when Stochastic < 20 and price below lower BB, sell when Stochastic > 80 and price above upper BB"
    • MACD + BB squeezeMACD direction after BB squeeze
      # SIG: MACD + BB squeeze
      "signals": "Buy when BB width at 20-bar low and MACD histogram turns positive, sell when turns negative"
    • Triple confirmRSI + MACD + MA all agree
      # SIG: Triple confirm
      "signals": "Buy when RSI > 50 AND MACD above signal AND price above EMA 200. Sell when all three reverse"
    Session
    • London open entryTrade first 30 min of London
      # SIG: London open entry
      "signals": "Only enter during first 30 minutes of London session (08:00-08:30 UTC). Buy/sell based on breakout of first 15-min range"
    • NY open momentumTrade NY open direction
      # SIG: NY open momentum
      "signals": "Buy if price > prior bar close in first 15 min of NY open (14:30 UTC), sell if price < prior close"
    • No Friday tradesAvoid weekend risk
      # SIG: No Friday trades
      "signals": "Normal signal logic but close all positions Friday 18:00 UTC, no new entries after Friday 16:00"
    • Overlap onlyLondon-NY overlap
      # SIG: Overlap only
      "signals": "Only trade during London-NY overlap (13:00-17:00 UTC), flat outside"
    Threshold
    • High confidence onlyStrict threshold
      # SIG: High confidence only
      "signals": "Only enter when model confidence > 70%. Exit when confidence drops below 55%"
    • Aggressive entryLow threshold
      # SIG: Aggressive entry
      "signals": "Enter on any model confidence > 50%. Stay in trade as long as signal direction unchanged"
    • Scaled entrySize by confidence
      # SIG: Scaled entry
      "signals": "Enter with 50% size at confidence > 55%, full size at > 65%. Exit at < 50%"
    Natural Language
    • NL, trend pullbackBuy dips in uptrend
      # SIG: NL: trend pullback
      "signals": "In an uptrend (price above SMA 200), buy when price pulls back to SMA 50 and bounces (close > open after touching SMA 50)"
    • NL, volatility breakoutTrade volatility expansion
      # SIG: NL: volatility breakout
      "signals": "Enter long when ATR suddenly increases (current ATR > 1.5x 20-bar average ATR) and price is trending up. Enter short if trending down."
    • NL, range tradingTrade within range
      # SIG: NL: range trading
      "signals": "Identify 50-bar range (high-low). Buy near range bottom, sell near range top. Exit if range breaks."
    • NL, news avoidanceSkip high-impact times
      # SIG: NL: news avoidance
      "signals": "Normal MACD crossover signals but skip any signal within 30 minutes of hourly bar boundaries (common news release times)"
    ML model23
    Tree-Based
    • Random ForestEnsemble of decision trees, robust, handles noise well
      # ML: Random Forest
      "model": "Random Forest"
    • Random Forest (1000 trees)Large ensemble for more stability
      # ML: Random Forest (1000 trees)
      "model": "Random Forest with 1000 estimators, max depth 8"
    • Random Forest (shallow)Shallow trees to prevent overfitting
      # ML: Random Forest (shallow)
      "model": "Random Forest with max depth 3, min samples leaf 20"
    • XGBoostGradient boosted trees, fast, accurate, popular in competitions
      # ML: XGBoost
      "model": "XGBoost"
    • XGBoost (tuned)XGBoost with specific hyperparameters
      # ML: XGBoost (tuned)
      "model": "XGBoost with 300 estimators, max depth 4, learning rate 0.05, subsample 0.8"
    • XGBoost (conservative)XGBoost tuned to avoid overfitting
      # ML: XGBoost (conservative)
      "model": "XGBoost with max depth 3, learning rate 0.01, 500 estimators, early stopping"
    • Gradient BoostingSklearn gradient boosting, slower but reliable
      # ML: Gradient Boosting
      "model": "Gradient Boosting"
    • Gradient Boosting (tuned)Tuned gradient boosting
      # ML: Gradient Boosting (tuned)
      "model": "Gradient Boosting with 200 estimators, max depth 4, learning rate 0.05, subsample 0.8"
    Linear
    • Logistic RegressionSimple linear classifier, fast, interpretable
      # ML: Logistic Regression
      "model": "Logistic Regression"
    • Logistic Regression (balanced)Handle class imbalance
      # ML: Logistic Regression (balanced)
      "model": "Logistic Regression with balanced class weights"
    • Logistic Regression (L1)Sparse features, L1 regularization
      # ML: Logistic Regression (L1)
      "model": "Logistic Regression with L1 penalty (Lasso) for feature selection"
    • Ridge ClassifierL2 regularized linear
      # ML: Ridge Classifier
      "model": "Ridge Classifier: linear model with L2 regularization"
    Auto
    • Let Claude decideAI picks the best model for your strategy
      # ML: Let Claude decide
      "model": "Let Claude decide"
    • Let Claude decide (ensemble)AI picks and combines models
      # ML: Let Claude decide (ensemble)
      "model": "Let Claude decide: prefer ensemble methods for robustness"
    Strategy-Specific
    • XGBoost for scalpingFast model for high-frequency
      # ML: XGBoost for scalping
      "model": "XGBoost with shallow trees (max depth 3), fast learning rate 0.1, 100 estimators: optimized for speed on 1-min data"
    • RF for swing tradingStable model for longer holds
      # ML: RF for swing trading
      "model": "Random Forest with 500 trees, max depth 10, balanced class weights: optimized for daily/hourly swing trades"
    • Logistic for trend followingSimple model for clear trends
      # ML: Logistic for trend following
      "model": "Logistic Regression: simple and fast, works well when signal is strong and features are well-engineered"
    • XGBoost for mean reversionTuned for range-bound markets
      # ML: XGBoost for mean reversion
      "model": "XGBoost with balanced class weights, max depth 4, learning rate 0.03: tuned for detecting overbought/oversold reversals"
    Class Weights
    • Balanced class weightsHandle unequal buy/sell/hold distribution
      # ML: Balanced class weights
      "model": "XGBoost with class_weight='balanced': adjusts for imbalanced signal distribution"
    • Custom class weightsWeight buys higher than sells
      # ML: Custom class weights
      "model": "Random Forest with custom class weights: {-1: 1.0, 0: 0.5, 1: 1.5}: prioritize catching buy signals"
    Natural Language
    • NL, best for noisy dataDescribe what you need
      # ML: NL: best for noisy data
      "model": "Use a model that handles noisy financial data well, resistant to overfitting, with good generalization on unseen bars"
    • NL, fast inferenceSpeed priority
      # ML: NL: fast inference
      "model": "Fast model: inference must be under 1ms per bar. Prefer simple model over complex ensemble."
    • NL, interpretableNeed to understand why
      # ML: NL: interpretable
      "model": "Interpretable model: I need to understand which features drive each prediction. Feature importance must be meaningful."
    Optimisation28
    Return
    • Maximize Sharpe ratioRisk-adjusted return, the gold standard
      # OPT: Maximize Sharpe ratio
      "optimization": "Maximize Sharpe ratio"
    • Maximize returnPure return, no risk adjustment
      # OPT: Maximize return
      "optimization": "Maximize total return"
    • Maximize Calmar ratioReturn relative to max drawdown
      # OPT: Maximize Calmar ratio
      "optimization": "Maximize Calmar ratio"
    • Maximize Sortino ratioLike Sharpe but only penalizes downside volatility
      # OPT: Maximize Sortino ratio
      "optimization": "Maximize Sortino ratio: penalize downside risk only"
    • Maximize profit factorGross profit / gross loss
      # OPT: Maximize profit factor
      "optimization": "Maximize profit factor (gross wins / gross losses)"
    Risk
    • Minimize max drawdownProtect capital above all
      # OPT: Minimize max drawdown
      "optimization": "Minimize maximum drawdown"
    • MDD < 10%Hard drawdown constraint
      # OPT: MDD < 10%
      "optimization": "Maximize return with max drawdown under 10%"
    • MDD < 5%Very tight drawdown
      # OPT: MDD < 5%
      "optimization": "Maximize Sharpe with max drawdown under 5%"
    • Minimize volatilityLow-volatility strategy
      # OPT: Minimize volatility
      "optimization": "Minimize return volatility (standard deviation of returns)"
    Win Rate
    • Maximize win rateConsistency, win more trades than lose
      # OPT: Maximize win rate
      "optimization": "Maximize win rate"
    • Win rate > 55%Minimum win rate constraint
      # OPT: Win rate > 55%
      "optimization": "Maximize Sharpe ratio with win rate above 55%"
    • Win rate > 60%High win rate constraint
      # OPT: Win rate > 60%
      "optimization": "Maximize return with win rate above 60%"
    Combined
    • Sharpe > 1, MDD < 10%Balanced, good risk-adjusted with drawdown cap
      # OPT: Sharpe > 1, MDD < 10%
      "optimization": "Sharpe > 1 with MDD < 10%"
    • Sharpe > 1.5, MDD < 15%Higher bar for Sharpe
      # OPT: Sharpe > 1.5, MDD < 15%
      "optimization": "Sharpe ratio above 1.5, max drawdown under 15%"
    • High Sharpe + high win rateBest of both
      # OPT: High Sharpe + high win rate
      "optimization": "Maximize Sharpe ratio while keeping win rate above 55%"
    • Return + low drawdownAggressive with safety net
      # OPT: Return + low drawdown
      "optimization": "Maximize total return, but keep max drawdown under 12%"
    • Calmar > 2Strong return/drawdown ratio
      # OPT: Calmar > 2
      "optimization": "Calmar ratio above 2: return must be at least 2x the max drawdown"
    Trade Frequency
    • Many tradesHigh frequency, more statistical significance
      # OPT: Many trades
      "optimization": "Maximize Sharpe with at least 50 trades in the test period"
    • Few high-quality tradesLow frequency, only the best setups
      # OPT: Few high-quality trades
      "optimization": "Maximize profit per trade, minimum 10 trades, win rate > 60%"
    • Balanced frequencyNot too many, not too few
      # OPT: Balanced frequency
      "optimization": "Maximize Sharpe with 20-40 trades in the test period"
    Hyperparameters
    • Conservative depthPrevent overfitting with shallow trees
      # OPT: Conservative depth
      "optimization": "Maximize Sharpe: use conservative hyperparameters: max depth 3-5, high regularization"
    • Aggressive depthAllow complex patterns
      # OPT: Aggressive depth
      "optimization": "Maximize return: allow deeper trees (max depth 8-10) for capturing complex patterns"
    • Balanced class weightsHandle signal imbalance
      # OPT: Balanced class weights
      "optimization": "Maximize Sharpe with balanced class weights: equal importance to buy, sell, and hold signals"
    • Early stoppingPrevent overfitting
      # OPT: Early stopping
      "optimization": "Maximize Sharpe with early stopping: stop training when validation metric stops improving"
    Natural Language
    • NL, robust to regime changeSurvive different market conditions
      # OPT: NL: robust to regime change
      "optimization": "Optimize for consistency across different market regimes: strategy should work in trending AND ranging markets"
    • NL, low correlation to buy-and-holdIndependent alpha
      # OPT: NL: low correlation to buy-and-hold
      "optimization": "Maximize alpha: returns should have low correlation with buy-and-hold. Strategy adds value beyond just holding."
    • NL, smooth equity curveNo big jumps or drops
      # OPT: NL: smooth equity curve
      "optimization": "Optimize for smooth equity curve: minimize daily return variance, avoid large single-trade impacts"
    • NL, overnight riskMinimize gap exposure
      # OPT: NL: overnight risk
      "optimization": "Minimize exposure during market close hours. Strategy should be flat or reduced size during low-liquidity periods."
    Risk management26
    Stop Loss
    • Stop loss 0.3%Tight stop, exit when position loses 0.3%
      # RISK: Stop loss 0.3%
      "risk": "Stop loss 0.3%"
    • Stop loss 0.5%Medium stop
      # RISK: Stop loss 0.5%
      "risk": "Stop loss 0.5%"
    • Stop loss 1%Wide stop, more room to breathe
      # RISK: Stop loss 1%
      "risk": "Stop loss 1%"
    • Stop loss 20 pipsPip-based stop for EURUSD
      # RISK: Stop loss 20 pips
      "risk": "Stop loss 20 pips (0.0020)"
    • ATR-based stopDynamic stop, wider when volatile
      # RISK: ATR-based stop
      "risk": "Stop loss = 2x ATR(14). Wider stop in volatile markets, tighter in quiet."
    • Trailing stop 0.3%Lock in profits as price moves
      # RISK: Trailing stop 0.3%
      "risk": "Trailing stop loss 0.3%: moves with price, locks in profits"
    Take Profit
    • TP 0.5%Fixed take profit
      # RISK: TP 0.5%
      "risk": "Take profit 0.5%"
    • 2:1 reward/riskTP is 2x the stop loss
      # RISK: 2:1 reward/risk
      "risk": "Stop loss 0.3%, take profit 0.6%: 2:1 reward to risk ratio"
    • 3:1 reward/riskTP is 3x the stop loss
      # RISK: 3:1 reward/risk
      "risk": "Stop loss 0.3%, take profit 0.9%: 3:1 reward to risk ratio"
    • ATR-based TPDynamic take profit
      # RISK: ATR-based TP
      "risk": "Take profit = 3x ATR(14), stop loss = 1.5x ATR(14)"
    Position Sizing
    • Fixed 1% riskRisk 1% of capital per trade
      # RISK: Fixed 1% risk
      "risk": "Fixed 1% risk per trade: position size calculated from stop loss distance"
    • Fixed 2% riskRisk 2% per trade
      # RISK: Fixed 2% risk
      "risk": "Fixed 2% risk per trade"
    • Kelly sizingKelly criterion, optimal sizing
      # RISK: Kelly sizing
      "risk": "Kelly position sizing: size based on win rate and avg win/loss ratio"
    • Half KellyConservative Kelly
      # RISK: Half Kelly
      "risk": "Half Kelly position sizing: half of Kelly optimal for safety"
    • ATR-based sizingSize inversely to volatility
      # RISK: ATR-based sizing
      "risk": "Position size = 1% account risk / ATR(14). Smaller when volatile, larger when quiet."
    • Fixed lotSimple fixed size
      # RISK: Fixed lot
      "risk": "Fixed 1.0 lot per trade, no dynamic sizing"
    Frequency
    • Max 3 trades/dayLimit daily trades
      # RISK: Max 3 trades/day
      "risk": "Max 3 trades per day"
    • Max 5 trades/dayMore active daily limit
      # RISK: Max 5 trades/day
      "risk": "Max 5 trades per day"
    • Max 1 trade/dayOne shot per day
      # RISK: Max 1 trade/day
      "risk": "Max 1 trade per day: wait for the best setup"
    Combined
    • SL + TP + sizingFull risk package
      # RISK: SL + TP + sizing
      "risk": "Stop loss 0.3%, take profit 0.6%, fixed 1% risk per trade"
    • ATR-based everythingFull ATR risk
      # RISK: ATR-based everything
      "risk": "ATR-based stop (1.5x ATR), ATR-based TP (3x ATR), position size = 1% / ATR"
    • Conservative fullLow risk setup
      # RISK: Conservative full
      "risk": "Stop loss 0.2%, take profit 0.6%, max 2 trades/day, half Kelly sizing"
    • Aggressive fullHigh risk setup
      # RISK: Aggressive full
      "risk": "Stop loss 0.5%, take profit 1.5%, Kelly sizing, no daily limit"
    Natural Language
    • NL, scale down on losing streakReduce size after losses
      # RISK: NL: scale down on losing streak
      "risk": "After 3 consecutive losing trades, reduce position size by 50%. Reset after a winner."
    • NL, no overnightClose before market quiet
      # RISK: NL: no overnight
      "risk": "Close all positions before 21:00 UTC (before forex daily rollover). No new entries after 20:30."
    • NL, volatility filterSkip low-vol periods
      # RISK: NL: volatility filter
      "risk": "Skip trades when ATR(14) is below its 50-bar average: not enough movement to be worth the spread"
    Position rules17
    Direction
    • Both directionsLong and short
      # POS: Both directions
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • Long onlyOnly buy
      # POS: Long only
      "pos_rules": {"max_pos": 1, "direction": "long", "on_opposite": "close_only", "cooldown": 0}
    • Short onlyOnly sell
      # POS: Short only
      "pos_rules": {"max_pos": 1, "direction": "short", "on_opposite": "close_only", "cooldown": 0}
    On Opposite
    • Reverse on oppositeFlip direction immediately
      # POS: Reverse on opposite
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • Close only on oppositeExit to flat, don't flip
      # POS: Close only on opposite
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "close_only", "cooldown": 0}
    • Ignore oppositeStay in trade, ignore reversals
      # POS: Ignore opposite
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "ignore", "cooldown": 0}
    Max Positions
    • 1 position maxSingle position at a time
      # POS: 1 position max
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • 2 concurrentAllow 2 trades at once
      # POS: 2 concurrent
      "pos_rules": {"max_pos": 2, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • 3 concurrentAllow 3 trades at once
      # POS: 3 concurrent
      "pos_rules": {"max_pos": 3, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    Cooldown
    • No cooldownRe-enter immediately
      # POS: No cooldown
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • 2-bar cooldownWait 2 bars after exit
      # POS: 2-bar cooldown
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 2}
    • 5-bar cooldownWait 5 bars
      # POS: 5-bar cooldown
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 5}
    • 10-bar cooldownLong cooldown, avoid overtrading
      # POS: 10-bar cooldown
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "reverse", "cooldown": 10}
    Combos
    • Conservative longLong only + close on opposite + cooldown
      # POS: Conservative long
      "pos_rules": {"max_pos": 1, "direction": "long", "on_opposite": "close_only", "cooldown": 3}
    • Aggressive scalperBoth directions + reverse + no cooldown
      # POS: Aggressive scalper
      "pos_rules": {"max_pos": 2, "direction": "both", "on_opposite": "reverse", "cooldown": 0}
    • Patient swingIgnore opposite + long cooldown
      # POS: Patient swing
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "ignore", "cooldown": 10}
    • Multi-position trend3 positions + long only
      # POS: Multi-position trend
      "pos_rules": {"max_pos": 3, "direction": "long", "on_opposite": "close_only", "cooldown": 5}
    Custom filter23
    Session
    • London session onlyTrade only during London hours
      # FILTER: London session only
      "risk_function": "Only trade during London session (08:00-16:00 UTC)"
    • NY session onlyTrade only during NY hours
      # FILTER: NY session only
      "risk_function": "Only trade during New York session (13:00-21:00 UTC)"
    • London-NY overlapBest liquidity hours
      # FILTER: London-NY overlap
      "risk_function": "Only trade during London-NY overlap (13:00-17:00 UTC)"
    • No Asian sessionSkip quiet hours
      # FILTER: No Asian session
      "risk_function": "No trading during Asian session (22:00-08:00 UTC)"
    • First hour of LondonTrade the open momentum
      # FILTER: First hour of London
      "risk_function": "Only take trades in first hour of London (08:00-09:00 UTC)"
    Day
    • No Friday tradesAvoid weekend gap risk
      # FILTER: No Friday trades
      "risk_function": "No new entries on Friday after 16:00 UTC. Close all positions by 20:00 UTC Friday."
    • No Monday morningSkip Monday gap reaction
      # FILTER: No Monday morning
      "risk_function": "No trades on Monday before 10:00 UTC: let the market settle after weekend gap"
    • Weekdays only (no weekend)Standard forex week
      # FILTER: Weekdays only (no weekend)
      "risk_function": "Only trade Monday 00:00 to Friday 20:00 UTC"
    • Tue-Thu onlyMid-week only
      # FILTER: Tue-Thu only
      "risk_function": "Only trade Tuesday through Thursday: skip Monday gaps and Friday squeezes"
    Volatility
    • High ATR onlyNeed movement to profit
      # FILTER: High ATR only
      "risk_function": "Only trade when ATR(14) is above its 20-bar average: need volatility for the trade to work"
    • Low ATR skipSkip dead markets
      # FILTER: Low ATR skip
      "risk_function": "Skip any signal when ATR(14) < 0.0003: spread will eat the profit"
    • BB squeeze skipAvoid range-bound
      # FILTER: BB squeeze skip
      "risk_function": "Skip signals when Bollinger Band width is below 20-bar low: market is too compressed"
    • Scale by volatilityLess size when wild
      # FILTER: Scale by volatility
      "risk_function": "Reduce position size by 50% when ATR is above 1.5x its average: lower risk in volatile conditions"
    Trend
    • Only with trendNo counter-trend trades
      # FILTER: Only with trend
      "risk_function": "Only take long signals when price is above SMA 200, only take short signals below SMA 200"
    • No counter-trendStrict trend following
      # FILTER: No counter-trend
      "risk_function": "Skip any buy signal when EMA 50 is below EMA 200 (downtrend). Skip sells in uptrend."
    • Momentum confirmNeed momentum behind signal
      # FILTER: Momentum confirm
      "risk_function": "Only take signals when 5-bar momentum is in the same direction as the signal"
    Loss
    • Stop after 3 lossesDrawdown circuit breaker
      # FILTER: Stop after 3 losses
      "risk_function": "After 3 consecutive losing trades in a day, stop trading for the rest of the day"
    • Daily loss limitCap daily losses
      # FILTER: Daily loss limit
      "risk_function": "Stop trading for the day if total daily loss exceeds 1% of capital"
    • Reduce after drawdownScale down in drawdown
      # FILTER: Reduce after drawdown
      "risk_function": "If equity is in a 5% drawdown from peak, reduce position size by 50% until new high"
    Cost
    • Wide spread skipProtect against bad fills
      # FILTER: Wide spread skip
      "risk_function": "Skip signals when spread is above 2 pips (0.0002): likely low liquidity"
    • News time skipAvoid slippage
      # FILTER: News time skip
      "risk_function": "No trades within 30 minutes before or after the hour mark (common news release times)"
    Combined
    • London + ATR + trendTriple filter
      # FILTER: London + ATR + trend
      "risk_function": "Only trade London session (08-16 UTC), when ATR > average, and price above SMA 200 for longs / below for shorts"
    • Full safety netMaximum protection
      # FILTER: Full safety net
      "risk_function": "London-NY overlap only, no Friday after 16:00, skip when ATR < average, stop after 3 consecutive losses, daily loss limit 1%"

    Backtesting

    Backtest config22
    • Default (beginner)Default config, $10K capital, 1 lot, 30x leverage, 55% threshold
      "capital": 10000,
      "lot_size": 1.0,
      "leverage": 30,
      "confidence_threshold": 55,
      "commission": 6.0,
      "swap_long": -1.0,
      "swap_short": 0.3,
      "timeframe": "15min"
    • ConservativeLower leverage, tighter threshold
      "capital": 10000,
      "lot_size": 0.5,
      "leverage": 50,
      "confidence_threshold": 65,
      "commission": 6.0,
      "swap_long": -1.0,
      "swap_short": 0.3,
      "timeframe": "15min"
    • AggressiveHigher leverage, lower threshold
      "capital": 10000,
      "lot_size": 2.0,
      "leverage": 200,
      "confidence_threshold": 50,
      "commission": 6.0,
      "swap_long": -1.0,
      "swap_short": 0.3,
      "timeframe": "15min"
    • Micro account$1K capital, 0.1 lot
      "capital": 1000,
      "lot_size": 0.1,
      "leverage": 100,
      "confidence_threshold": 55,
      "commission": 0.6,
      "swap_long": -0.1,
      "swap_short": 0.03,
      "timeframe": "15min"
    • Large account$100K capital, 10 lots
      "capital": 100000,
      "lot_size": 10.0,
      "leverage": 100,
      "confidence_threshold": 60,
      "commission": 60.0,
      "swap_long": -10.0,
      "swap_short": 3.0,
      "timeframe": "15min"
    • 1-min scalping1-minute timeframe
      "timeframe": "1min",
      "confidence_threshold": 50
    • 5-min intraday5-minute timeframe
      "timeframe": "5min",
      "confidence_threshold": 55
    • 1-hour swing1-hour timeframe
      "timeframe": "1h",
      "leverage": 50,
      "confidence_threshold": 60
    • High confidence (70%)Only trade when very confident
      "confidence_threshold": 70
      # Fewer trades, higher conviction
    • Low threshold (50%)Trade on any edge
      "confidence_threshold": 50
      # More trades, more noise
    • Zero commissionNo costs, pure signal test
      "commission": 0.0,
      "swap_long": 0.0,
      "swap_short": 0.0
      # Tests pure signal quality
    • High commission stressDouble costs, stress test
      "commission": 12.0,
      "swap_long": -2.0,
      "swap_short": 0.6
      # If still profitable, strategy is robust
    • 80/20 splitMore training data
      "train_split": 0.8
      # 80% train, 20% test
    • 60/40 splitMore validation data
      "train_split": 0.6
      # 60% train, 40% test: better validation
    • Short range (1 month)Quick test
      "start_date": "2026-03-01",
      "end_date": "2026-04-01"
    • Full range (10 months)Maximum data
      "start_date": "2025-06-01",
      "end_date": "2026-04-01"
    • Long onlyOnly buy positions
      "pos_rules": {"max_pos": 1, "direction": "long", "on_opposite": "close_only", "cooldown": 0}
    • Short onlyOnly sell positions
      "pos_rules": {"max_pos": 1, "direction": "short", "on_opposite": "close_only", "cooldown": 0}
    • 2 positions + cooldownAllow 2 concurrent, 5-bar cooldown
      "pos_rules": {"max_pos": 2, "direction": "both", "on_opposite": "reverse", "cooldown": 5}
    • Ignore oppositeStay in trade, ignore reversals
      "pos_rules": {"max_pos": 1, "direction": "both", "on_opposite": "ignore", "cooldown": 0}
      # Stays until stop/TP
    • Conservative scalper (full)Complete config combo
      {
          "capital": 10000, "lot_size": 0.5,
          "leverage": 50, "confidence_threshold": 60,
          "commission": 6.0, "timeframe": "5min",
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7
      }
    • Aggressive trend (full)Complete config combo
      {
          "capital": 50000, "lot_size": 5.0,
          "leverage": 200, "confidence_threshold": 55,
          "commission": 30.0, "timeframe": "1h",
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.8
      }

    API workflows

    Generate11
    • MACD Crossover, BasicSimple MACD crossover strategy with XGBoost
      import requests
      
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
          "features": "MACD (12,26,9)",
          "signals": "Buy when MACD crosses above signal line, sell when crosses below",
          "model": "XGBoost",
          "optimization": "Maximize Sharpe ratio",
          "risk": "Stop loss 0.3%",
          "indicators": {"macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers={"X-API-Key": "qm_YOUR_KEY"})
      
      print(resp.json()["code"][:200])
    • RSI Mean ReversionBuy oversold RSI, sell overbought RSI with Bollinger confirmation
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
          "features": "RSI 14, Bollinger Bands (20,2), Volume Z-score",
          "signals": "Buy when RSI < 30 and price near lower BB, sell when RSI > 70 and price near upper BB",
          "model": "Random Forest",
          "optimization": "Maximize Calmar ratio",
          "risk": "Stop loss 0.5%, max 3 trades per day",
          "indicators": {"rsi_enabled": true, "rsi_period": 14, "bb_enabled": true, "bb_period": 20, "bb_std": 2.0},
          "pos_rules": {"max_pos": 1, "on_opposite": "close_only", "direction": "both", "cooldown": 2},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • EMA Trend Following, Long OnlyLong-only trend strategy using EMA 50/200 golden cross
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
          "features": "EMA Cross (50/200), ATR 14",
          "signals": "Buy when EMA 50 crosses above EMA 200 (golden cross)",
          "model": "Gradient Boosting",
          "optimization": "Maximize return",
          "risk": "Stop loss 0.5%, Kelly position sizing",
          "indicators": {"ema_enabled": true, "ema_periods": "50,200", "atr_enabled": true, "atr_period": 14},
          "pos_rules": {"max_pos": 1, "direction": "long", "on_opposite": "close_only", "cooldown": 3},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • Stochastic + BB ScalperHigh-frequency scalping with Stochastic oversold/overbought + Bollinger breakout
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
          "features": "Stochastic (14,3), Bollinger Bands (20,2), RSI 14, ATR 14",
          "signals": "Buy when Stochastic K < 20 and price below lower BB, sell when K > 80 and price above upper BB",
          "model": "XGBoost",
          "optimization": "Maximize win rate",
          "risk": "Stop loss 0.3%, max 3 trades per day",
          "indicators": {
              "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3,
              "bb_enabled": true, "bb_period": 20, "bb_std": 2.0,
              "rsi_enabled": true, "rsi_period": 14,
              "atr_enabled": true, "atr_period": 14
          },
          "pos_rules": {"max_pos": 1, "on_opposite": "reverse", "cooldown": 1},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • Multi-Indicator ConservativeConservative strategy combining SMA, RSI, BB with tight drawdown control
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate", json={
          "features": "SMA (50,200), RSI 14, Bollinger Bands (20,2), ATR 14",
          "signals": "Buy when price above SMA 200, RSI between 40-60, and close to BB mid",
          "model": "Logistic Regression",
          "optimization": "Sharpe > 1 with MDD < 10%",
          "risk": "Stop loss 0.5%, fixed 1% risk per trade",
          "indicators": {
              "sma_enabled": true, "sma_periods": "50,200",
              "rsi_enabled": true, "rsi_period": 14,
              "bb_enabled": true, "bb_period": 20, "bb_std": 2.0,
              "atr_enabled": true, "atr_period": 14
          },
          "pos_rules": {"max_pos": 1, "direction": "long", "on_opposite": "close_only", "cooldown": 5},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • MACD with Custom Fast/SlowMACD with non-standard periods (8,21,5) for faster signals
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "MACD (8,21,5), RSI 14",
          "signals": "MACD crossover: faster periods for quicker entries",
          "model": "XGBoost",
          "optimization": "Maximize Sharpe ratio",
          "risk": "Stop loss 0.3%",
          "indicators": {"macd_enabled": true, "macd_fast": 8, "macd_slow": 21, "macd_signal": 5, "rsi_enabled": true},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • Short-Only StrategyShort-only RSI overbought strategy with ignore on opposite signals
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "RSI 14, Bollinger Bands (20,2)",
          "signals": "Short when RSI > 75 and price above upper Bollinger Band",
          "model": "Random Forest",
          "optimization": "Maximize win rate",
          "risk": "Stop loss 0.5%",
          "indicators": {"rsi_enabled": true, "rsi_period": 14, "bb_enabled": true},
          "pos_rules": {"max_pos": 1, "direction": "short", "on_opposite": "ignore", "cooldown": 3},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • Session-Filtered StrategyOnly trade during London-NY overlap with risk filter
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "MACD (12,26,9), ATR 14, Volume Z-score",
          "signals": "MACD crossover with volume confirmation",
          "model": "XGBoost",
          "optimization": "Maximize Sharpe ratio",
          "risk": "Stop loss 0.3%, fixed 1% risk per trade",
          "risk_function": "Only trade during London-NY overlap (13:00-17:00 UTC). No trading on Fridays after 18:00 UTC. Skip if ATR is below its 20-bar average.",
          "indicators": {"macd_enabled": true, "atr_enabled": true, "atr_period": 14},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • ATR-Based Position SizingUse ATR to dynamically size positions, wider stops when volatile
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "EMA Cross (50/200), ATR 14, RSI 14",
          "signals": "MA crossover with RSI between 40-60 as filter",
          "model": "Gradient Boosting",
          "optimization": "Minimize max drawdown",
          "risk": "ATR-based stop loss: stop = 2 x ATR(14). Position size = 1% account risk / stop distance. Scale down when ATR > 1.5x its 20-bar average.",
          "indicators": {"ema_enabled": true, "ema_periods": "50,200", "atr_enabled": true, "atr_period": 14, "rsi_enabled": true},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • WMA + Stochastic ComboWeighted Moving Average trend + Stochastic timing
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "WMA 20, Stochastic (14,3), ATR 14",
          "signals": "Buy when price above WMA and Stochastic crosses above 20 from below. Sell when price below WMA and Stochastic crosses below 80 from above.",
          "model": "XGBoost",
          "optimization": "Maximize Sharpe ratio",
          "risk": "Stop loss 0.4%",
          "indicators": {"wma_enabled": true, "wma_periods": "20", "stoch_enabled": true, "stoch_k": 14, "stoch_d": 3, "atr_enabled": true},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    • Max 2 Positions + CooldownAllow 2 concurrent positions with 5-bar cooldown between trades
      resp = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "MACD (12,26,9), RSI 14, Bollinger Bands (20,2)",
          "signals": "MACD crossover confirmed by RSI",
          "model": "XGBoost",
          "optimization": "Maximize return",
          "risk": "Stop loss 0.3% per position",
          "indicators": {"macd_enabled": true, "rsi_enabled": true, "bb_enabled": true},
          "pos_rules": {"max_pos": 2, "on_opposite": "reverse", "direction": "both", "cooldown": 5},
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
    Templates3
    • MACD MomentumUse the built-in MACD Momentum template with no customization
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate/from-template", json={
          "template": "macd_momentum",
          "start_date": "2025-06-01",
          "end_date": "2026-04-01",
          "train_split": 0.7,
          "claude_model": "sonnet"
      }, headers=HEADERS)
      
      print(resp.json()["template_name"])  # "MACD Momentum"
    • Scalper, Long Only OverrideUse scalper template but override to long-only with custom RSI period
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate/from-template", json={
          "template": "scalper",
          "start_date": "2025-06-01",
          "end_date": "2026-04-01",
          "pos_rules": {"direction": "long"},
          "indicators": {"rsi_period": 21},
          "claude_model": "sonnet"
      }, headers=HEADERS)
      
      # Template indicators (stoch, bb, rsi, atr) preserved
      # RSI period overridden from 14 to 21
      # Direction overridden to long-only
    • Mean Reversion + Custom RiskMean reversion template with custom risk filter for session hours
      resp = requests.post("https://api.quantifyme.ai/api/v1/generate/from-template", json={
          "template": "mean_reversion",
          "start_date": "2025-06-01",
          "end_date": "2026-04-01",
          "risk_function": "Only trade during London-NY overlap (13:00-17:00 UTC), skip Fridays after 18:00",
          "claude_model": "sonnet"
      }, headers=HEADERS)
    Train1
    • Train Model from Generated CodeGenerate strategy, then submit for training and poll until done
      import time
      
      # Step 1: Generate
      gen = requests.post(f"{BASE}/api/v1/generate", json={
          "features": "MACD, RSI 14",
          "signals": "MACD crossover with RSI confirmation",
          "model": "XGBoost",
          "optimization": "Maximize Sharpe",
          "risk": "Stop loss 0.3%",
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "claude_model": "sonnet"
      }, headers=HEADERS)
      code = gen.json()["code"]
      
      # Step 2: Train
      train = requests.post(f"{BASE}/api/v1/train", json={
          "code": code, "model_name": "My MACD Model",
          "start_date": "2025-06-01", "end_date": "2026-04-01",
          "train_split": 0.7, "timeframe": "15min"
      }, headers=HEADERS)
      job_id = train.json()["job_id"]
      
      # Step 3: Poll
      while True:
          s = requests.get(f"{BASE}/api/v1/train/{job_id}", headers=HEADERS).json()
          print(s["status"])
          if s["status"] in ("done", "failed"): break
          time.sleep(3)
      
      if s["status"] == "done":
          print(s["metrics"])
    Indicators3
    • Compute RSI ValuesGet RSI 14 values for last 100 bars without training
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators", json={
          "indicators": {"rsi_enabled": true, "rsi_period": 14},
          "symbol": "EURUSD",
          "timeframe": "15min",
          "limit": 100,
          "format": "columns"
      }, headers=HEADERS)
      
      data = resp.json()
      print(data["ind_rsi14"][:5])     # [45.2, 48.1, 52.3, ...]
      print(data["timestamps"][:5])    # ["2026-04-13 22:00:00", ...]
    • Compute MACD + BB + ATRGet multiple indicators at once in row format
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators", json={
          "indicators": {
              "macd_enabled": true, "macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
              "bb_enabled": true, "bb_period": 20, "bb_std": 2.0,
              "atr_enabled": true, "atr_period": 14
          },
          "symbol": "EURUSD",
          "timeframe": "1h",
          "start": "2026-04-01",
          "limit": 50,
          "format": "rows"
      }, headers=HEADERS)
      
      for row in resp.json()["data"][:3]:
          print(row["timestamp"], row["ind_macd_line"], row["ind_bb_pct"])
    • Compute SMA Distance from PriceSMA 20/50/200 with distance-from-price features
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators", json={
          "indicators": {"sma_enabled": true, "sma_periods": "20,50,200"},
          "timeframe": "15min",
          "limit": 200
      }, headers=HEADERS)
      
      data = resp.json()
      # data["ind_sma20"]: raw SMA 20 values
      # data["ind_dm_sma20"]: distance: (close - sma20) / sma20
      # data["ind_sma50"], data["ind_dm_sma50"], etc.
      print(f"Indicators computed: {data['meta']['indicators_computed']}")
    Custom indicator3
    • SupertrendGenerate a Supertrend indicator from natural language
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators/custom", json={
          "source": "Supertrend indicator with ATR period 10 and multiplier 3. Show buy/sell signals on crossover.",
          "symbol": "EURUSD",
          "timeframe": "15min",
          "limit": 2000,
          "provider": "anthropic",
          "fe_mode": "basic"
      }, headers=HEADERS)
      
      result = resp.json()
      print(f"Name: {result['name']}")
      print(f"Overlays: {len(result['overlays'])}")
      print(f"Signals: {len(result['signals'])}")
      print(f"Features: {list(result['features'].keys())}")
    • Hull MAHull Moving Average with trend coloring
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators/custom", json={
          "source": "Hull Moving Average (HMA) with period 20. Color green when rising, red when falling. Generate buy signal when HMA turns from falling to rising, sell when turns from rising to falling.",
          "timeframe": "15min",
          "fe_mode": "full"
      }, headers=HEADERS)
      
      result = resp.json()
      print(f"{result['name']}: {len(result['signals'])} signals")
      print(f"ML features: {len(result['features'])} columns")
    • Pine Script RSI DivergenceConvert Pine Script RSI divergence detector to Python
      pine_code = """
      //@version=5
      indicator('RSI Divergence', overlay=false)
      rsi_len = input(14)
      rsi_val = ta.rsi(close, rsi_len)
      bull_div = rsi_val < 30 and rsi_val > rsi_val[5] and close < close[5]
      bear_div = rsi_val > 70 and rsi_val < rsi_val[5] and close > close[5]
      plot(rsi_val)
      plotshape(bull_div, style=shape.triangleup, location=location.bottom)
      plotshape(bear_div, style=shape.triangledown, location=location.top)
      """
      
      resp = requests.post("https://api.quantifyme.ai/api/v1/indicators/custom", json={
          "source": pine_code,
          "timeframe": "15min",
          "fe_mode": "basic"
      }, headers=HEADERS)
    Discovery2
    • Discover Available PresetsList all chip presets, templates, and position rules options
      # No auth needed for discovery endpoints
      presets = requests.get(f"{BASE}/api/v1/presets").json()
      
      print("Feature chips:", presets["chips"]["features"])
      print("Signal chips:", presets["chips"]["signals"])
      print("Model chips:", presets["chips"]["model"])
      print()
      print("Templates:")
      for key, t in presets["templates"].items():
          print(f"  {key}: {t['name']}: {t['description']}")
      print()
      print("Position rules:")
      for k, v in presets["pos_rules_schema"].items():
          print(f"  {k}: options={v.get('options','any')}, default={v['default']}")
    • Discover Indicator SchemaList all available indicators with params and defaults
      schema = requests.get(f"{BASE}/api/v1/indicator-schema").json()
      
      for name, ind in schema["indicators"].items():
          params = ", ".join(f"{k}={v['default']}" for k, v in ind["params"].items())
          features = ", ".join(ind["features_generated"])
          print(f"{name:8} | {ind['description'][:50]:50} | {params}")
          print(f"{'':8} | features: {features}")
    Data1
    • Get OHLC DataFetch raw OHLC candle data for analysis
      resp = requests.get(f"{BASE}/api/v1/ohlc", params={
          "symbol": "EURUSD",
          "timeframe": "15min",
          "start": "2026-04-01",
          "limit": 100
      }, headers=HEADERS)
      
      data = resp.json()
      print(f"{data['rows']} rows, {data['tokens_remaining']} tokens left")
      for bar in data["data"][:3]:
          print(f"{bar['time']} O={bar['open']:.5f} H={bar['high']:.5f} L={bar['low']:.5f} C={bar['close']:.5f}")
    Models1
    • List All Trained ModelsFetch all your trained models with metadata
      resp = requests.get(f"{BASE}/api/v1/models", headers=HEADERS)
      
      for m in resp.json()["models"]:
          print(f"{m['model_name']:20} trained: {m.get('train_start','')} → {m.get('train_end','')}")
    QuantifyMe
    DocsAgentsCommunityPricing
    Sign in