SkillAgentSearch skills...

Evosignal

High-Frequency Trading Strategies Discoved by EvoSignal - LLM-Driven Scientific Discovery (AlphaEvolve-like)

Install / Use

/learn @kayuksel/Evosignal
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

AlphaEvolve for Discovery of HF Trading Strategies

Overview

This repository implements a novel, adaptive technical indicator discovered through LLM-driven scientific discovery. The indicator synthesizes multi-horizon momentum, volatility regime detection, tail-risk adjustment, and Gaussian-weighted trend filtering to generate a normalized trading signal for the AUDNZD currency pair on hourly data. The parameters of the discovered trading strategy are not tuned.

Results

Below equity curve generated by applying the discovered strategy to AUDNZD hourly data (rolling windows of length=200 are fed to the below technical_indicator function to generate signals, and then positions are taken by thresholding values generated by the technical indicator.)

Strategy Results

Example Technical Indicator Code

def technical_indicator(ohlcv: torch.Tensor, eps = 1e-06) -> torch.Tensor:
    (n, T, f) = ohlcv.shape
    pad = lambda x, L: x if x.size(1) >= L else F.pad(x, (L - x.size(1), 0), mode='replicate')
    log_close = ohlcv[..., 3].clamp_min(eps).log()
    rts = log_close - torch.cat([log_close[:, :1], log_close[:, :-1]], dim=1)
    base_win = 20
    vol_recent = pad(rts, base_win)[:, -base_win:].std(dim=1)
    adapt = (1 + 0.2 * ((vol_recent - vol_recent.median()) / (vol_recent.median() + eps))).clamp(0.8, 1.2)
    multi_fd = torch.stack([rts[:, -1] - pad(rts, w)[:, -w] for w in [5, 10, 20]], dim=0).mean(dim=0).tanh()
    entropy = (1 + pad(rts, base_win).unfold(1, base_win, 1).std(dim=2)).log().mean(dim=1).sigmoid()
    vs = pad(ohlcv[..., 4], 60)
    dv = vs[:, 1:] - vs[:, :-1]
    avg_gain = dv.clamp_min(0).unfold(1, 14, 1).mean(dim=2)[:, -1]
    avg_loss = (-dv).clamp_min(0).unfold(1, 14, 1).mean(dim=2)[:, -1].clamp_min(eps)
    vol_exp = (vs.std(dim=1) / (vs.mean(dim=1) + eps)).clamp(0.8, 1.2)
    rsi_norm = ((100 - 100 / (1 + avg_gain / avg_loss)) / 100) ** vol_exp
    vol_adj = (vs[:, -1] / (vs.mean(dim=1) + eps)).sigmoid() * pad(vs, 14).unfold(1, 14, 1).std(dim=2)[:, -1].sigmoid()
    ens_wins = torch.tensor([10, 30, 60], device=rts.device, dtype=torch.long)
    rp = pad(rts, int(ens_wins.max().item()))
    blend = lambda x: 0.3 * x.quantile(0.25, dim=1) + 0.4 * x.quantile(0.5, dim=1) + 0.3 * x.quantile(0.75, dim=1)
    (S_list, W_list) = ([], [])
    for w in ens_wins.tolist():
        last_roll = rp.unfold(1, w, 1)[:, -1, :]
        wk = torch.exp(-0.5 * ((torch.arange(w, device=rts.device, dtype=rts.dtype) - (w - 1)) / (w * 0.5 + eps)) ** 2)
        moment = (last_roll * wk / (wk.sum() + eps)).sum(dim=1)
        m_last = last_roll.mean(dim=1)
        std_last = last_roll.std(dim=1).clamp_min(eps)
        skew = ((last_roll - m_last.unsqueeze(1)) ** 3).mean(dim=1) / std_last ** 3
        kurt = ((last_roll - m_last.unsqueeze(1)) ** 4).mean(dim=1) / std_last ** 4 - 3
        q_val = last_roll.quantile(0.05, dim=1)
        msk = last_roll < q_val.unsqueeze(1)
        cvar_est = last_roll.masked_fill(~msk, 0).sum(dim=1) / msk.sum(dim=1).clamp_min(1)
        tail = (-(cvar_est - q_val) * (1 + torch.relu(-skew))).sigmoid()
        comb = entropy * moment + (1 - entropy) * blend(last_roll) 
        comb += 0.1 * (skew.tanh() - kurt.tanh() + rsi_norm + multi_fd.tanh())
        S_list.append((-(comb * vol_adj / (1 + 0.5 * vol_recent)) ** 2).exp() * tail * multi_fd.tanh().sigmoid())
        W_list.append(moment.sigmoid() / (std_last ** 2 + eps))
    dyn_w = (-torch.stack(W_list, dim=0)).softmax(dim=0)
    multi_ens = (torch.stack(S_list, dim=0) * dyn_w).sum(dim=0)
    weights = torch.arange(rp.size(1), device=rts.device, dtype=rts.dtype).unsqueeze(0)
    wei_num = 0.7 * (-adapt.unsqueeze(1) * weights).exp() + 0.3 * (-0.05 * weights).exp()
    wei = wei_num / (wei_num.sum(dim=1, keepdim=True) + eps)
    trend = (-10 * ((rp * wei).sum(dim=1) - rp[:, -1]) ** 2).exp() 
    cross = (-(8 * (rp[:, -1] - rp[:, -1].median()) / (rts.std(dim=1) + eps))).sigmoid()
    return (multi_ens * trend * cross + eps).pow(1 / 3) * (1 + 0.1 * multi_fd)

Strategy Description

  1. Volatility Regime Detection

    • Measures each asset’s volatility over the most recent 20 periods (standard deviation of log-returns) and benchmarks it against the cross-sectional median volatility across all assets.
    • Defines an adapt factor in [0.8, 1.2] that down-weights signals when volatility is unusually high and up-weights them when volatility is unusually low.
  2. Adaptive Decay Parameter

    • Uses the adapt factor to set the exponential decay rates for weighing past returns: higher adapt → faster decay (focus on the very recent), lower adapt → slower decay (longer memory).
    • Ensures the strategy automatically zooms in or out on past data depending on current volatility regimes.
  3. Multi-Window Momentum with Tail Risk

    • For windows of 10, 30, and 60 periods, applies Gaussian-shaped weights (peaking on the most recent day) to compute a decayed momentum (“moment”) over each horizon.
    • Calculates 5% Conditional Value at Risk (CVaR) by averaging the worst 5% of returns in each window and adjusts for skewness to quantify downside risk.
    • Blends each window’s momentum and tail-risk via a penalty on extreme moves, then aggregates the three signals into one multi_ens score using inverse-variance weighting.
  4. Gaussian-Weighted Trend Filters

    • Applies two complementary exponential-decay filters (one adaptive to volatility via adapt, one fixed) across the full return history to measure trend consistency.
    • Penalizes the signal if today’s return diverges sharply from the time-weighted historical average, enforcing smooth, coherent trends.
  5. Cross-Sectional Skew Adjustment

    • Within each sub-model, computes the skewness of the past-w returns and uses a tanh(skew) term to tilt signals in the direction of pronounced asymmetry.
    • At the final stage, measures how far today’s return deviates from its own historical median (in units of its own volatility) and runs that through a sigmoid to dampen outsized moves.
  6. Aggregation & Normalization

    • Multiplies together the ensemble momentum signal (multi_ens), the trend-consistency filter, and the historical-median return filter, then adds a tiny epsilon to avoid zeros.
    • Applies a cube-root (power 1/3) to soften extremes, and finally tilts the result by (1 + 0.1 × short-term momentum) to re-emphasize fresh price action.

References

  1. AlphaQuant: LLM-Driven Automated Robust Feature Engineering for Quantitative Finance. In Proceedings of the Thirteenth International Conference on Learning Representations (ICLR 2025), Singapore. Available at SSRN: https://ssrn.com/abstract=5124841.

  2. AlphaPortfolio: Discovery of Portfolio Optimization and Allocation Methods Using LLMs. In Proceedings of the Thirteenth International Conference on Learning Representations (ICLR 2025), Singapore. Available at SSRN: https://ssrn.com/abstract=5118317.

  3. AlphaSharpe: LLM-Driven Discovery of Robust Risk-Adjusted Metrics. Preprint, arXiv:2502.00029. Available at SSRN: https://ssrn.com/abstract=5111141.

  4. AlphaLoss: LLM-Driven Evolution of Robust, Interpretable, and Multi-Objective Portfolio Optimization Loss Functions. Submitted to the European Conference on Machine Learning and Principles and Practice of Knowledge Discovery in Databases (ECML-PKDD 2025), Porto. Available at SSRN: https://ssrn.com/abstract=5263279.

  5. AlphaEvolve: A coding agent for scientific and algorithmic discovery. White paper by Alexander Novikov et al., June 16, 2025. Preprint, arXiv:2506.13131. Available at SSRN: https://arxiv.org/abs/2506.13131.

  6. R&D-Agent-Quant: A Multi-Agent Framework for Data-Centric Factors and Model Joint Optimization. Preprint, arXiv:2505.15155v1. Available at: https://arxiv.org/abs/2505.15155v1.

  7. QuantEvolve: Automating Quantitative Strategy Discovery through a Multi-Agent Evolutionary Framework. Preprint, arXiv:2510.18569. Available at: https://arxiv.org/abs/2510.18569.

  8. EvoRisk: Autonomously Discovered Regime-Adaptive Resilience-Aware Financial Metric. Submitted to the Thirteenth International Conference on Learning Representations (ICLR 2026). Preprint, Available at SSRN: https://ssrn.com/abstract=5791002.

Related Skills

View on GitHub
GitHub Stars10
CategoryDevelopment
Updated8d ago
Forks3

Languages

Python

Security Score

75/100

Audited on Mar 28, 2026

No findings