investing-algorithm-framework 2.0__tar.gz → 2.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/PKG-INFO +4 -4
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/README.md +3 -3
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/algorithm.py +17 -3
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/services/market_service.py +1 -1
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +2 -2
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/order_service/order_service.py +21 -24
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/portfolio_service/portfolio_service.py +45 -2
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework.egg-info/PKG-INFO +5 -5
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework.egg-info/SOURCES.txt +0 -1
- investing_algorithm_framework-2.0/investing_algorithm_framework/services/portfolio_service.py +0 -207
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/AUTHORS.md +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/LICENSE +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/app.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/strategy.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/task.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/create_app.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/error_handler.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/responses.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/create_app.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/dependency_container.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/config.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/constants.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/data_structures.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/exceptions.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/backtest_profile.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/base_model.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/order.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/order_fee.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/position/position.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/trade.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/services/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/services/market_data_sources.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/singleton.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/strategy.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/backtesting.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/csv.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/random.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/backtest_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/configuration_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/portfolio_configuration_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/portfolio_service/__init__.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/portfolio_service/backtest_portfolio_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/portfolio_snapshot_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/position_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/repository_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework.egg-info/dependency_links.txt +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework.egg-info/requires.txt +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/investing_algorithm_framework.egg-info/top_level.txt +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/setup.cfg +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/setup.py +0 -0
- {investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/tests/test_create_app.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: investing_algorithm_framework
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: A framework for creating an investment algorithm
|
|
5
5
|
Home-page: https://github.com/coding-kitties/investing-algorithm-framework.git
|
|
6
6
|
Download-URL: https://github.com/coding-kitties/investing-algorithm-framework/archive/v0.1.1.tar.gz
|
|
@@ -259,9 +259,9 @@ The framework has by default support for [ccxt](https://github.com/ccxt/ccxt).
|
|
|
259
259
|
This should allow you to connect to a lot of brokers/exchanges.
|
|
260
260
|
|
|
261
261
|
```python
|
|
262
|
-
from investing_algorithm_framework import
|
|
263
|
-
MarketCredential
|
|
264
|
-
app =
|
|
262
|
+
from investing_algorithm_framework import PortfolioConfiguration, \
|
|
263
|
+
MarketCredential, create_app
|
|
264
|
+
app = create_app()
|
|
265
265
|
app.add_market_credential(
|
|
266
266
|
MarketCredential(
|
|
267
267
|
market="<your market>",
|
|
@@ -222,9 +222,9 @@ The framework has by default support for [ccxt](https://github.com/ccxt/ccxt).
|
|
|
222
222
|
This should allow you to connect to a lot of brokers/exchanges.
|
|
223
223
|
|
|
224
224
|
```python
|
|
225
|
-
from investing_algorithm_framework import
|
|
226
|
-
MarketCredential
|
|
227
|
-
app =
|
|
225
|
+
from investing_algorithm_framework import PortfolioConfiguration, \
|
|
226
|
+
MarketCredential, create_app
|
|
227
|
+
app = create_app()
|
|
228
228
|
app.add_market_credential(
|
|
229
229
|
MarketCredential(
|
|
230
230
|
market="<your market>",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import decimal
|
|
2
3
|
from typing import List
|
|
3
4
|
|
|
4
5
|
from investing_algorithm_framework.domain import OrderStatus, OrderFee, \
|
|
@@ -718,9 +719,22 @@ class Algorithm:
|
|
|
718
719
|
if order.get_trade_closed_at() is not None
|
|
719
720
|
]
|
|
720
721
|
|
|
721
|
-
def round_down(self, value,
|
|
722
|
-
|
|
723
|
-
|
|
722
|
+
def round_down(self, value, amount_of_decimals):
|
|
723
|
+
|
|
724
|
+
if self.count_decimals(value) <= amount_of_decimals:
|
|
725
|
+
return value
|
|
726
|
+
|
|
727
|
+
with decimal.localcontext() as ctx:
|
|
728
|
+
d = decimal.Decimal(value)
|
|
729
|
+
ctx.rounding = decimal.ROUND_DOWN
|
|
730
|
+
return float(round(d, amount_of_decimals))
|
|
731
|
+
|
|
732
|
+
def count_decimals(self, number):
|
|
733
|
+
decimal_str = str(number)
|
|
734
|
+
if '.' in decimal_str:
|
|
735
|
+
return len(decimal_str.split('.')[1])
|
|
736
|
+
else:
|
|
737
|
+
return 0
|
|
724
738
|
|
|
725
739
|
def get_open_trades(self, target_symbol=None):
|
|
726
740
|
portfolios = self.portfolio_service.get_all()
|
|
@@ -123,7 +123,7 @@ class MarketService(ABC):
|
|
|
123
123
|
return None
|
|
124
124
|
|
|
125
125
|
for market_data_credentials in self.market_credentials:
|
|
126
|
-
if market_data_credentials.market == market:
|
|
126
|
+
if market_data_credentials.market.lower() == market.lower():
|
|
127
127
|
return market_data_credentials
|
|
128
128
|
|
|
129
129
|
return None
|
|
@@ -405,8 +405,8 @@ class CCXTTickerBacktestMarketDataSource(
|
|
|
405
405
|
|
|
406
406
|
class CCXTOHLCVMarketDataSource(OHLCVMarketDataSource):
|
|
407
407
|
|
|
408
|
-
def get_data(self, **kwargs):
|
|
409
|
-
market_service = CCXTMarketService(
|
|
408
|
+
def get_data(self, market_credential_service, **kwargs):
|
|
409
|
+
market_service = CCXTMarketService(market_credential_service)
|
|
410
410
|
|
|
411
411
|
if self.start_date is None:
|
|
412
412
|
raise OperationalException(
|
|
@@ -153,7 +153,7 @@ class OrderService(RepositoryService):
|
|
|
153
153
|
if OrderType.LIMIT.equals(order.get_order_type()):
|
|
154
154
|
|
|
155
155
|
if OrderSide.BUY.equals(order.get_order_side()):
|
|
156
|
-
self.market_service.create_limit_buy_order(
|
|
156
|
+
external_order = self.market_service.create_limit_buy_order(
|
|
157
157
|
target_symbol=order.get_target_symbol(),
|
|
158
158
|
trading_symbol=order.get_trading_symbol(),
|
|
159
159
|
amount=order.get_amount(),
|
|
@@ -161,33 +161,30 @@ class OrderService(RepositoryService):
|
|
|
161
161
|
market=portfolio.get_market()
|
|
162
162
|
)
|
|
163
163
|
else:
|
|
164
|
-
self.market_service
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
external_order = self.market_service\
|
|
165
|
+
.create_limit_sell_order(
|
|
166
|
+
target_symbol=order.get_target_symbol(),
|
|
167
|
+
trading_symbol=order.get_trading_symbol(),
|
|
168
|
+
amount=order.get_amount(),
|
|
169
|
+
price=order.get_price(),
|
|
170
|
+
market=portfolio.get_market()
|
|
171
|
+
)
|
|
171
172
|
else:
|
|
172
173
|
if OrderSide.BUY.equals(order.get_order_side()):
|
|
173
174
|
raise OperationalException("Market buy order not supported")
|
|
174
175
|
else:
|
|
175
|
-
self.market_service
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
"updated_at": datetime.now()
|
|
188
|
-
}
|
|
189
|
-
)
|
|
190
|
-
return order
|
|
176
|
+
external_order = self.market_service\
|
|
177
|
+
.create_market_sell_order(
|
|
178
|
+
target_symbol=order.get_target_symbol(),
|
|
179
|
+
trading_symbol=order.get_trading_symbol(),
|
|
180
|
+
amount=order.get_amount(),
|
|
181
|
+
market=portfolio.get_market()
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
data = external_order.to_dict()
|
|
185
|
+
data["status"] = OrderStatus.OPEN.value
|
|
186
|
+
data["updated_at"] = datetime.now()
|
|
187
|
+
return self.update(order_id, data)
|
|
191
188
|
except Exception as e:
|
|
192
189
|
logger.error("Error executing order: {}".format(e))
|
|
193
190
|
return self.update(
|
|
@@ -99,7 +99,6 @@ class PortfolioService(RepositoryService):
|
|
|
99
99
|
}
|
|
100
100
|
)
|
|
101
101
|
|
|
102
|
-
|
|
103
102
|
for position in self.position_repository.get_all(
|
|
104
103
|
{"portfolio_id": portfolio.id}
|
|
105
104
|
):
|
|
@@ -168,9 +167,11 @@ class PortfolioService(RepositoryService):
|
|
|
168
167
|
if self.repository.exists(
|
|
169
168
|
{"identifier": portfolio_configuration.identifier}
|
|
170
169
|
):
|
|
171
|
-
|
|
170
|
+
portfolio = self.repository.find(
|
|
172
171
|
{"identifier": portfolio_configuration.identifier}
|
|
173
172
|
)
|
|
173
|
+
self.sync_portfolio(portfolio, portfolio_configuration)
|
|
174
|
+
return portfolio
|
|
174
175
|
|
|
175
176
|
balances = self.market_service\
|
|
176
177
|
.get_balance(market=portfolio_configuration.market)
|
|
@@ -185,6 +186,19 @@ class PortfolioService(RepositoryService):
|
|
|
185
186
|
balances[portfolio_configuration.trading_symbol.upper()]
|
|
186
187
|
["free"]
|
|
187
188
|
)
|
|
189
|
+
|
|
190
|
+
if portfolio_configuration.initial_balance is not None and \
|
|
191
|
+
unallocated < portfolio_configuration.initial_balance:
|
|
192
|
+
raise OperationalException(
|
|
193
|
+
f"Insufficient balance on market "
|
|
194
|
+
f"{portfolio_configuration.market} "
|
|
195
|
+
f"for trading symbol "
|
|
196
|
+
f"{portfolio_configuration.trading_symbol}. "
|
|
197
|
+
f"Portfolio configuration initial balance: "
|
|
198
|
+
f"{portfolio_configuration.initial_balance} "
|
|
199
|
+
f"Available balance: {unallocated}"
|
|
200
|
+
)
|
|
201
|
+
|
|
188
202
|
creation_data = {
|
|
189
203
|
"unallocated": unallocated,
|
|
190
204
|
"identifier": portfolio_configuration.identifier,
|
|
@@ -202,3 +216,32 @@ class PortfolioService(RepositoryService):
|
|
|
202
216
|
}
|
|
203
217
|
)
|
|
204
218
|
self.create_snapshot(portfolio.id, created_at=portfolio.created_at)
|
|
219
|
+
|
|
220
|
+
def sync_portfolio(self, portfolio, portfolio_configuration):
|
|
221
|
+
balances = self.market_service \
|
|
222
|
+
.get_balance(market=portfolio_configuration.market)
|
|
223
|
+
|
|
224
|
+
if portfolio_configuration.trading_symbol.upper() not in balances:
|
|
225
|
+
raise OperationalException(
|
|
226
|
+
f"Trading symbol balance not available "
|
|
227
|
+
f"in portfolio on market {portfolio_configuration.market}"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
unallocated = float(
|
|
231
|
+
balances[portfolio_configuration.trading_symbol.upper()]
|
|
232
|
+
["free"]
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if unallocated < portfolio.unallocated:
|
|
236
|
+
raise OperationalException(
|
|
237
|
+
"There seems to be a mismatch between the portfolio of this "
|
|
238
|
+
"algorithm and the portfolio on the exchange. "
|
|
239
|
+
f"Please make sure that the available "
|
|
240
|
+
f"{portfolio.trading_symbol} "
|
|
241
|
+
f"of your portfolio on the market {portfolio.market} "
|
|
242
|
+
"matches the portfolio of this algorithm."
|
|
243
|
+
f"Current portfolio: {portfolio.unallocated} "
|
|
244
|
+
f"{portfolio.trading_symbol}"
|
|
245
|
+
f"Available on market: {unallocated} "
|
|
246
|
+
f"{portfolio.trading_symbol}"
|
|
247
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version: 2.0
|
|
2
|
+
Name: investing_algorithm_framework
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: A framework for creating an investment algorithm
|
|
5
5
|
Home-page: https://github.com/coding-kitties/investing-algorithm-framework.git
|
|
6
6
|
Download-URL: https://github.com/coding-kitties/investing-algorithm-framework/archive/v0.1.1.tar.gz
|
|
@@ -259,9 +259,9 @@ The framework has by default support for [ccxt](https://github.com/ccxt/ccxt).
|
|
|
259
259
|
This should allow you to connect to a lot of brokers/exchanges.
|
|
260
260
|
|
|
261
261
|
```python
|
|
262
|
-
from investing_algorithm_framework import
|
|
263
|
-
MarketCredential
|
|
264
|
-
app =
|
|
262
|
+
from investing_algorithm_framework import PortfolioConfiguration, \
|
|
263
|
+
MarketCredential, create_app
|
|
264
|
+
app = create_app()
|
|
265
265
|
app.add_market_credential(
|
|
266
266
|
MarketCredential(
|
|
267
267
|
market="<your market>",
|
|
@@ -117,7 +117,6 @@ investing_algorithm_framework/services/backtest_service.py
|
|
|
117
117
|
investing_algorithm_framework/services/configuration_service.py
|
|
118
118
|
investing_algorithm_framework/services/market_credential_service.py
|
|
119
119
|
investing_algorithm_framework/services/portfolio_configuration_service.py
|
|
120
|
-
investing_algorithm_framework/services/portfolio_service.py
|
|
121
120
|
investing_algorithm_framework/services/portfolio_snapshot_service.py
|
|
122
121
|
investing_algorithm_framework/services/position_service.py
|
|
123
122
|
investing_algorithm_framework/services/position_snapshot_service.py
|
investing_algorithm_framework-2.0/investing_algorithm_framework/services/portfolio_service.py
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
|
|
4
|
-
from investing_algorithm_framework.domain import OrderSide, OrderStatus, \
|
|
5
|
-
OperationalException, MarketService
|
|
6
|
-
from investing_algorithm_framework.services.repository_service \
|
|
7
|
-
import RepositoryService
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger("investing_algorithm_framework")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class PortfolioService(RepositoryService):
|
|
13
|
-
|
|
14
|
-
def __init__(
|
|
15
|
-
self,
|
|
16
|
-
market_service: MarketService,
|
|
17
|
-
market_credential_service,
|
|
18
|
-
position_repository,
|
|
19
|
-
order_service,
|
|
20
|
-
portfolio_repository,
|
|
21
|
-
portfolio_configuration_service,
|
|
22
|
-
portfolio_snapshot_service,
|
|
23
|
-
):
|
|
24
|
-
self.market_service = market_service
|
|
25
|
-
self.position_repository = position_repository
|
|
26
|
-
self.portfolio_configuration_service = portfolio_configuration_service
|
|
27
|
-
self.order_service = order_service
|
|
28
|
-
self.portfolio_snapshot_service = portfolio_snapshot_service
|
|
29
|
-
self.market_credentials_service = market_credential_service
|
|
30
|
-
super(PortfolioService, self).__init__(portfolio_repository)
|
|
31
|
-
|
|
32
|
-
def find(self, query_params):
|
|
33
|
-
portfolio = self.repository.find(query_params)
|
|
34
|
-
portfolio_configuration = self.portfolio_configuration_service\
|
|
35
|
-
.get(portfolio.identifier)
|
|
36
|
-
portfolio.configuration = portfolio_configuration
|
|
37
|
-
return portfolio
|
|
38
|
-
|
|
39
|
-
def create(self, data):
|
|
40
|
-
unallocated = data.get("unallocated", 0)
|
|
41
|
-
portfolio = super(PortfolioService, self).create(data)
|
|
42
|
-
self.position_repository.create(
|
|
43
|
-
{
|
|
44
|
-
"symbol": portfolio.get_trading_symbol(),
|
|
45
|
-
"amount": unallocated,
|
|
46
|
-
"portfolio_id": portfolio.id,
|
|
47
|
-
"cost": unallocated
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
|
-
self.create_snapshot(portfolio.id, created_at=portfolio.created_at)
|
|
51
|
-
return portfolio
|
|
52
|
-
|
|
53
|
-
def sync_portfolios(self):
|
|
54
|
-
|
|
55
|
-
for portfolio in self.get_all():
|
|
56
|
-
portfolio_configuration = self.portfolio_configuration_service\
|
|
57
|
-
.get(portfolio.identifier)
|
|
58
|
-
|
|
59
|
-
self.market_service.market_data_credentials = \
|
|
60
|
-
self.market_credentials_service.get_all()
|
|
61
|
-
balances = self.market_service.get_balance(portfolio.market)
|
|
62
|
-
|
|
63
|
-
for symbol in balances["free"]:
|
|
64
|
-
balance = balances["free"][symbol]
|
|
65
|
-
logger.info(f"Syncing {symbol} balance")
|
|
66
|
-
|
|
67
|
-
if self.position_repository.exists(
|
|
68
|
-
{"portfolio_id": portfolio.id, "symbol": symbol}
|
|
69
|
-
):
|
|
70
|
-
position = self.position_repository.find(
|
|
71
|
-
{
|
|
72
|
-
"portfolio_id": portfolio.id,
|
|
73
|
-
"symbol": symbol
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
self.position_repository.update(
|
|
77
|
-
position.id,
|
|
78
|
-
{"amount": balance}
|
|
79
|
-
)
|
|
80
|
-
else:
|
|
81
|
-
self.position_repository.create(
|
|
82
|
-
{
|
|
83
|
-
"symbol": symbol,
|
|
84
|
-
"amount": balance,
|
|
85
|
-
"portfolio_id": portfolio.id
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
if symbol == portfolio.trading_symbol:
|
|
90
|
-
if portfolio.unallocated != balance:
|
|
91
|
-
logger.info(
|
|
92
|
-
"Updating unallocated balance "
|
|
93
|
-
f"from {portfolio.unallocated} "
|
|
94
|
-
f"to {balance}"
|
|
95
|
-
)
|
|
96
|
-
difference = balance - portfolio.get_unallocated()
|
|
97
|
-
self.update(
|
|
98
|
-
portfolio.id,
|
|
99
|
-
{
|
|
100
|
-
"unallocated": portfolio.get_unallocated() + difference,
|
|
101
|
-
"net_size": portfolio.get_net_size() + difference
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
for position in self.position_repository.get_all(
|
|
107
|
-
{"portfolio_id": portfolio.id}
|
|
108
|
-
):
|
|
109
|
-
if position.symbol == portfolio.trading_symbol:
|
|
110
|
-
continue
|
|
111
|
-
|
|
112
|
-
logger.info(f"Syncing {position.symbol} orders")
|
|
113
|
-
|
|
114
|
-
external_orders = self.market_service\
|
|
115
|
-
.get_orders(
|
|
116
|
-
f"{position.symbol}/{portfolio.trading_symbol}",
|
|
117
|
-
since=portfolio_configuration.track_from,
|
|
118
|
-
market=portfolio.market
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
logger.info(
|
|
122
|
-
f"Found {len(external_orders)} external orders "
|
|
123
|
-
f"for position {position.symbol}"
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
for external_order in external_orders:
|
|
127
|
-
|
|
128
|
-
if self.order_service.exists(
|
|
129
|
-
{"external_id": external_order.external_id}
|
|
130
|
-
):
|
|
131
|
-
logger.info("Updating existing order")
|
|
132
|
-
order = self.order_service.find(
|
|
133
|
-
{"external_id": external_order.external_id}
|
|
134
|
-
)
|
|
135
|
-
self.order_service.update(
|
|
136
|
-
order.id, external_order.to_dict()
|
|
137
|
-
)
|
|
138
|
-
else:
|
|
139
|
-
logger.info(
|
|
140
|
-
"Creating new order based on external order"
|
|
141
|
-
)
|
|
142
|
-
data = external_order.to_dict()
|
|
143
|
-
data["position_id"] = position.id
|
|
144
|
-
data["portfolio_id"] = portfolio.id
|
|
145
|
-
self.order_service.create(
|
|
146
|
-
data, execute=False, validate=False, sync=False
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
def create_snapshot(self, portfolio_id, created_at=None):
|
|
150
|
-
|
|
151
|
-
if created_at is None:
|
|
152
|
-
created_at = datetime.utcnow()
|
|
153
|
-
|
|
154
|
-
portfolio = self.get(portfolio_id)
|
|
155
|
-
pending_orders = self.order_service.get_all(
|
|
156
|
-
{
|
|
157
|
-
"order_side": OrderSide.BUY.value,
|
|
158
|
-
"status": OrderStatus.OPEN.value,
|
|
159
|
-
"portfolio_id": portfolio.id
|
|
160
|
-
}
|
|
161
|
-
)
|
|
162
|
-
return self.portfolio_snapshot_service.create_snapshot(
|
|
163
|
-
portfolio,
|
|
164
|
-
pending_orders=pending_orders,
|
|
165
|
-
created_at=created_at
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
def create_portfolio_from_configuration(self, portfolio_configuration):
|
|
169
|
-
logger.info("Creating portfolios")
|
|
170
|
-
|
|
171
|
-
if self.repository.exists(
|
|
172
|
-
{"identifier": portfolio_configuration.identifier}
|
|
173
|
-
):
|
|
174
|
-
return self.repository.find(
|
|
175
|
-
{"identifier": portfolio_configuration.identifier}
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
balances = self.market_service\
|
|
179
|
-
.get_balance(market=portfolio_configuration.market)
|
|
180
|
-
|
|
181
|
-
if portfolio_configuration.trading_symbol.upper() not in balances:
|
|
182
|
-
raise OperationalException(
|
|
183
|
-
f"Trading symbol balance not available "
|
|
184
|
-
f"in portfolio on market {portfolio_configuration.market}"
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
unallocated = float(
|
|
188
|
-
balances[portfolio_configuration.trading_symbol.upper()]
|
|
189
|
-
["free"]
|
|
190
|
-
)
|
|
191
|
-
creation_data = {
|
|
192
|
-
"unallocated": unallocated,
|
|
193
|
-
"identifier": portfolio_configuration.identifier,
|
|
194
|
-
"trading_symbol": portfolio_configuration.trading_symbol.upper(),
|
|
195
|
-
"market": portfolio_configuration.market.upper(),
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
portfolio = self.repository.create(creation_data)
|
|
199
|
-
self.position_repository.create(
|
|
200
|
-
{
|
|
201
|
-
"symbol": portfolio.get_trading_symbol(),
|
|
202
|
-
"amount": unallocated,
|
|
203
|
-
"portfolio_id": portfolio.id,
|
|
204
|
-
"cost": unallocated
|
|
205
|
-
}
|
|
206
|
-
)
|
|
207
|
-
self.create_snapshot(portfolio.id, created_at=portfolio.created_at)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{investing_algorithm_framework-2.0 → investing_algorithm_framework-2.0.2}/tests/test_create_app.py
RENAMED
|
File without changes
|