-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add experiment multiple algorithms support (#252)
* Add experiment multiple algorithms support * Add experimentation functionality * Fix ohlcv data sources tests * Fix ohlcv data sources tests
- Loading branch information
Showing
145 changed files
with
10,901 additions
and
11,943 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .algorithm import create_algorithm | ||
|
||
|
||
__all__ = ["create_algorithm"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
File renamed without changes.
Oops, something went wrong.