Delete USDT-M futures support since the user's Binance API key does not support futures trading. This simplifies the CLI to spot-only: - Remove futures client wrapper (um_futures_client.py) - Remove futures trade commands and close position logic - Simplify account service to spot-only (no market_type field) - Remove futures references from opportunity service - Update README and tests to reflect spot-only architecture - Bump version to 2.0.7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
"""Account and market service tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from coinhunter.services import account_service, market_service
|
|
|
|
|
|
class FakeSpotClient:
|
|
def account_info(self):
|
|
return {
|
|
"balances": [
|
|
{"asset": "USDT", "free": "120.0", "locked": "0"},
|
|
{"asset": "BTC", "free": "0.01", "locked": "0"},
|
|
{"asset": "DOGE", "free": "1", "locked": "0"},
|
|
]
|
|
}
|
|
|
|
def ticker_price(self, symbols=None):
|
|
prices = {
|
|
"BTCUSDT": {"symbol": "BTCUSDT", "price": "60000"},
|
|
"DOGEUSDT": {"symbol": "DOGEUSDT", "price": "0.1"},
|
|
}
|
|
if not symbols:
|
|
return list(prices.values())
|
|
return [prices[symbol] for symbol in symbols]
|
|
|
|
def ticker_24h(self, symbols=None):
|
|
rows = [
|
|
{"symbol": "BTCUSDT", "lastPrice": "60000", "priceChangePercent": "4.5", "quoteVolume": "10000000", "highPrice": "61000", "lowPrice": "58000"},
|
|
{"symbol": "ETHUSDT", "lastPrice": "3000", "priceChangePercent": "3.0", "quoteVolume": "8000000", "highPrice": "3050", "lowPrice": "2900"},
|
|
{"symbol": "DOGEUSDT", "lastPrice": "0.1", "priceChangePercent": "1.0", "quoteVolume": "200", "highPrice": "0.11", "lowPrice": "0.09"},
|
|
]
|
|
if not symbols:
|
|
return rows
|
|
wanted = set(symbols)
|
|
return [row for row in rows if row["symbol"] in wanted]
|
|
|
|
def exchange_info(self):
|
|
return {"symbols": [{"symbol": "BTCUSDT", "status": "TRADING"}, {"symbol": "ETHUSDT", "status": "TRADING"}, {"symbol": "DOGEUSDT", "status": "BREAK"}]}
|
|
|
|
|
|
class AccountMarketServicesTestCase(unittest.TestCase):
|
|
def test_account_overview_and_dust_filter(self):
|
|
config = {
|
|
"market": {"default_quote": "USDT"},
|
|
"trading": {"dust_usdt_threshold": 10.0},
|
|
}
|
|
payload = account_service.get_overview(
|
|
config,
|
|
spot_client=FakeSpotClient(),
|
|
)
|
|
self.assertEqual(payload["overview"]["total_equity_usdt"], 720.1)
|
|
symbols = {item["symbol"] for item in payload["positions"]}
|
|
self.assertNotIn("DOGEUSDT", symbols)
|
|
self.assertIn("BTCUSDT", symbols)
|
|
|
|
def test_market_tickers_and_scan_universe(self):
|
|
config = {
|
|
"market": {"default_quote": "USDT", "universe_allowlist": [], "universe_denylist": []},
|
|
"opportunity": {"min_quote_volume": 1000},
|
|
}
|
|
tickers = market_service.get_tickers(config, ["btc/usdt", "ETH-USDT"], spot_client=FakeSpotClient())
|
|
self.assertEqual([item["symbol"] for item in tickers["tickers"]], ["BTCUSDT", "ETHUSDT"])
|
|
|
|
universe = market_service.get_scan_universe(config, spot_client=FakeSpotClient())
|
|
self.assertEqual([item["symbol"] for item in universe], ["BTCUSDT", "ETHUSDT"])
|