A backtestable signal engine for perpetual-futures strategies — DSL, indicators, and an honest backtester.
Project description
perpsignal
A backtestable signal engine for perpetual-futures strategies. Write a strategy as a compact expression (or a JSON signal definition), evaluate it against OHLCV data, and backtest it into honest metrics — Sharpe, return, drawdown, win rate — with fees, funding, stops/targets, and leverage modelled.
This is the open-source core extracted from Signalview, a non-custodial platform where backtested perps strategies are scored and traded by AI agents on Hyperliquid. The engine here has no wallet, key, custody, or live-trading code — it's a pure research/backtest library, safe to run anywhere.
⚠️ Research and backtesting only. Nothing here is financial advice, and a backtest is not a promise of future results. Perpetual-futures trading is high-risk.
Install
pip install perpsignal # once published
# or, from source:
pip install git+https://github.com/mokshyaprotocol/signalview
Requires Python 3.10+, pandas, numpy, requests.
Quickstart
import pandas as pd
from perpsignal import evaluate, discretize, run, BacktestConfig, RiskConfig
# df needs columns: open, high, low, close, volume (a DatetimeIndex is ideal)
df = pd.read_parquet("BTCUSDT-1h.parquet")
cfg = BacktestConfig(symbol="BTCUSDT", interval="1h") # holds the entry thresholds
# A score is any expression that evaluates to a Series (positive = long).
# This one is a mean-reversion fade: high when price is stretched below its
# 48-bar mean, low when stretched above.
score = evaluate("zscore(close, 48) * -1", df)
# Map the continuous score to a {-1, 0, +1} position via the config thresholds.
# run() expects a discrete position, not a raw score.
position = discretize(score, cfg)
result = run(
df, position, cfg,
RiskConfig(), # leverage / take-profit / stop-loss (sane defaults)
bars_per_year=24 * 365, # hourly bars
)
print(result.metrics) # {'sharpe': ..., 'total_return': ..., 'max_drawdown': ..., 'win_rate': ..., 'trades': ...}
The signal DSL
Expressions are built from market variables and functions.
Variables: close, high, low, open, volume, funding, oi
(open interest), bar_index.
Functions:
| Trend / momentum | rsi(close, n), ema(close, n), sma(close, n), slope(close, n), adx(n), macd-style via ema diffs |
| Volatility | atr(n), stdev(x, n), bb_width(close, n, k), bb_upper/bb_lower/bb_mid(close, n, k) |
| Normalization | zscore(x, n), clip(x, lo, hi), sign(x), abs(x), log(x), sqrt(x), tanh(x) |
| Volume / flow | vwap(n), session_vwap(), corr(a, b, n) |
| Windowing | highest(x, n), lowest(x, n), prev(x, k) |
| Logic | if(cond, a, b), min, max, comparisons (>, <, >=, ...), and/or |
Expressions are parsed by a real tokenizer→parser→evaluator (perpsignal.dsl)
and include an auto-repair pass (parse_with_repair) that fixes common
mistakes and reports what it changed — handy when the author is an LLM.
Signals as data
A strategy can also be a JSON SignalDef (portable, diffable, PR-able):
from perpsignal import parse_signal
sig = parse_signal({
"asset": "BTCUSDT", "timeframe": "1h",
"expression": "rsi(close, 14) - 50",
# ... weights, regime config, risk bounds
})
See examples/ for runnable scripts and a sample signal file.
Fetching data
perpsignal.data pulls public Binance / Hyperliquid OHLCV and caches to disk.
An optional Upstash cache layer self-disables when its env vars are unset — you
never need it to run locally.
Contributing
New indicators, factors, and strategies are very welcome — this engine exists to be extended. A new built-in is usually one function plus one test. See CONTRIBUTING.md. Every PR is backtested in CI so improvements are judged on objective metrics, not opinion — which also makes this a clean target for autonomous/AI-agent strategy search.
License
Apache License 2.0. © 2026 Signalview.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file perpsignal-0.1.0.tar.gz.
File metadata
- Download URL: perpsignal-0.1.0.tar.gz
- Upload date:
- Size: 70.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
faa2bde935989030636a0937fe45ef771ba85b1db362920b85f4edd4f1d2759d
|
|
| MD5 |
4d8533a9cafe3ec41a72ca33c51845f7
|
|
| BLAKE2b-256 |
ef1f7b655a20af6641bdf3fa73c0bc831c92ac4dab065f380a52edda6d60ac25
|
Provenance
The following attestation bundles were made for perpsignal-0.1.0.tar.gz:
Publisher:
publish.yml on mokshyaprotocol/signalview
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
perpsignal-0.1.0.tar.gz -
Subject digest:
faa2bde935989030636a0937fe45ef771ba85b1db362920b85f4edd4f1d2759d - Sigstore transparency entry: 2033282579
- Sigstore integration time:
-
Permalink:
mokshyaprotocol/signalview@63a5fa593ca2142b0ea6951cb34517e74e5dcfb7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mokshyaprotocol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@63a5fa593ca2142b0ea6951cb34517e74e5dcfb7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file perpsignal-0.1.0-py3-none-any.whl.
File metadata
- Download URL: perpsignal-0.1.0-py3-none-any.whl
- Upload date:
- Size: 69.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b15641d96c88ddcd2359fd6f519b3d36f29a721e45ec929c96eda0d66e1ab10
|
|
| MD5 |
97c56734be542b898cfe5311c8ac0b0d
|
|
| BLAKE2b-256 |
10fa6fad0403fa040eb8d19cdd5a6ae5981c5280b99e813832d6f7b9ba0dad27
|
Provenance
The following attestation bundles were made for perpsignal-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mokshyaprotocol/signalview
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
perpsignal-0.1.0-py3-none-any.whl -
Subject digest:
7b15641d96c88ddcd2359fd6f519b3d36f29a721e45ec929c96eda0d66e1ab10 - Sigstore transparency entry: 2033282676
- Sigstore integration time:
-
Permalink:
mokshyaprotocol/signalview@63a5fa593ca2142b0ea6951cb34517e74e5dcfb7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mokshyaprotocol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@63a5fa593ca2142b0ea6951cb34517e74e5dcfb7 -
Trigger Event:
release
-
Statement type: