Skip to content
Draft
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
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
setup(
name="wata",
version="0.1",
packages=find_packages(),
package_dir={'': 'src'},
packages=find_packages(where='src'),
entry_points={
'console_scripts': [
'watasaxoauth=src.saxo_authen.cli:main',
Expand Down
10 changes: 6 additions & 4 deletions src/trade/api_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -853,10 +853,12 @@ def get_spending_power(self):
if not resp_balance or "SpendingPower" not in resp_balance:
logging.error(f"Invalid balance response: {resp_balance}")
raise SaxoApiError("Invalid balance response received, missing SpendingPower.")
spending_power = resp_balance["SpendingPower"]
if not isinstance(spending_power, (int, float)):
logging.error(f"Invalid SpendingPower value: {spending_power}")
raise SaxoApiError(f"Invalid SpendingPower value received: {spending_power}")
spending_power_raw = resp_balance["SpendingPower"]
try:
spending_power = float(spending_power_raw)
except (ValueError, TypeError):
logging.error(f"Invalid SpendingPower value: {spending_power_raw}")
raise SaxoApiError(f"Invalid SpendingPower value received: {spending_power_raw}")

logging.info(f"Spending Power retrieved: {spending_power}")
return spending_power
Expand Down
8 changes: 8 additions & 0 deletions src/wata.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Metadata-Version: 2.4
Name: wata
Version: 0.1
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: python-dotenv
Dynamic: license-file
Dynamic: requires-dist
160 changes: 160 additions & 0 deletions src/wata.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
LICENSE
README.md
setup.py
src/configuration/__init__.py
src/database/__init__.py
src/database/show_data.py
src/logging_helper/__init__.py
src/message_helper/__init__.py
src/mq_telegram/__init__.py
src/mq_telegram/tools.py
src/saxo_authen/__init__.py
src/saxo_authen/cli.py
src/saxo_openapi/__init__.py
src/saxo_openapi/exceptions.py
src/saxo_openapi/saxo_openapi.py
src/saxo_openapi/contrib/__init__.py
src/saxo_openapi/contrib/session.py
src/saxo_openapi/contrib/orders/__init__.py
src/saxo_openapi/contrib/orders/baseorder.py
src/saxo_openapi/contrib/orders/helper.py
src/saxo_openapi/contrib/orders/limitorder.py
src/saxo_openapi/contrib/orders/marketorder.py
src/saxo_openapi/contrib/orders/mixin.py
src/saxo_openapi/contrib/orders/onfill.py
src/saxo_openapi/contrib/orders/stoporder.py
src/saxo_openapi/contrib/util/__init__.py
src/saxo_openapi/contrib/util/instrument_to_uic.py
src/saxo_openapi/contrib/ws/__init__.py
src/saxo_openapi/contrib/ws/stream.py
src/saxo_openapi/definitions/__init__.py
src/saxo_openapi/definitions/accounthistory.py
src/saxo_openapi/definitions/activities.py
src/saxo_openapi/definitions/orders.py
src/saxo_openapi/definitions/reportformats.py
src/saxo_openapi/endpoints/__init__.py
src/saxo_openapi/endpoints/apirequest.py
src/saxo_openapi/endpoints/decorators.py
src/saxo_openapi/endpoints/accounthistory/__init__.py
src/saxo_openapi/endpoints/accounthistory/accountvalues.py
src/saxo_openapi/endpoints/accounthistory/base.py
src/saxo_openapi/endpoints/accounthistory/historicalpositions.py
src/saxo_openapi/endpoints/accounthistory/performance.py
src/saxo_openapi/endpoints/accounthistory/responses/__init__.py
src/saxo_openapi/endpoints/accounthistory/responses/accountvalues.py
src/saxo_openapi/endpoints/accounthistory/responses/historicalpositions.py
src/saxo_openapi/endpoints/accounthistory/responses/performance.py
src/saxo_openapi/endpoints/chart/__init__.py
src/saxo_openapi/endpoints/chart/base.py
src/saxo_openapi/endpoints/chart/charts.py
src/saxo_openapi/endpoints/chart/responses/__init__.py
src/saxo_openapi/endpoints/chart/responses/charts.py
src/saxo_openapi/endpoints/eventnotificationservices/__init__.py
src/saxo_openapi/endpoints/eventnotificationservices/base.py
src/saxo_openapi/endpoints/eventnotificationservices/clientactivities.py
src/saxo_openapi/endpoints/eventnotificationservices/responses/__init__.py
src/saxo_openapi/endpoints/eventnotificationservices/responses/clientactivities.py
src/saxo_openapi/endpoints/portfolio/__init__.py
src/saxo_openapi/endpoints/portfolio/accountgroups.py
src/saxo_openapi/endpoints/portfolio/accounts.py
src/saxo_openapi/endpoints/portfolio/balances.py
src/saxo_openapi/endpoints/portfolio/base.py
src/saxo_openapi/endpoints/portfolio/clients.py
src/saxo_openapi/endpoints/portfolio/closedpositions.py
src/saxo_openapi/endpoints/portfolio/exposure.py
src/saxo_openapi/endpoints/portfolio/netpositions.py
src/saxo_openapi/endpoints/portfolio/orders.py
src/saxo_openapi/endpoints/portfolio/positions.py
src/saxo_openapi/endpoints/portfolio/users.py
src/saxo_openapi/endpoints/portfolio/responses/__init__.py
src/saxo_openapi/endpoints/portfolio/responses/accountgroups.py
src/saxo_openapi/endpoints/portfolio/responses/accounts.py
src/saxo_openapi/endpoints/portfolio/responses/balances.py
src/saxo_openapi/endpoints/portfolio/responses/clients.py
src/saxo_openapi/endpoints/portfolio/responses/closedpositions.py
src/saxo_openapi/endpoints/portfolio/responses/exposure.py
src/saxo_openapi/endpoints/portfolio/responses/netpositions.py
src/saxo_openapi/endpoints/portfolio/responses/orders.py
src/saxo_openapi/endpoints/portfolio/responses/positions.py
src/saxo_openapi/endpoints/portfolio/responses/users.py
src/saxo_openapi/endpoints/referencedata/__init__.py
src/saxo_openapi/endpoints/referencedata/algostrategies.py
src/saxo_openapi/endpoints/referencedata/base.py
src/saxo_openapi/endpoints/referencedata/countries.py
src/saxo_openapi/endpoints/referencedata/cultures.py
src/saxo_openapi/endpoints/referencedata/currencies.py
src/saxo_openapi/endpoints/referencedata/currencypairs.py
src/saxo_openapi/endpoints/referencedata/exchanges.py
src/saxo_openapi/endpoints/referencedata/instruments.py
src/saxo_openapi/endpoints/referencedata/languages.py
src/saxo_openapi/endpoints/referencedata/standarddates.py
src/saxo_openapi/endpoints/referencedata/timezones.py
src/saxo_openapi/endpoints/referencedata/responses/__init__.py
src/saxo_openapi/endpoints/referencedata/responses/algostrategies.py
src/saxo_openapi/endpoints/referencedata/responses/countries.py
src/saxo_openapi/endpoints/referencedata/responses/cultures.py
src/saxo_openapi/endpoints/referencedata/responses/currencies.py
src/saxo_openapi/endpoints/referencedata/responses/currencypairs.py
src/saxo_openapi/endpoints/referencedata/responses/exchanges.py
src/saxo_openapi/endpoints/referencedata/responses/instruments.py
src/saxo_openapi/endpoints/referencedata/responses/languages.py
src/saxo_openapi/endpoints/referencedata/responses/standarddates.py
src/saxo_openapi/endpoints/referencedata/responses/timezones.py
src/saxo_openapi/endpoints/rootservices/__init__.py
src/saxo_openapi/endpoints/rootservices/base.py
src/saxo_openapi/endpoints/rootservices/diagnostics.py
src/saxo_openapi/endpoints/rootservices/features.py
src/saxo_openapi/endpoints/rootservices/sessions.py
src/saxo_openapi/endpoints/rootservices/subscriptions.py
src/saxo_openapi/endpoints/rootservices/user.py
src/saxo_openapi/endpoints/rootservices/responses/__init__.py
src/saxo_openapi/endpoints/rootservices/responses/features.py
src/saxo_openapi/endpoints/rootservices/responses/sessions.py
src/saxo_openapi/endpoints/rootservices/responses/subscriptions.py
src/saxo_openapi/endpoints/rootservices/responses/user.py
src/saxo_openapi/endpoints/trading/__init__.py
src/saxo_openapi/endpoints/trading/allocationkeys.py
src/saxo_openapi/endpoints/trading/base.py
src/saxo_openapi/endpoints/trading/infoprices.py
src/saxo_openapi/endpoints/trading/messages.py
src/saxo_openapi/endpoints/trading/optionschain.py
src/saxo_openapi/endpoints/trading/orders.py
src/saxo_openapi/endpoints/trading/positions.py
src/saxo_openapi/endpoints/trading/prices.py
src/saxo_openapi/endpoints/trading/screener.py
src/saxo_openapi/endpoints/trading/responses/__init__.py
src/saxo_openapi/endpoints/trading/responses/allocationkeys.py
src/saxo_openapi/endpoints/trading/responses/infoprices.py
src/saxo_openapi/endpoints/trading/responses/messages.py
src/saxo_openapi/endpoints/trading/responses/optionschain.py
src/saxo_openapi/endpoints/trading/responses/orders.py
src/saxo_openapi/endpoints/trading/responses/positions.py
src/saxo_openapi/endpoints/trading/responses/prices.py
src/saxo_openapi/endpoints/valueadd/__init__.py
src/saxo_openapi/endpoints/valueadd/base.py
src/saxo_openapi/endpoints/valueadd/pricealerts.py
src/saxo_openapi/endpoints/valueadd/responses/__init__.py
src/saxo_openapi/endpoints/valueadd/responses/pricealerts.py
src/scheduler/__init__.py
src/schema/__init__.py
src/wata.egg-info/PKG-INFO
src/wata.egg-info/SOURCES.txt
src/wata.egg-info/dependency_links.txt
src/wata.egg-info/entry_points.txt
src/wata.egg-info/requires.txt
src/wata.egg-info/top_level.txt
src/web_server/__init__.py
src/web_server/auth_token.py
src/web_server/cli.py
tests/test_configuration_manager.py
tests/test_data_factory.py
tests/test_db_position_manager.py
tests/test_instrument_service.py
tests/test_order_service.py
tests/test_performance_monitor.py
tests/test_position_service.py
tests/test_saxo_api_client.py
tests/test_trade_rules.py
tests/test_trading_orchestrator.py
tests/test_web_server.py
tests/test_web_server_advanced.py
Empty file.
3 changes: 3 additions & 0 deletions src/wata.egg-info/entry_points.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[console_scripts]
watasaxoauth = src.saxo_authen.cli:main
watawebtoken = src.web_server.cli:main
2 changes: 2 additions & 0 deletions src/wata.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests
python-dotenv
10 changes: 10 additions & 0 deletions src/wata.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
configuration
database
logging_helper
message_helper
mq_telegram
saxo_authen
saxo_openapi
scheduler
schema
web_server
66 changes: 66 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import pytest
from unittest.mock import MagicMock

from src.configuration import ConfigurationManager
from src.database import DbOrderManager, DbPositionManager
from src.trade.rules import TradingRule
from src.saxo_authen import SaxoAuth
from src.trade.api_actions import SaxoApiClient

@pytest.fixture
def mock_config_manager():
"""A mock for ConfigurationManager with a flexible side_effect."""
manager = MagicMock(spec=ConfigurationManager)

def get_config_value(key, default=None):
configs = {
"saxo_auth.env": "simulation",
"trade.config.general.api_limits": {"top_instruments": 200, "top_positions": 200, "top_closed_positions": 500},
"trade.config.turbo_preference.price_range": {"min": 4, "max": 15},
"trade.config.general.retry_config": {"max_retries": 5, "retry_sleep_seconds": 2},
"trade.config.general.websocket": {"refresh_rate_ms": 10000},
"trade.config.buying_power": {"safety_margins": {"bid_calculation": 1}, "max_account_funds_to_use_percentage": 100},
"trade.config.position_management": {"performance_thresholds": {"stoploss_percent": -20, "max_profit_percent": 60}},
"trade.config.general": {"timezone": "Europe/Paris"},
"logging.persistant": {"log_path": "/tmp/logs"}
}
# Return specific value if key exists, otherwise the provided default
return configs.get(key, default)

manager.get_config_value.side_effect = get_config_value
manager.get_logging_config.return_value = {"persistant": {"log_path": "/tmp/logs"}}
return manager

@pytest.fixture
def mock_saxo_auth():
"""A mock for SaxoAuth."""
auth = MagicMock(spec=SaxoAuth)
auth.get_token.return_value = "test_token"
return auth

@pytest.fixture
def mock_db_order_manager():
"""A mock for DbOrderManager."""
return MagicMock(spec=DbOrderManager)

@pytest.fixture
def mock_db_position_manager():
"""A mock for DbPositionManager."""
return MagicMock(spec=DbPositionManager)

@pytest.fixture
def mock_trading_rule():
"""A mock for TradingRule."""
rule = MagicMock(spec=TradingRule)
rule.get_rule_config.return_value = {"percent_profit_wanted_per_days": 1.0}
return rule

@pytest.fixture
def mock_api_client():
"""
A mock for the low-level SaxoApiClient.
This fixture mocks the *wrapper* client, not the underlying SaxoOpenApiLib.
This is useful for testing the services that *use* the client.
"""
client = MagicMock(spec=SaxoApiClient)
return client
Loading