Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,7 @@ def get_historical_tentacle_configs(
for config_start_time_and_config in master_config[
constants.CONFIG_HISTORICAL_CONFIGURATION
]
if (
config_start_time_and_config[0] >= from_time
and config_start_time_and_config[0] <= to_time
)
if from_time <= config_start_time_and_config[0] <= to_time
]
except KeyError:
raise KeyError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ def _reset_kline(self):

def _update_kline_key(self, kline_key, kline_update):
try:
if kline_update[kline_key] is not math.nan:
if not math.isnan(kline_update[kline_key]):
self.kline[kline_key] = kline_update[kline_key]
except KeyError:
pass

def _update_kline_init_only_key(self, kline_key, kline_update):
try:
if self.kline[kline_key] is math.nan:
if math.isnan(self.kline[kline_key]):
self.kline[kline_key] = kline_update[kline_key]
except KeyError:
pass
Expand All @@ -58,11 +58,11 @@ def kline_update(self, kline):
self._update_kline_key(enums.PriceIndexes.IND_PRICE_VOL.value, kline)
self._update_kline_key(enums.PriceIndexes.IND_PRICE_CLOSE.value, kline)

if self.kline[enums.PriceIndexes.IND_PRICE_HIGH.value] is math.nan or \
if math.isnan(self.kline[enums.PriceIndexes.IND_PRICE_HIGH.value]) or \
self.kline[enums.PriceIndexes.IND_PRICE_HIGH.value] < kline[enums.PriceIndexes.IND_PRICE_HIGH.value]:
self._update_kline_key(enums.PriceIndexes.IND_PRICE_HIGH.value, kline)

if self.kline[enums.PriceIndexes.IND_PRICE_LOW.value] is math.nan or \
if math.isnan(self.kline[enums.PriceIndexes.IND_PRICE_LOW.value]) or \
self.kline[enums.PriceIndexes.IND_PRICE_LOW.value] > kline[enums.PriceIndexes.IND_PRICE_LOW.value]:
self._update_kline_key(enums.PriceIndexes.IND_PRICE_LOW.value, kline)
except TypeError as e:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class ExchangeColumns(enum.Enum):
REST = "rest"
WEBSOCKET = "ws"
LOGO_URL = "logo"
ICON_URL = "icon"
REFERRAL = "referral"


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def is_ms_valid(value, zero_valid=False):
value = float(value)
except ValueError:
return False
return value is not None and value is not math.nan and (value >= 0 if zero_valid else value > 0)
return value is not None and not math.isnan(value) and (value >= 0 if zero_valid else value > 0)


def check_market_status_limits(market_limit):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ async def get_exchange_details(
exchange.name,
exchange.urls[ccxt_enums.ExchangeColumns.WEBSITE.value],
exchange.urls[ccxt_enums.ExchangeColumns.API.value],
exchange.urls[ccxt_enums.ExchangeColumns.LOGO_URL.value],
_get_exchange_image_url_from_exchange_metadata(exchange.describe()),
False,
)
except AttributeError as err:
Expand Down Expand Up @@ -748,6 +748,17 @@ def _to_available_trading_types(exchange_name: str) -> list[protocol_models.Trad
]


def _get_exchange_image_url_from_exchange_metadata(exchange_metadata: dict) -> typing.Optional[str]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

options = exchange_metadata.get("options") or {}
octobot_options = options.get("octobot") or {}
octobot_urls = octobot_options.get("urls") or {}
icon_url = octobot_urls.get(ccxt_enums.ExchangeColumns.ICON_URL.value)
if icon_url:
return icon_url
exchange_urls = exchange_metadata.get("urls") or {}
return exchange_urls.get(ccxt_enums.ExchangeColumns.LOGO_URL.value)


def _get_register_url_from_exchange_urls(exchange_urls: dict) -> typing.Optional[str]:
referral = exchange_urls.get(ccxt_enums.ExchangeColumns.REFERRAL.value)
if isinstance(referral, dict):
Expand All @@ -767,7 +778,7 @@ def _build_ccxt_exchange_availability(exchange_name: str) -> protocol_models.Exc
return protocol_models.ExchangeAvailability(
internal_name=exchange_name,
name=exchange_metadata.get("name") or exchange_name,
logo=exchange_urls.get(ccxt_enums.ExchangeColumns.LOGO_URL.value),
logo=_get_exchange_image_url_from_exchange_metadata(exchange_metadata),
available_trading_types=_to_available_trading_types(exchange_name),
support_type=_get_exchange_support_status(exchange_name),
sandboxable=_is_exchange_sandboxable(exchange_metadata),
Expand Down
2 changes: 1 addition & 1 deletion packages/trading/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
numpy

# Exchange connection requirements
octobot-ccxt==0.0.13 # always ensure real exchanges tests (in tests_additional and authenticated exchange tests) are passing before changing the ccxt version
octobot-ccxt==0.0.14 # always ensure real exchanges tests (in tests_additional and authenticated exchange tests) are passing before changing the ccxt version

cryptography # Never specify a version (managed by https://github.com/Drakkar-Software/OctoBot-PyPi-Linux-Deployer)

Expand Down
28 changes: 27 additions & 1 deletion packages/trading/tests/exchanges/util/test_exchange_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ async def test_get_exchange_details(tentacles_setup_config, supported_exchanges)
assert details.name == "Binance"
assert details.url == "https://www.binance.com"
assert len(details.api) > 1
assert "https://github.com/user-attachments/assets" in details.logo_url
assert details.logo_url == "https://exchanges-icons.octobot.cloud/binance-icon.webp"
assert details.has_websocket is False # default value
get_tentacle_config_mock.assert_not_called()

Expand Down Expand Up @@ -634,6 +634,32 @@ def test_builds_exchange_availability_from_metadata(
protocol_models.TradingType.FUTURES,
]

@mock.patch.object(exchange_util, "is_broker_enabled_on_exchange", return_value=False)
@mock.patch.object(exchange_util, "get_supported_exchange_types")
@mock.patch.object(exchange_util, "_get_ccxt_exchange_metadata")
def test_prefers_icon_over_logo_in_availability(
self,
metadata_mock,
supported_types_mock,
_broker_enabled_mock,
):
metadata_mock.return_value = {
"name": "Binance",
"options": {
"octobot": {
"urls": {
"icon": "https://exchanges-icons.octobot.cloud/binance-icon.webp",
},
},
},
"urls": {
"logo": "https://logo.example/binance",
},
}
supported_types_mock.return_value = [enums.ExchangeTypes.SPOT]
availability = exchange_util._build_ccxt_exchange_availability("binance")
assert availability.logo == "https://exchanges-icons.octobot.cloud/binance-icon.webp"

@mock.patch.object(exchange_util, "is_broker_enabled_on_exchange", return_value=False)
@mock.patch.object(exchange_util, "get_supported_exchange_types")
@mock.patch.object(exchange_util, "_get_ccxt_exchange_metadata")
Expand Down
Loading