Skip to content

Commit 4a1c579

Browse files
committed
Add symbols specification
1 parent 12b2d18 commit 4a1c579

File tree

14 files changed

+214
-68
lines changed

14 files changed

+214
-68
lines changed

.gitignore

+3-2
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,6 @@ lib/
145145
bumpversion.egg-info/
146146
*.sqlite3
147147

148-
*/backtest_data/
149-
*/backtest_reports/
148+
**/backtest_data/*
149+
*/backtest_reports/
150+
**/backtest_reports/*

README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ It also exposes an REST API that allows you to interact with the algorithm.
3838
import pathlib
3939
from investing_algorithm_framework import create_app, PortfolioConfiguration, \
4040
RESOURCE_DIRECTORY, TimeUnit, CCXTOHLCVMarketDataSource, Algorithm, \
41-
CCXTTickerMarketDataSource, MarketCredential
41+
CCXTTickerMarketDataSource, MarketCredential, SYMBOLS
42+
43+
# Define resource directory and the symbols you want to trade
44+
config = {
45+
RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()
46+
SYMBOLS: ["BTC/EUR"]
47+
}
4248

4349
# Define market data sources
4450
bitvavo_btc_eur_ohlcv_2h = CCXTOHLCVMarketDataSource(
@@ -54,7 +60,7 @@ bitvavo_btc_eur_ticker = CCXTTickerMarketDataSource(
5460
market="BITVAVO",
5561
symbol="BTC/EUR",
5662
)
57-
app = create_app({RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()})
63+
app = create_app(config=config)
5864
algorithm = Algorithm()
5965

6066
app.add_market_data_source(bitvavo_btc_eur_ohlcv_2h)

examples/backtest/app.py

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
app = create_app(
66
config={RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()}
77
)
8+
9+
10+
if __name__ == "__main__":
11+
app.run()

examples/bitvavo_trading_bot/bitvavo.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import os
12
from investing_algorithm_framework import MarketCredential, TimeUnit, \
23
CCXTOHLCVMarketDataSource, CCXTTickerMarketDataSource, TradingStrategy, \
3-
create_app, PortfolioConfiguration, Algorithm
4+
create_app, PortfolioConfiguration, Algorithm, SYMBOLS, RESOURCE_DIRECTORY
45

56
"""
67
Bitvavo trading bot example with market data sources of bitvavo.
@@ -45,12 +46,18 @@ def apply_strategy(self, algorithm, market_data):
4546
print(market_data["BTC/EUR-ohlcv"])
4647
print(market_data["BTC/EUR-ticker"])
4748

49+
50+
config = {
51+
SYMBOLS: ["BTC/EUR"],
52+
RESOURCE_DIRECTORY: os.path.join(os.path.dirname(__file__), "resources")
53+
}
54+
4855
# Create an algorithm and link your trading strategy to it
4956
algorithm = Algorithm()
5057
algorithm.add_strategy(BitvavoTradingStrategy)
5158

5259
# Create an app and add the market data sources and market credentials to it
53-
app = create_app()
60+
app = create_app(config=config)
5461
app.add_market_credential(bitvavo_market_credential)
5562
app.add_market_data_source(bitvavo_btc_eur_ohlcv_2h)
5663
app.add_market_data_source(bitvavo_btc_eur_ticker)

examples/coinbase_trading_bot/coinbase.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import os
12
from investing_algorithm_framework import MarketCredential, TimeUnit, \
23
CCXTOHLCVMarketDataSource, CCXTTickerMarketDataSource, TradingStrategy, \
3-
create_app, PortfolioConfiguration, Algorithm
4+
create_app, PortfolioConfiguration, Algorithm, SYMBOLS, RESOURCE_DIRECTORY
45

56
"""
67
Coinbase market data sources example. Coinbase requires you to have an API key
@@ -42,11 +43,15 @@ class CoinBaseTradingStrategy(TradingStrategy):
4243
def apply_strategy(self, algorithm, market_data):
4344
pass
4445

46+
config = {
47+
SYMBOLS: ["BTC/EUR"],
48+
RESOURCE_DIRECTORY: os.path.join(os.path.dirname(__file__), "resources")
49+
}
4550

4651
algorithm = Algorithm()
4752
algorithm.add_strategy(CoinBaseTradingStrategy)
4853

49-
app = create_app()
54+
app = create_app(config=config)
5055
app.add_algorithm(algorithm)
5156
app.add_market_credential(coinbase_market_credential)
5257
app.add_market_data_source(coinbase_btc_eur_ohlcv_2h)
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import pathlib
22

3-
from investing_algorithm_framework import create_app, RESOURCE_DIRECTORY
3+
from investing_algorithm_framework import create_app, RESOURCE_DIRECTORY, \
4+
SYMBOLS
45

5-
app = create_app(
6-
config={RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()}
7-
)
6+
config = {
7+
SYMBOLS: ["BTC/EUR"],
8+
RESOURCE_DIRECTORY: pathlib.Path(__file__).parent.resolve()
9+
}
10+
app = create_app(config=config)
811

investing_algorithm_framework/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
OrderStatus, OrderSide, Config, TimeUnit, TimeInterval, Order, Portfolio, \
66
Position, TimeFrame, BACKTESTING_INDEX_DATETIME, MarketCredential, \
77
PortfolioConfiguration, RESOURCE_DIRECTORY, pretty_print_backtest, \
8-
Trade, OHLCVMarketDataSource, OrderBookMarketDataSource, \
8+
Trade, OHLCVMarketDataSource, OrderBookMarketDataSource, SYMBOLS, \
99
TickerMarketDataSource, MarketService, BacktestReportsEvaluation, \
1010
pretty_print_backtest_reports_evaluation, load_backtest_reports
1111
from investing_algorithm_framework.app import TradingStrategy, \
@@ -55,4 +55,5 @@
5555
"pretty_print_backtest_reports_evaluation",
5656
"BacktestReportsEvaluation",
5757
"load_backtest_reports",
58+
"SYMBOLS"
5859
]

investing_algorithm_framework/app/app.py

+1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ def _initialize_app_for_backtest(
248248
# Override the portfolio service with the backtest portfolio service
249249
self.container.portfolio_service.override(
250250
BacktestPortfolioService(
251+
configuration_service=self.container.configuration_service(),
251252
market_credential_service=self.container
252253
.market_credential_service(),
253254
market_service=self.container.market_service(),

investing_algorithm_framework/dependency_container.py

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class DependencyContainer(containers.DeclarativeContainer):
8585
)
8686
portfolio_service = providers.Factory(
8787
PortfolioService,
88+
configuration_service=configuration_service,
8889
market_credential_service=market_credential_service,
8990
market_service=market_service,
9091
position_repository=position_repository,

investing_algorithm_framework/domain/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
DATETIME_FORMAT, DATETIME_FORMAT_BACKTESTING, BACKTESTING_FLAG, \
1414
BACKTESTING_INDEX_DATETIME, BACKTESTING_START_DATE, CCXT_DATETIME_FORMAT, \
1515
BACKTEST_DATA_DIRECTORY_NAME, TICKER_DATA_TYPE, OHLCV_DATA_TYPE, \
16-
CURRENT_UTC_DATETIME, BACKTESTING_END_DATE, \
16+
CURRENT_UTC_DATETIME, BACKTESTING_END_DATE, SYMBOLS, \
1717
CCXT_DATETIME_FORMAT_WITH_TIMEZONE, \
1818
BACKTESTING_PENDING_ORDER_CHECK_INTERVAL
1919
from .singleton import Singleton
@@ -105,4 +105,5 @@
105105
"BacktestReportsEvaluation",
106106
"load_csv_into_dict",
107107
"load_backtest_reports",
108+
"SYMBOLS"
108109
]

investing_algorithm_framework/domain/config.py

+1-48
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class Config(dict):
7676
SQLITE_ENABLED = True
7777
SQLITE_INITIALIZED = False
7878
BACKTEST_DATA_DIRECTORY_NAME = "backtest_data"
79+
SYMBOLS = None
7980

8081
def __init__(self, resource_directory=None):
8182
super().__init__()
@@ -85,54 +86,6 @@ def __init__(self, resource_directory=None):
8586

8687
super().__init__(vars(self.__class__))
8788

88-
# def __setitem__(self, key, item):
89-
# self.__dict__[key] = item
90-
#
91-
# def __getitem__(self, key):
92-
# return self.__dict__[key]
93-
#
94-
# def __repr__(self):
95-
# return repr(self.__dict__)
96-
#
97-
# def __len__(self):
98-
# return len(self.__dict__)
99-
#
100-
# def __delitem__(self, key):
101-
# del self.__dict__[key]
102-
#
103-
# def clear(self):
104-
# return self.__dict__.clear()
105-
#
106-
# def copy(self):
107-
# return self.__dict__.copy()
108-
#
109-
# def has_key(self, k):
110-
# return k in self.__dict__
111-
#
112-
# def update(self, *args, **kwargs):
113-
# return self.__dict__.update(*args, **kwargs)
114-
#
115-
# def keys(self):
116-
# return self.__dict__.keys()
117-
#
118-
# def values(self):
119-
# return self.__dict__.values()
120-
#
121-
# def items(self):
122-
# return self.__dict__.items()
123-
#
124-
# def pop(self, *args):
125-
# return self.__dict__.pop(*args)
126-
#
127-
# def __cmp__(self, dict_):
128-
# return self.__cmp__(self.__dict__, dict_)
129-
#
130-
# def __contains__(self, item):
131-
# return item in self.__dict__
132-
#
133-
# def __iter__(self):
134-
# return iter(self.__dict__)
135-
13689
def __str__(self):
13790
field_strings = []
13891

investing_algorithm_framework/domain/constants.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
DATABASE_URL = 'DATABASE_URL'
1212
DEFAULT_DATABASE_NAME = "database"
1313

14+
SYMBOLS = "SYMBOLS"
1415
RESOURCE_DIRECTORY = "RESOURCE_DIRECTORY"
1516
BACKTEST_DATA_DIRECTORY_NAME = "BACKTEST_DATA_DIRECTORY_NAME"
1617
LOG_LEVEL = 'LOG_LEVEL'

investing_algorithm_framework/services/portfolio_service/portfolio_service.py

+22-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
from datetime import datetime
33

44
from investing_algorithm_framework.domain import OrderSide, OrderStatus, \
5-
OperationalException, MarketService, MarketCredentialService
5+
OperationalException, MarketService, MarketCredentialService, SYMBOLS
66
from investing_algorithm_framework.services.repository_service \
77
import RepositoryService
8+
from investing_algorithm_framework.services.configuration_service import \
9+
ConfigurationService
810

911
logger = logging.getLogger("investing_algorithm_framework")
1012

@@ -18,6 +20,7 @@ class PortfolioService(RepositoryService):
1820

1921
def __init__(
2022
self,
23+
configuration_service: ConfigurationService,
2124
market_service: MarketService,
2225
market_credential_service: MarketCredentialService,
2326
position_repository,
@@ -26,6 +29,7 @@ def __init__(
2629
portfolio_configuration_service,
2730
portfolio_snapshot_service,
2831
):
32+
self.configuration_service = configuration_service
2933
self.market_credential_service = market_credential_service
3034
self.market_service = market_service
3135
self.position_repository = position_repository
@@ -235,12 +239,24 @@ def sync_portfolio_orders(self, portfolio):
235239
portfolio_configuration = self.portfolio_configuration_service \
236240
.get(portfolio.identifier)
237241

238-
# Get all available symbols for the market and check if
239-
# there are orders
240-
available_symbols = self.market_service.get_symbols(
241-
market=portfolio.market
242-
)
242+
# Check if the symbols param in the configuration is set
243+
config = self.configuration_service.config
244+
245+
if SYMBOLS in config and config[SYMBOLS] is not None:
246+
available_symbols = config[SYMBOLS]
247+
248+
if not isinstance(available_symbols, list):
249+
raise OperationalException(
250+
"The symbols configuration should be a list of strings"
251+
)
252+
else:
253+
# if not, get all available symbols for the market and check if
254+
# there are orders
255+
available_symbols = self.market_service.get_symbols(
256+
market=portfolio.market
257+
)
243258

259+
# Check if there are orders for the available symbols
244260
for symbol in available_symbols:
245261
orders = self.market_service.get_orders(
246262
symbol=symbol,

0 commit comments

Comments
 (0)