Architecture¶
etoropy is organized in layers. The high-level
EToroTrading client composes REST, WebSocket, and
instrument-resolution sub-systems and exposes a unified async API.
Layer diagram¶
+------------------------------------------------------+
| EToroTrading (trading/client.py) |
| High-level: buy, sell, stream, wait_for_order |
+----+-----------------------------+-------------------+
| |
+----v-------------+ +-----------v-----------+
| RestClient | | WsClient |
| (9 sub-clients) | | auth, heartbeat, |
| | | reconnect, events |
+----+-------------+ +-----------+-----------+
| |
+----v-------------+ +-----------v-----------+
| HttpClient | | websockets lib |
| httpx + retry | | (ping_interval for |
| + rate limiter | | heartbeat) |
+------------------+ +-----------------------+
Package layout¶
etoropy/
__init__.py # Public API exports
_utils.py # UUID generation
config/
settings.py # EToroConfig (pydantic-settings)
constants.py # URLs, defaults, limits
errors/
exceptions.py # 6-class error hierarchy
models/
enums.py # CandleInterval, OrderStatusId, etc.
common.py # Pagination, TokenResponse
market_data.py # Instrument, Rate, Candle models
trading.py # Order, Position, Portfolio models
feeds.py # Social feed, user profile models
websocket.py # WsEnvelope, WsInstrumentRate, WsPrivateEvent
http/
client.py # HttpClient (httpx wrapper with auth, retry, rate limiting)
rate_limiter.py # Token-bucket rate limiter
retry.py # Exponential backoff with jitter
rest/
_base.py # BaseRestClient (GET/POST/PUT/DELETE helpers)
rest_client.py # RestClient facade (composes all sub-clients)
market_data.py # 8 endpoints
trading_execution.py # 7 endpoints (demo/real routing)
trading_info.py # 4 endpoints (demo/real routing)
watchlists.py # 14 endpoints
feeds.py # 3 endpoints
reactions.py # 1 endpoint
discovery.py # 2 endpoints
pi_data.py # 1 endpoint
users_info.py # 6 endpoints
ws/
client.py # WsClient (auth, heartbeat, reconnect, events)
message_parser.py # Parse WS envelopes into typed events
subscription.py # Topic set tracking for reconnect re-subscribe
trading/
client.py # EToroTrading (high-level entry point)
instrument_resolver.py # Symbol <-> ID resolution (CSV + API)
data/
instruments.csv # 5,200+ symbol mappings
REST sub-clients¶
The RestClient facade composes nine specialized clients:
Client |
Endpoints |
Description |
|---|---|---|
8 |
Instruments, rates, candles, exchanges, industries |
|
7 |
Market/limit orders, close positions, cancel orders |
|
4 |
Portfolio, P&L, order status, trade history |
|
14 |
CRUD for user/public watchlists |
|
3 |
Instrument/user feeds, post creation |
|
1 |
Comment creation |
|
2 |
Curated lists, market recommendations |
|
6 |
User profiles, portfolios, performance, search |
|
1 |
Copier public info |
WebSocket event system¶
EToroTrading exposes a Node.js-style event emitter:
Event |
Callback signature |
Description |
|---|---|---|
|
|
Live price tick |
|
|
Order status change |
|
|
WebSocket connected and authenticated |
|
|
Client disconnected |
|
|
Any error |
|
|
Raw WebSocket envelope |
Instrument resolution¶
The InstrumentResolver translates human-readable symbols
("AAPL", "BTC") into eToro’s integer instrument IDs through three
tiers:
Bundled CSV – 5,200+ pre-mapped symbols loaded with
load_bundled_csv(). Instant, no network call.API exact match – queries
/market-data/searchbyinternalSymbolFull.API text search – fallback free-text search on the same endpoint.
Results are cached in memory for the lifetime of the client.
Rate limiting & retry¶
Rate limiter: Token-bucket algorithm (20 requests per 10-second window by
default). Automatically pauses outgoing requests when the bucket is full.
Honors Retry-After headers from 429 responses.
Retry: Exponential backoff with jitter (+-25%). Retries on:
HTTP 429 (rate limit)
HTTP 5xx (server error)
Connection errors and read timeouts
Default: 3 attempts, 1-second base delay, 2x backoff multiplier.