Magik Analysis
Overview
Magik Analysis is a stock and crypto market analysis tool which enables running complex trading strategies over historical datasets.
Technologies Used
- AlphaVantage: API used for fetching and caching historical data
- Python: core language for analysis engine
Description
Magik Analysis aims to simplify stock and crypto analysis by abstracting the strategy design component of backtesting. Users are able to create unique trading strategies using either provided indicators or by implementing custom indicators, which can be used as part of a trading strategy. Strategies are defined using JSON, parsed, and fed through a logic engine that asserts whether the provided criteria were triggered and keeps track of the performance of the strategy over historical datasets. Such datasets can be provided locally or fetched from the AlphaVantage API.
Trading strategies in MAGE are defined using JSON configuration files. This declarative approach allows you to build complex conditional trading logic without writing code.
Structure
Basic Template
{
"name": "Strategy Name",
"description": "Strategy description",
"dataSpecifications": [...],
"signals": [...],
"actions": [...]
}
Top-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | ✓ | Strategy identifier used in reports and output files |
description |
string | ✓ | Human-readable explanation of the strategy logic |
dataSpecifications |
array | ✓ | Define symbols, data sources, and indicators |
signals |
array | Reusable boolean conditions that can be referenced in actions | |
actions |
array | ✓ | Trading instructions (buy/sell) with trigger criteria |
Data Specifications
Defines the market data and technical indicators required for your strategy.
{
"symbol": "6B.FUT",
"source": "LocalFiles",
"marketType": "FUTURE",
"timeSeries": "1h",
"indicators": [...]
}
Fields
| Field | Options | Description |
|---|---|---|
symbol |
string | Ticker symbol or $1 as placeholder |
source |
LocalFiles, AlphaVantage |
Data provider |
marketType |
FUTURE, SPOT, CRYPTO, EQUITY |
Asset classification |
timeSeries |
1h, DAILY, etc. |
Candle time resolution |
indicators |
array | Technical indicators to compute |
Indicators
Each indicator calculates a technical value that can be referenced in your strategy logic.
{
"name": "rsi",
"identifier": "RSI_14",
"config": {
"real": "close",
"timeperiod": 14
}
}
| Field | Description |
|---|---|
name |
Indicator function: rsi, sma, delta, sbh, var_change_pct |
identifier |
Variable name used to reference this indicator in criteria |
config |
Indicator-specific parameters |
Common Indicators
RSI - Relative Strength Index
{
"name": "rsi",
"identifier": "RSI",
"config": {
"real": "close",
"timeperiod": 14
}
}
SMA - Simple Moving Average
{
"name": "sma",
"identifier": "SMA_50",
"config": {
"real": "close",
"timeperiod": 50
}
}
Delta - Change between two points
{
"name": "delta",
"identifier": "DELTA_RSI",
"config": {
"indicator": "RSI",
"d1": 0,
"d2": -6
}
}
SBH - Session-Based High/Low
{
"name": "sbh",
"identifier": "SBH",
"config": {
"pre_session": [0, 5],
"session_a": [6, 12],
"session_b": [13, 20]
}
}
Signals
Optional reusable conditions that act as boolean flags. Once triggered, they remain active until reset.
{
"identifier": "BULLISH_SIGNAL",
"criteria": {
"var1": {
"symbol": "6B.FUT",
"var": "RSI",
"offset": 0
},
"op": "lt",
"var2": {
"symbol": null,
"var": 30,
"offset": 0
}
}
}
| Field | Description |
|---|---|
identifier |
Signal name to reference in actions |
criteria |
Logical condition that activates the signal |
Actions
Define when and how to execute trades.
{
"action": {
"do": "MARKET_BUY"
},
"symbol": "6B.FUT",
"size": {
"size": 10,
"type": "STANDARD"
},
"criteria": {...},
"followUpActions": [...]
}
Action Types
| Type | Description |
|---|---|
MARKET_BUY |
Open or add to a long position |
MARKET_SELL |
Close long position or open short |
SIGNAL_RESET |
Reset a signal flag to inactive |
Size Configuration
| Field | Values | Description |
|---|---|---|
size |
number | Quantity or percentage |
type |
STANDARD, PERCENT |
Fixed units or % of position (1.0 = 100%) |
transform |
object | Optional dynamic sizing function |
Transform Example
"size": {
"size": 10,
"type": "STANDARD",
"transform": {
"method": "rsi_inverse_range",
"configuration": {
"symbol": "6B.FUT",
"variables": ["RSI"],
"rsiRange": [30, 70]
}
}
}
Criteria Logic
Criteria define conditional logic using comparison operators and AND/OR chains.
Structure
{
"var1": {
"symbol": "6B.FUT",
"var": "close",
"offset": 0
},
"op": "gt",
"var2": {
"symbol": "6B.FUT",
"var": "SMA_50",
"offset": 0
},
"and": [...],
"or": [...]
}
Variable Object
| Field | Description |
|---|---|
symbol |
Symbol to reference, or null for global variables |
var |
Variable name (see Variable Reference below) |
offset |
Lookback period: 0 = current, -1 = previous bar, -6 = 6 bars ago |
Comparison Operators
| Operator | Meaning |
|---|---|
eq |
Equal to |
gt |
Greater than |
lt |
Less than |
gteq |
Greater than or equal to |
lteq |
Less than or equal to |
Logical Operators
and: Array of criteria - ALL must be trueor: Array of criteria - ANY can be true
Example: Complex Criteria
{
"var1": {"symbol": "6B.FUT", "var": "RSI", "offset": 0},
"op": "lt",
"var2": {"symbol": null, "var": 30, "offset": 0},
"and": [
{
"var1": {"symbol": "6B.FUT", "var": "close", "offset": 0},
"op": "gt",
"var2": {"symbol": "6B.FUT", "var": "SMA_50", "offset": 0}
},
{
"var1": {"symbol": "6B.FUT", "var": "position", "offset": 0},
"op": "eq",
"var2": {"symbol": null, "var": false, "offset": 0}
}
]
}
This reads as: “RSI is below 30 AND close is above SMA_50 AND no position is open”
Variable Reference
Market Data
open,close,high,low,volume
Timestamps
timestamp.hour- Hour of day (0-23)timestamp.day- Day of weektimestamp.minute- Minute
Indicators
Use the identifier defined in your data specifications:
RSI,SMA_50,DELTA_RSI, etc.
Position Data
position- Boolean, true if position is openposition.quantity- Current position sizeposition.pnl- Unrealized P&L
Signals
Reference signal identifier names directly:
BULLISH_SIGNAL,TREND_ACTIVE, etc.
Portfolio
portfolio- Portfolio object with all positions
Complete Example
{
"name": "RSI Oversold Long",
"description": "Buy when RSI drops below 30 and price is above 50-day SMA",
"dataSpecifications": [
{
"symbol": "6B.FUT",
"source": "LocalFiles",
"marketType": "FUTURE",
"timeSeries": "1h",
"indicators": [
{
"name": "rsi",
"identifier": "RSI",
"config": {"real": "close", "timeperiod": 14}
},
{
"name": "sma",
"identifier": "SMA_50",
"config": {"real": "close", "timeperiod": 50}
}
]
}
],
"signals": [
{
"identifier": "OVERSOLD",
"criteria": {
"var1": {"symbol": "6B.FUT", "var": "RSI", "offset": 0},
"op": "lt",
"var2": {"symbol": null, "var": 30, "offset": 0}
}
}
],
"actions": [
{
"action": {"do": "MARKET_BUY"},
"symbol": "6B.FUT",
"size": {"size": 10, "type": "STANDARD"},
"criteria": {
"var1": {"symbol": null, "var": "OVERSOLD", "offset": 0},
"op": "eq",
"var2": {"symbol": null, "var": true, "offset": 0},
"and": [
{
"var1": {"symbol": "6B.FUT", "var": "close", "offset": 0},
"op": "gt",
"var2": {"symbol": "6B.FUT", "var": "SMA_50", "offset": 0}
},
{
"var1": {"symbol": "6B.FUT", "var": "position", "offset": 0},
"op": "eq",
"var2": {"symbol": null, "var": false, "offset": 0}
}
]
},
"followUpActions": [
{
"action": {"do": "SIGNAL_RESET", "signal": "OVERSOLD"}
}
]
},
{
"action": {"do": "MARKET_SELL"},
"symbol": "6B.FUT",
"size": {"size": 1.0, "type": "PERCENT"},
"criteria": {
"var1": {"symbol": "6B.FUT", "var": "RSI", "offset": 0},
"op": "gt",
"var2": {"symbol": null, "var": 70, "offset": 0}
}
}
]
}
Key Features
- Backtesting of complex trading strategies
- Caching of historical candle datasets
- Generation of reports, including strategy trades and performance
- Complex logic engine for handling strategies
What I Learned
I have worked with market data before, so this project was really about taking the knowledge I had already built on other projects and rolling it into this idea. That being said, I did explore some public Python libraries for trading indicators and used the AlphaVantage API for the first time. This was also the first time I had worked with futures data, so I learned about some of the complexities involved in contract rolling and had to implement a data aggregator to roll all the data into a single set.
Daniel Anderson