Skip to main content

A domain-specific configuration language for trading systems

Project description

tradsl

A powerful domain-specific configuration language for trading systems. Define your trading strategy, models, data adapters, and backtest configuration in a single declarative DSL with built-in feature computation and backtesting.

Features

  • Declarative DSL - Define timeseries, models, agents, adapters, and parameters in a simple text format
  • Parameter Blocks - Reusable parameter sets (mlparams:, windowparams:) that can be referenced across your config
  • Data Adapters - Plug in any data source adapter via class path resolution
  • Submodels - Use models as inputs to other models for ensemble/hierarchical strategies
  • DAG Execution - Automatic topological ordering with cycle detection
  • Type Safety - Schema validation for all config blocks
  • Feature Engine - Compute features via DAG with support for timeseries functions and model predictions
  • Training Scheduler - Rolling/expanding window training with configurable retrain schedules
  • Backtest Interpreter - Run full backtests with event-driven feature computation
  • Violent Failure - Explicit errors for invalid sizer output, model failures, and data issues

Installation

pip install -e .

Requires: pandas, numpy

Quick Start

import tradsl
from tradsl.utils import TradslInterpreter, load_timeseries, compute_features
from datetime import datetime

# Define your strategy
config_str = """
mlparams:
  lr=0.001
  epochs=100

:yfinance
type=adapter
class=adapters.YFAdapter

:nvda
type=timeseries
adapter=yfinance
parameters=["nvda"]

:vix
type=timeseries
adapter=yfinance
parameters=["^VIX"]

:nvda_ma30
type=timeseries
function=rolling_mean
inputs=[nvda]
params=mlparams

:signal_model
type=model
class=RandomForest
inputs=[nvda, vix, nvda_ma30]
params=mlparams
dotraining=true
retrain_schedule=weekly
training_window=rolling
training_window_size=500

:agent
type=agent
inputs=[signal_model, vix]
tradable=[nvda]
sizer=kelly_sizer

:backtest
type=backtest
start=2020-01-01
end=2024-01-01
capital=100000
"""

# Define your Python functions/classes
def rolling_mean(data, **kwargs):
    window = kwargs.get('window', 30)
    return data.rolling(window=window).mean()

class RandomForest:
    def __init__(self, lr=0.001, epochs=100, **kwargs):
        self.lr = lr
        self.epochs = epochs
    
    def train(self, X, y, **kwargs):
        # Training logic here
        pass
    
    def predict(self, X, **kwargs):
        # Return dict of output_name -> values
        return {'allocation': [0.5] * len(X)}

def kelly_sizer(signals, tradable):
    """Must return dict mapping each tradable symbol to allocation weight"""
    return {sym: 1.0 / len(tradable) for sym in tradable}

# Parse and resolve
config = tradsl.parse(config_str, context={
    'rolling_mean': rolling_mean,
    'RandomForest': RandomForest,
    'kelly_sizer': kelly_sizer,
    'adapters.YFAdapter': YourAdapterClass,
})

# Run backtest
interpreter = TradslInterpreter(config)
results = interpreter.run_backtest(
    start=datetime(2020, 1, 1),
    end=datetime(2024, 1, 1),
    frequency='1min'
)

DSL Syntax

Parameter Blocks

mlparams:
  lr=0.001
  epochs=100

windowparams:
  window=30
  min_periods=10

Adapters

:yfinance
type=adapter
class=adapters.YFAdapter

Timeseries

:nvda
type=timeseries
adapter=yfinance
parameters=["nvda"]

Or derived timeseries:

:nvda_ma30
type=timeseries
function=rolling_mean
inputs=[nvda]
params=windowparams

Models

:signal_model
type=model
class=RandomForest
inputs=[nvda, vix]
params=mlparams
dotraining=true
retrain_schedule=weekly
training_window=rolling
training_window_size=500
load_from=./models/signal_model.pkl

Submodels (Model Ensemble)

:ensemble
type=model
class=EnsembleModel
inputs=[signal_model, another_model]

Agent

:agent
type=agent
inputs=[signal_model, vix]
tradable=[nvda]
sizer=kelly_sizer

Backtest

:backtest
type=backtest
start=2020-01-01
end=2024-01-01
capital=100000

Output Structure

The parse() function returns a dict with:

  • Config blocks - Your timeseries, models, agent with resolved callables
  • _params - Parameter blocks dict
  • _adapters - Instantiated adapter objects
  • _backtest - Backtest configuration
  • _execution_order - Topological sort of nodes
  • _graph - Dependency graph (deps, reverse_deps)

Utilities

load_timeseries(config, start, end, frequency)

Load historical data from configured adapters:

from tradsl.utils import load_timeseries
from datetime import datetime

df = load_timeseries(config, datetime(2020, 1, 1), datetime(2024, 1, 1))
# Returns DataFrame with columns like nvda_close, vix_volume, etc.

compute_features(config, data)

Compute all features via DAG:

from tradsl.utils import compute_features

features = compute_features(config, raw_data)
# Adds computed columns for timeseries functions and model predictions

TradslInterpreter

Full backtest runner:

from tradsl.utils import TradslInterpreter

interpreter = TradslInterpreter(config)
interpreter.load_data(start, end)
interpreter.compute_initial_features()
interpreter.train_models()

results = interpreter.run_backtest(start, end, frequency='1min')

Context Resolution

When calling tradsl.parse(), pass a context dict with:

  • Functions: rolling_mean, kelly_sizer, etc.
  • Model classes: RandomForest, LSTM, etc.
  • Adapter classes: adapters.YFAdapter (full class path as key)
config = tradsl.parse(source, context={
    'my_function': my_function,
    'adapters.YFAdapter': YFAdapterClass,
})

Violent Failure

The system uses violent failure - explicit errors are raised for:

  • Sizer output: Wrong keys, None, NaN/Inf, negative values, non-dict returns
  • Model prediction: Failures or wrong return types
  • Training: Instantiation failures, training errors
  • Data loading: Adapter failures or empty data

This prevents silent failures and makes debugging explicit.

Testing

# Run all tests
python -m pytest tradsl/ -v

# Run specific test file
python -m pytest tradsl/test_parser.py -v

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tradsl-0.0.1.tar.gz (27.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tradsl-0.0.1-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

Details for the file tradsl-0.0.1.tar.gz.

File metadata

  • Download URL: tradsl-0.0.1.tar.gz
  • Upload date:
  • Size: 27.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.1

File hashes

Hashes for tradsl-0.0.1.tar.gz
Algorithm Hash digest
SHA256 bcc599a843e4b30c10408c83eb4839285b6ce36b015415160cb71d49bdc2e30a
MD5 f09623a0820140a650e9df115425235d
BLAKE2b-256 76a2011146801d1ca61941167463a5122a53b348383c0206822e78078d7e5bbc

See more details on using hashes here.

File details

Details for the file tradsl-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: tradsl-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 35.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.1

File hashes

Hashes for tradsl-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 53ffec53d703f551ddce874402f4969870f05c46cfe6baf1e5fc02bc8205d3ca
MD5 66d2626f6909699770171ec6f45cf2aa
BLAKE2b-256 ef0fa64b1e4a74970f36dea3ac316a021ca7876f3340301ce183e7995c72474c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page