Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experiment multiple algorithms support #252

Merged
merged 4 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 64 additions & 96 deletions README.md

Large diffs are not rendered by default.

File renamed without changes.
5 changes: 5 additions & 0 deletions examples/backtest/algorithm/algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from investing_algorithm_framework import Algorithm
from .strategy import CrossOverStrategy

algorithm = Algorithm()
algorithm.add_strategy(CrossOverStrategy)
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
https://tulipindicators.org/ or go directly to the pypi page:
https://pypi.org/project/tulipy/
"""
# Define market data sources

def is_below_trend(fast_series, slow_series):
return fast_series[-1] < slow_series[-1]

Expand Down Expand Up @@ -55,6 +53,9 @@ class CrossOverStrategy(TradingStrategy):
"DOT/EUR-ticker"
]
symbols = ["BTC/EUR", "DOT/EUR"]
fast = 9
slow = 50
trend = 100

def apply_strategy(self, algorithm: Algorithm, market_data):

Expand All @@ -72,8 +73,8 @@ def apply_strategy(self, algorithm: Algorithm, market_data):
price = ticker_data['bid']

if not algorithm.has_position(target_symbol) \
and is_crossover(fast, slow)\
and not is_above_trend(fast, trend):
and is_crossover(fast, slow) \
and is_above_trend(fast, trend):
algorithm.create_limit_order(
target_symbol=target_symbol,
order_side=OrderSide.BUY,
Expand All @@ -84,6 +85,7 @@ def apply_strategy(self, algorithm: Algorithm, market_data):

if algorithm.has_position(target_symbol) \
and is_below_trend(fast, slow):

open_trades = algorithm.get_open_trades(
target_symbol=target_symbol
)
Expand Down
7 changes: 7 additions & 0 deletions examples/backtest/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import pathlib

from investing_algorithm_framework import create_app, RESOURCE_DIRECTORY

app = create_app(
config={RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()}
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
pretty_print_backtest

from app import app
from algorithm.algorithm import algorithm
from algorithm.data_sources import bitvavo_btc_eur_ohlcv_2h, \
bitvavo_dot_eur_ohlcv_2h, bitvavo_dot_eur_ticker, bitvavo_btc_eur_ticker


app.add_algorithm(algorithm)
app.add_market_data_source(bitvavo_btc_eur_ohlcv_2h)
app.add_market_data_source(bitvavo_dot_eur_ohlcv_2h)
app.add_market_data_source(bitvavo_btc_eur_ticker)
app.add_market_data_source(bitvavo_dot_eur_ticker)


# Add a portfolio configuration of 400 euro initial balance
Expand All @@ -18,10 +28,10 @@
if __name__ == "__main__":
end_date = datetime(2023, 12, 2)
start_date = end_date - timedelta(days=100)
experiment_report, backtest_reports = app.experiment(
backtest_report = app.run_backtest(
algorithm=algorithm,
start_date=start_date,
end_date=end_date,
pending_order_check_interval="2h",
strategies=[]
)
pretty_print_expirement(expirement_report)
pretty_print_backtest(backtest_report)
Empty file.
4 changes: 4 additions & 0 deletions examples/backtest_expirement/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .algorithm import create_algorithm


__all__ = ["create_algorithm"]
97 changes: 97 additions & 0 deletions examples/backtest_expirement/algorithms/algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from investing_algorithm_framework import Algorithm, TradingStrategy, \
TimeUnit, OrderSide
import tulipy as ti

def is_below_trend(fast_series, slow_series):
return fast_series[-1] < slow_series[-1]


def is_above_trend(fast_series, slow_series):
return fast_series[-1] > slow_series[-1]


def is_crossover(fast, slow):
"""
Expect df to have columns: Date, ma_<period_one>, ma_<period_two>.
With the given date time it will check if the ma_<period_one> is a
crossover with the ma_<period_two>
"""
return fast[-2] <= slow[-2] and fast[-1] > slow[-1]


def is_crossunder(fast, slow):
"""
Expect df to have columns: Date, ma_<period_one>, ma_<period_two>.
With the given date time it will check if the ma_<period_one> is a
crossover with the ma_<period_two>
"""
return fast[-2] >= slow[-2] and fast[-1] < slow[-1]


class Strategy(TradingStrategy):
time_unit = TimeUnit.HOUR
interval = 2
market_data_sources = [
"BTC/EUR-ohlcv",
"DOT/EUR-ohlcv",
"BTC/EUR-ticker",
"DOT/EUR-ticker"
]
symbols = ["BTC/EUR", "DOT/EUR"]

def __init__(self, fast, slow, trend):
self.fast = fast
self.slow = slow
self.trend = trend
super().__init__()

def apply_strategy(self, algorithm: Algorithm, market_data):

for symbol in self.symbols:
target_symbol = symbol.split('/')[0]

if algorithm.has_open_orders(target_symbol):
continue

df = market_data[f"{symbol}-ohlcv"]
ticker_data = market_data[f"{symbol}-ticker"]
fast = ti.sma(df['Close'].to_numpy(), self.fast)
slow = ti.sma(df['Close'].to_numpy(), self.slow)
trend = ti.sma(df['Close'].to_numpy(), self.trend)
price = ticker_data['bid']

if not algorithm.has_position(target_symbol) \
and is_crossover(fast, slow) \
and is_above_trend(fast, trend):
algorithm.create_limit_order(
target_symbol=target_symbol,
order_side=OrderSide.BUY,
price=price,
percentage_of_portfolio=25,
precision=4,
)

if algorithm.has_position(target_symbol) \
and is_below_trend(fast, slow):

open_trades = algorithm.get_open_trades(
target_symbol=target_symbol
)

for trade in open_trades:
algorithm.close_trade(trade)


def create_algorithm(
name,
description,
fast,
slow,
trend
) -> Algorithm:
algorithm = Algorithm(
name=name,
description=description
)
algorithm.add_strategy(Strategy(fast, slow, trend))
return algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
from data_sources import bitvavo_btc_eur_ohlcv_2h, bitvavo_dot_eur_ohlcv_2h, \
bitvavo_dot_eur_ticker, bitvavo_btc_eur_ticker
from investing_algorithm_framework import create_app, RESOURCE_DIRECTORY
from strategy import CrossOverStrategy

app = create_app(
config={RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()}
)
app.add_strategy(CrossOverStrategy)
app.add_market_data_source(bitvavo_btc_eur_ohlcv_2h)
app.add_market_data_source(bitvavo_dot_eur_ohlcv_2h)
app.add_market_data_source(bitvavo_btc_eur_ticker)
Expand Down
162 changes: 162 additions & 0 deletions examples/backtest_expirement/backtest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
from datetime import datetime, timedelta

from algorithms import create_algorithm
from app import app
from investing_algorithm_framework import PortfolioConfiguration, \
pretty_print_backtest_reports_evaluation, BacktestReportsEvaluation, \
load_backtest_reports


if __name__ == "__main__":
end_date = datetime(2023, 12, 2)
start_date = end_date - timedelta(days=100)
# Add a portfolio configuration of 400 euro initial balance
app.add_portfolio_configuration(
PortfolioConfiguration(
market="BINANCE",
trading_symbol="EUR",
initial_balance=400,
)
)

# Run the backtest for each algorithm
reports = app.run_backtests(
algorithms=[
create_algorithm(
name="9-50-100",
description="9-50-100",
fast=9,
slow=50,
trend=100
),
create_algorithm(
name="10-50-100",
description="10-50-100",
fast=10,
slow=50,
trend=100
),
create_algorithm(
name="11-50-100",
description="11-50-100",
fast=11,
slow=50,
trend=100
),
create_algorithm(
name="9-75-150",
description="9-75-150",
fast=9,
slow=75,
trend=150
),
create_algorithm(
name="10-75-150",
description="10-75-150",
fast=10,
slow=75,
trend=150
),
create_algorithm(
name="11-75-150",
description="11-75-150",
fast=11,
slow=75,
trend=150
),
create_algorithm(
name="20-75-150",
description="20-75-150",
fast=20,
slow=75,
trend=150
),
create_algorithm(
name="21-75-150",
description="21-75-150",
fast=21,
slow=75,
trend=150
),
create_algorithm(
name="22-75-150",
description="22-75-150",
fast=22,
slow=75,
trend=150
),
create_algorithm(
name="23-75-150",
description="23-75-150",
fast=23,
slow=75,
trend=150
),
create_algorithm(
name="24-75-150",
description="24-75-150",
fast=24,
slow=75,
trend=150
),
create_algorithm(
name="25-75-150",
description="25-75-150",
fast=25,
slow=75,
trend=150
),
create_algorithm(
name="20-75-200",
description="20-75-200",
fast=20,
slow=75,
trend=200
),
create_algorithm(
name="21-75-200",
description="24-75-200",
fast=24,
slow=75,
trend=200
),
create_algorithm(
name="22-75-200",
description="24-75-200",
fast=24,
slow=75,
trend=200
),
create_algorithm(
name="23-75-200",
description="24-75-200",
fast=24,
slow=75,
trend=200
),
create_algorithm(
name="24-75-200",
description="24-75-200",
fast=24,
slow=75,
trend=200
),
create_algorithm(
name="25-75-150",
description="25-75-200",
fast=25,
slow=75,
trend=200
),
],
start_date=start_date,
end_date=end_date,
pending_order_check_interval="2h",
)
evaluation = BacktestReportsEvaluation(reports)
pretty_print_backtest_reports_evaluation(evaluation)
reports = load_backtest_reports(
"backtest_reports"
)
evaluation = BacktestReportsEvaluation(reports)
pretty_print_backtest_reports_evaluation(evaluation)
Loading
Loading