7
7
from example_publisher .providers .coin_gecko import CoinGecko
8
8
from example_publisher .config import Config
9
9
from example_publisher .providers .pyth_replicator import PythReplicator
10
- from example_publisher .pythd import Pythd , SubscriptionId
10
+ from example_publisher .pythd import PriceUpdate , Pythd , SubscriptionId
11
11
12
12
13
13
log = get_logger ()
@@ -50,7 +50,6 @@ def __init__(self, config: Config) -> None:
50
50
51
51
self .pythd : Pythd = Pythd (
52
52
address = config .pythd .endpoint ,
53
- on_notify_price_sched = self .on_notify_price_sched ,
54
53
)
55
54
self .subscriptions : Dict [SubscriptionId , Product ] = {}
56
55
self .products : List [Product ] = []
@@ -66,18 +65,17 @@ def is_healthy(self) -> bool:
66
65
async def start (self ):
67
66
await self .pythd .connect ()
68
67
69
- self ._product_update_task = asyncio .create_task (
70
- self ._start_product_update_loop ()
71
- )
72
-
73
- async def _start_product_update_loop (self ):
74
68
await self ._upd_products ()
69
+
70
+ self ._product_update_task = asyncio .create_task (self ._product_update_loop ())
71
+ self ._price_update_task = asyncio .create_task (self ._price_update_loop ())
72
+
75
73
self .provider .start ()
76
74
75
+ async def _product_update_loop (self ):
77
76
while True :
78
- await self ._upd_products ()
79
- await self ._subscribe_notify_price_sched ()
80
77
await asyncio .sleep (self .config .product_update_interval_secs )
78
+ await self ._upd_products ()
81
79
82
80
async def _upd_products (self ):
83
81
log .debug ("fetching product accounts from Pythd" )
@@ -114,58 +112,51 @@ async def _upd_products(self):
114
112
115
113
self .provider .upd_products ([product .symbol for product in self .products ])
116
114
117
- async def _subscribe_notify_price_sched (self ):
118
- # Subscribe to Pythd's notify_price_sched for each product that
119
- # is not subscribed yet. Unfortunately there is no way to unsubscribe
120
- # to the prices that are no longer available.
121
- log .debug ("subscribing to notify_price_sched" )
122
-
123
- subscriptions = {}
124
- for product in self .products :
125
- if not product .subscription_id :
126
- subscription_id = await self .pythd .subscribe_price_sched (
127
- product .price_account
115
+ async def _price_update_loop (self ):
116
+ while True :
117
+ price_updates = []
118
+ for product in self .products :
119
+ price = self .provider .latest_price (product .symbol )
120
+ if not price :
121
+ log .info ("latest price not available" , symbol = product .symbol )
122
+ continue
123
+
124
+ scaled_price = self .apply_exponent (price .price , product .exponent )
125
+ scaled_conf = self .apply_exponent (price .conf , product .exponent )
126
+
127
+ price_updates .append (
128
+ PriceUpdate (
129
+ account = product .price_account ,
130
+ price = scaled_price ,
131
+ conf = scaled_conf ,
132
+ status = TRADING ,
133
+ )
134
+ )
135
+ log .debug (
136
+ "sending price update" ,
137
+ symbol = product .symbol ,
138
+ price_account = product .price_account ,
139
+ price = price .price ,
140
+ conf = price .conf ,
141
+ scaled_price = scaled_price ,
142
+ scaled_conf = scaled_conf ,
128
143
)
129
- product .subscription_id = subscription_id
130
-
131
- subscriptions [product .subscription_id ] = product
132
-
133
- self .subscriptions = subscriptions
134
-
135
- async def on_notify_price_sched (self , subscription : int ) -> None :
136
144
137
- log .debug ("received notify_price_sched" , subscription = subscription )
138
- if subscription not in self .subscriptions :
139
- return
145
+ self .last_successful_update = (
146
+ price .timestamp
147
+ if self .last_successful_update is None
148
+ else max (self .last_successful_update , price .timestamp )
149
+ )
140
150
141
- # Look up the current price and confidence interval of the product
142
- product = self .subscriptions [subscription ]
143
- price = self .provider .latest_price (product .symbol )
144
- if not price :
145
- log .info ("latest price not available" , symbol = product .symbol )
146
- return
151
+ log .info (
152
+ "sending batch update_price" ,
153
+ num_price_updates = len (price_updates ),
154
+ total_products = len (self .products ),
155
+ )
147
156
148
- # Scale the price and confidence interval using the Pyth exponent
149
- scaled_price = self .apply_exponent (price .price , product .exponent )
150
- scaled_conf = self .apply_exponent (price .conf , product .exponent )
157
+ await self .pythd .update_price_batch (price_updates )
151
158
152
- # Send the price update
153
- log .info (
154
- "sending update_price" ,
155
- product_account = product .product_account ,
156
- price_account = product .price_account ,
157
- price = scaled_price ,
158
- conf = scaled_conf ,
159
- symbol = product .symbol ,
160
- )
161
- await self .pythd .update_price (
162
- product .price_account , scaled_price , scaled_conf , TRADING
163
- )
164
- self .last_successful_update = (
165
- price .timestamp
166
- if self .last_successful_update is None
167
- else max (self .last_successful_update , price .timestamp )
168
- )
159
+ await asyncio .sleep (self .config .price_update_interval_secs )
169
160
170
161
def apply_exponent (self , x : float , exp : int ) -> int :
171
162
return int (x * (10 ** (- exp )))
0 commit comments