A python framework that can be used to create, test and deploy trading algorithms.
Project description
Dijkies
Dijkies is a Python framework for creating, testing, and deploying algorithmic trading strategies in a clean, modular, and exchange-agnostic way.
The core idea behind Dijkies is to separate trading logic from execution and infrastructure, allowing the same strategy code to be reused for:
- Historical backtesting
- Paper trading
- Live trading
Philosophy
In Dijkies, a strategy is responsible only for making decisions — when to buy, when to sell, and how much. Everything else, such as order execution, fee calculation, balance management, and exchange communication, is handled by dedicated components.
This separation ensures that strategies remain:
- Easy to reason about
- Easy to test
- Easy to reuse across environments
A strategy written once can be backtested on historical data and later deployed to a real exchange without modification.
How It Works
At a high level, Dijkies operates as follows:
- Market data (candles) is fetched from an exchange or data provider
- A rolling window of historical data is passed to a strategy
- The strategy analyzes the data and generates buy/sell signals
- Orders are placed through a standardized execution interface
- Account state is updated accordingly
- Results are collected (during backtesting) or executed live
Key Design Principles
-
Strategy–Executor separation Trading logic is completely decoupled from execution logic.
-
Single interface for backtesting and live trading Switching between backtesting and live trading requires no strategy changes.
-
Explicit state management All balances and positions are tracked in a transparent
Stateobject. -
Minimal assumptions Dijkies does not enforce indicators, timeframes, or asset types.
-
Composable and extensible New exchanges, execution models, and risk layers can be added easily.
Who Is This For?
Dijkies is designed for:
- Developers building algorithmic trading systems
- Quantitative traders who want full control over strategy logic
- Anyone who wants to move from backtesting to production without rewriting code
What Dijkies Is Not
- A no-code trading bot
- A black-box strategy optimizer
- A fully managed trading platform
Dijkies provides the building blocks, not the trading edge.
Quick Start
This quick start shows how to define a strategy, fetch market data, and run a backtest in just a few steps.
1. Define a Strategy
A strategy is a class that inherits from Strategy and implements the execute method.
It receives a rolling dataframe of candles and decides when to place orders.
# create strategy
from dijkies.executors import (
ExchangeAssetClient,
BacktestExchangeAssetClient,
State
)
from dijkies.strategy import Strategy
from ta.momentum import RSIIndicator
from pandas.core.frame import DataFrame as PandasDataFrame
from dijkies.data_pipeline import DataPipeline, NoDataPipeline
class RSIStrategy(Strategy):
analysis_dataframe_size_in_minutes = 60*24*30
def __init__(
self,
executor: ExchangeAssetClient,
lower_threshold: float,
higher_threshold: float,
) -> None:
self.lower_threshold = lower_threshold
self.higher_threshold = higher_threshold
super().__init__(executor)
def execute(self, candle_df: PandasDataFrame) -> None:
candle_df["momentum_rsi"] = RSIIndicator(candle_df.close).rsi()
previous_candle = candle_df.iloc[-2]
current_candle = candle_df.iloc[-1]
is_buy_signal = (
previous_candle.momentum_rsi > self.lower_threshold
and current_candle.momentum_rsi < self.lower_threshold
)
if is_buy_signal:
self.executor.place_market_buy_order(
self.state.base,
self.state.quote_available,
)
is_sell_signal = (
previous_candle.momentum_rsi < self.higher_threshold
and current_candle.momentum_rsi > self.higher_threshold
)
if is_sell_signal:
self.executor.place_market_sell_order(
self.state.base,
self.state.base_available,
)
def get_data_pipeline(self) -> DataPipeline:
"""
Implement this metho
"""
return NoDataPipeline()
2. fetch data for your backtest
Market data is provided as a pandas DataFrame containing OHLCV candles.
from dijkies.exchange_market_api import BitvavoMarketAPI
bitvavo_market_api = BitvavoMarketAPI()
candle_df = bitvavo_market_api.get_candles()
3. Set Up State and BacktestingExecutor
Market data is provided as a pandas DataFrame containing OHLCV candles.
from dijkies.executors import BacktestExchangeAssetClient, State
state = State(
base="XRP",
total_base=0,
total_quote=1000,
)
executor = BacktestExchangeAssetClient(
state=state,
fee_limit_order=0.0015,
fee_market_order=0.0025,
)
4. Run the Backtest
Use the Backtester to run the strategy over historical data.
from dijkies.backtest import Backtester
strategy = RSIStrategy(
executor=executor,
lower_threshold=35,
higher_threshold=65,
)
results = strategy.backtest(
candle_df=candle_df,
)
results.total_value_strategy.plot()
results.total_value_hodl.plot()
Deployment & Live Trading
Dijkies supports deploying strategies to live trading environments using the same strategy code that is used for backtesting. Deployment is built around a small set of composable components that handle persistence, credentials, execution switching, and bot lifecycle management.
At a high level, deployment works by:
- Persisting a configured strategy
- Attaching a live exchange executor
- Running the strategy via a
Bot - Managing lifecycle states such as active, paused, and stopped
Core Deployment Concepts
Strategy Persistence
Strategies are serialized and stored so they can be resumed, paused, or stopped without losing state.
This includes:
- Strategy parameters
- Internal indicators or buffers
- Account state (balances, open orders, etc.)
Persistence is handled through a StrategyRepository.
Strategy Status
Each deployed strategy (bot) exists in one of the following states:
- active — strategy is running normally
- paused — strategy execution stopped due to an error
- stopped — strategy has been intentionally stopped
Status transitions are managed automatically by the deployment system.
Executor Switching
One of Dijkies’ key design goals is that strategies do not know whether they are backtesting or live trading.
At deployment time, the executor is injected dynamically:
BacktestExchangeAssetClientfor backtestingBitvavoExchangeAssetClientfor live trading
No strategy code changes are required.
Strategy Repository
The StrategyRepository abstraction defines how strategies are stored and retrieved.
class StrategyRepository(ABC):
def store(...)
def read(...)
def change_status(...)
LocalStrategyRepository
The provided implementation stores strategies locally using pickle.
Directory Structure
root/ └── person_id/ └── exchange/ └── status/ └── bot_id.pkl
from pathlib import Path
from dijkies.bot import LocalStrategyRepository
repo = LocalStrategyRepository(Path("./strategies"))
# read
strategy = repo.read(
person_id="ArnoldDijk",
exchange="bitvavo",
bot_id="rsi_bot",
status="active"
)
# store
repo.store(
strategy=strategy,
person_id="ArnoldDijk",
exchange="bitvavo",
bot_id="berend_botje",
status="active"
)
# change status
repo.change_status(
person_id="ArnoldDijk",
exchange="bitvavo",
bot_id="berend_botje",
from_status="active",
to_status="stopped",
)
This makes it easy to:
- Resume bots after restarts
- Inspect stored strategies
- Build higher-level orchestration around the filesystem
Credentials Management
Live trading requires exchange credentials. These are abstracted behind a CredentialsRepository.
class CredentialsRepository(ABC):
def get_api_key(...)
def get_api_secret_key(...)
The local implementation retrieves credentials from environment variables:
export alice_bitvavo_api_key="..."
export alice_bitvavo_api_secret_key="..."
import LocalCredentialsRepository
credentials_repository = LocalCredentialsRepository()
bitvavo_api_key = credentials_repository.get_api_key(
person_id="alice",
exchange="bitvavo"
)
This keeps secrets out of source code and allows standard deployment practices (Docker, CI/CD, etc.).
The Bot
The Bot class is the runtime orchestrator responsible for:
- Loading a stored strategy
- Injecting the correct executor
- Running or stopping the strategy
- Handling failures and state transitions
running the bot
bot.run(
person_id="alice",
exchange="bitvavo",
bot_id="rsi-xrp",
status="active",
)
What happens internally:
- The state of the strategy is loaded from the repository
- The executor is replaced with a live exchange client
- The strategy’s data pipeline is executed
- strategy.run() is called
- The new state of the strategy is persisted
If an exception occurs:
- The strategy is stored
- The bot is automatically moved to paused
Stopping a Bot
Bots can be stopped gracefully using the stop method.
bot.stop(
person_id="alice",
exchange="bitvavo",
bot_id="rsi-xrp",
status="active",
asset_handling="quote_only",
)
Asset Handling Options
When stopping a bot, you must specify how assets should be handled:
quote_only
Sell all base assets and remain in quote currency
base_only
Buy base assets using all available quote currency
ignore
Leave balances unchanged
Before stopping, the bot:
- Cancels all open orders
- Handles assets according to the selected mode
- Persists the final state
- Moves the bot to stopped
If anything fails, the bot is moved to paused.
Deployment Quickstart
In this example, we will use the earlier defined rsi strategy.
Step 1: Create and Backtest a Strategy
from dijkies.executors import BacktestExchangeAssetClient, State
from dijkies.backtest import Backtester
state = State(
base="XRP",
total_base=0,
total_quote=1000,
)
executor = BacktestExchangeAssetClient(
state=state,
fee_market_order=0.0025,
fee_limit_order=0.0015,
)
strategy = RSIStrategy(
executor=executor,
lower_threshold=35,
higher_threshold=65,
)
results = strategy.backtest(candle_df)
analyse the results and decide if you want to use this strategy.
Step 2: Prepare the Strategy for Deployment
After backtesting, the same strategy instance can be deployed live.
Create a Strategy Repository
from pathlib import Path
from dijkies.bot import LocalStrategyRepository
strategy_repository = LocalStrategyRepository(
root_directory=Path("./strategies")
)
Store the strategy
strategy_repository.store(
strategy=strategy,
person_id="alice",
exchange="bitvavo",
bot_id="rsi-xrp",
status="active",
)
This serializes the strategy and its state so it can be resumed later.
Step 3: Configure Exchange Credentials
Set your exchange credentials as environment variables:
export alice_bitvavo_api_key="your_api_key"
export alice_bitvavo_api_secret_key="your_api_secret"
Step 4: Create the Bot Runtime
The Bot orchestrates loading, execution, and lifecycle management.
from dijkies.bot import Bot, LocalCredentialsRepository
credentials_repository = LocalCredentialsRepository()
bot = Bot(
strategy_repository=strategy_repository,
credential_repository=credentials_repository,
)
Step 5: Run the Strategy Live
start the live trading bot
bot.run(
person_id="alice",
exchange="bitvavo",
bot_id="rsi-xrp",
status="active",
)
What Happens Under the Hood:
- The strategy is loaded from disk
- The backtest executor is replaced with BitvavoExchangeAssetClient where API credentials are injected
- The strategy’s data pipeline fetches live market data
- strategy.run() executes decision logic. Here, orders are executed on the exchange and state is modified accordingly
- strategy is persisted, executor and credentials not included.
If an exception occurs, the bot is automatically moved to paused.
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 dijkies-0.1.3.tar.gz.
File metadata
- Download URL: dijkies-0.1.3.tar.gz
- Upload date:
- Size: 14.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cff6dc9413ab7058a6b853f4c87f808e3732ffd32379e1e5df6bfaea987964b
|
|
| MD5 |
18a89e5f045c1bcb6813f7e836f2299d
|
|
| BLAKE2b-256 |
7defca8829feb0578df6067ea81e20f8ce28cfa6ef9722e3e5bc5a01a0b44e04
|
File details
Details for the file dijkies-0.1.3-py3-none-any.whl.
File metadata
- Download URL: dijkies-0.1.3-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b18cfcf6f51edd334eea041df881e634dab7fb634d6c53b8d0814ec00a3f5be8
|
|
| MD5 |
b80e16d6b607924bacc8780ffd30127f
|
|
| BLAKE2b-256 |
beb55bb61e8654e81169afe321a55521698e973df0d2f2217ae7543c37e91653
|