Python Integration¶
Use sigc from Python with the pysigc package.
Installation¶
Quick Start¶
Python
import pysigc
# Run a strategy file
results = pysigc.run("strategy.sig")
# Access results
print(f"Total Return: {results.total_return:.1%}")
print(f"Sharpe Ratio: {results.sharpe_ratio:.2f}")
print(f"Max Drawdown: {results.max_drawdown:.1%}")
Running Strategies¶
From File¶
From String¶
Python
strategy = """
data:
source = "prices.csv"
format = csv
columns:
date: Date
ticker: Symbol
close: Numeric as prices
signal momentum:
emit zscore(ret(prices, 60))
portfolio main:
weights = rank(momentum).long_short(top=0.2, bottom=0.2)
backtest from 2020-01-01 to 2024-12-31
"""
results = pysigc.run_string(strategy)
With Parameters¶
With Custom Data¶
Python
import pandas as pd
# Your data
df = pd.read_csv("my_prices.csv")
# Run with data
results = pysigc.run(
"strategy.sig",
data={"prices": df}
)
Results Object¶
Performance Metrics¶
Python
results = pysigc.run("strategy.sig")
# Return metrics
results.total_return # Total return
results.cagr # Compound annual growth rate
results.daily_return # pandas Series of daily returns
# Risk metrics
results.volatility # Annualized volatility
results.sharpe_ratio # Sharpe ratio
results.sortino_ratio # Sortino ratio
results.max_drawdown # Maximum drawdown
results.calmar_ratio # Calmar ratio
# Benchmark metrics (if benchmark specified)
results.alpha # Alpha
results.beta # Beta
results.information_ratio # Information ratio
results.tracking_error # Tracking error
Weights and Positions¶
Python
# Target weights (pandas DataFrame)
weights = results.weights
# Columns: date, ticker, weight
# Position history
positions = results.positions
# Columns: date, ticker, shares, value
# Current positions
current = results.current_positions()
Signals¶
Python
# Access computed signals
signals = results.signals
# Dict[str, pd.DataFrame] - signal name to values
momentum = results.signals["momentum"]
# Columns: date, ticker, value
Trades¶
Python
# Trade history
trades = results.trades
# Columns: date, ticker, side, quantity, price
# Trade statistics
print(f"Total trades: {len(trades)}")
print(f"Turnover: {results.turnover:.1%}")
Jupyter Notebooks¶
Display Results¶
Python
import pysigc
results = pysigc.run("strategy.sig")
# Rich display in Jupyter
results # Shows formatted summary
Plot Performance¶
Python
import matplotlib.pyplot as plt
# Plot cumulative returns
results.plot_cumulative_returns()
plt.show()
# Plot drawdown
results.plot_drawdown()
plt.show()
# Plot monthly returns heatmap
results.plot_monthly_returns()
plt.show()
Interactive Analysis¶
Python
# Export to pandas for custom analysis
returns = results.daily_return
weights = results.weights
# Custom calculations
rolling_sharpe = returns.rolling(60).mean() / returns.rolling(60).std() * np.sqrt(252)
Parameter Optimization¶
Grid Search¶
Python
import pysigc
import pandas as pd
# Define parameter grid
lookbacks = [20, 40, 60, 80, 100]
top_pcts = [0.1, 0.2, 0.3]
results_list = []
for lookback in lookbacks:
for top_pct in top_pcts:
result = pysigc.run(
"strategy.sig",
params={"lookback": lookback, "top_pct": top_pct}
)
results_list.append({
"lookback": lookback,
"top_pct": top_pct,
"sharpe": result.sharpe_ratio,
"return": result.total_return,
"drawdown": result.max_drawdown
})
df = pd.DataFrame(results_list)
print(df.sort_values("sharpe", ascending=False))
Parallel Optimization¶
Python
from concurrent.futures import ProcessPoolExecutor
import pysigc
def run_with_params(params):
return pysigc.run("strategy.sig", params=params)
param_sets = [
{"lookback": 20, "top_pct": 0.2},
{"lookback": 40, "top_pct": 0.2},
{"lookback": 60, "top_pct": 0.2},
# ...
]
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(run_with_params, param_sets))
Data Integration¶
Pandas DataFrame¶
Python
import pandas as pd
import pysigc
# Load your data
prices = pd.read_csv("prices.csv", parse_dates=["date"])
# Run strategy with data
results = pysigc.run(
"strategy.sig",
data={"prices": prices}
)
From Database¶
Python
import pandas as pd
import pysigc
from sqlalchemy import create_engine
# Load from database
engine = create_engine("postgresql://localhost/marketdb")
prices = pd.read_sql(
"SELECT date, ticker, close FROM daily_prices",
engine
)
# Run strategy
results = pysigc.run("strategy.sig", data={"prices": prices})
Real-Time Data¶
Python
import pysigc
# Connect to live data
client = pysigc.LiveClient()
# Subscribe to updates
@client.on_bar
def on_new_bar(bar):
# Recompute signals
signals = pysigc.compute_signal("momentum", data=bar)
print(f"New signal: {signals}")
client.subscribe(["AAPL", "MSFT", "GOOGL"])
client.run()
Integration with ML¶
Feature Engineering¶
Python
import pysigc
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
# Get signal values as features
results = pysigc.run("feature_signals.sig")
signals = results.signals
# Combine signals into feature matrix
features = pd.merge(
signals["momentum"],
signals["value"],
on=["date", "ticker"],
suffixes=["_mom", "_val"]
)
# Add target (future returns)
features["target"] = features.groupby("ticker")["close"].pct_change(5).shift(-5) > 0
# Train model
X = features[["momentum", "value"]]
y = features["target"]
model = RandomForestClassifier().fit(X, y)
Using Predictions¶
Python
# Generate predictions
features["ml_signal"] = model.predict_proba(X)[:, 1]
# Use in sigc strategy
strategy = """
signal ml_alpha:
emit ml_predictions
portfolio main:
weights = rank(ml_alpha).long_short(top=0.2, bottom=0.2)
"""
results = pysigc.run_string(
strategy,
data={"ml_predictions": features[["date", "ticker", "ml_signal"]]}
)
API Reference¶
pysigc.run()¶
Python
pysigc.run(
file: str, # Strategy file path
params: dict = None, # Parameter overrides
data: dict = None, # Custom data
config: dict = None, # Runtime config
output: str = None # Output format
) -> Results
pysigc.run_string()¶
Python
pysigc.run_string(
strategy: str, # Strategy code
params: dict = None,
data: dict = None,
config: dict = None
) -> Results
pysigc.compile()¶
Python
# Just compile (no run)
compiled = pysigc.compile("strategy.sig")
print(compiled.signals) # List of signals
print(compiled.portfolios) # List of portfolios
pysigc.validate()¶
Python
# Validate without running
errors = pysigc.validate("strategy.sig")
if errors:
for e in errors:
print(f"{e.line}: {e.message}")
Error Handling¶
Python
import pysigc
from pysigc.errors import (
ParseError,
DataError,
ComputeError,
ConfigError
)
try:
results = pysigc.run("strategy.sig")
except ParseError as e:
print(f"Syntax error at line {e.line}: {e.message}")
except DataError as e:
print(f"Data error: {e}")
except ComputeError as e:
print(f"Computation error: {e}")
except ConfigError as e:
print(f"Configuration error: {e}")
Performance Tips¶
1. Reuse Compiled Strategies¶
Python
# Compile once
compiled = pysigc.compile("strategy.sig")
# Run multiple times with different params
for params in param_sets:
results = compiled.run(params=params)
2. Use Parquet Data¶
3. Limit Date Range¶
Python
results = pysigc.run(
"strategy.sig",
config={"start_date": "2023-01-01", "end_date": "2024-01-01"}
)
Best Practices¶
1. Version Your Strategies¶
2. Use Type Hints¶
Python
from pysigc import Results
def analyze_results(results: Results) -> dict:
return {
"sharpe": results.sharpe_ratio,
"return": results.total_return
}