Skip to content

Commit 5e2195e

Browse files
committed
feat(plot): xstrk/strk feed analysis
1 parent db6e91e commit 5e2195e

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

pragma-sdk/plot_xstrk_feed.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# /// script
2+
# requires-python = ">=3.11"
3+
# dependencies = [
4+
# "pragma-sdk",
5+
# "matplotlib",
6+
# ]
7+
# ///
8+
"""
9+
Script to plot CONVERSION_XSTRK/USD, STRK/USD, and CONVERSION_XSTRK/STRK feed data
10+
over the last 6 hours (21600 blocks).
11+
"""
12+
13+
import asyncio
14+
from datetime import datetime
15+
16+
import matplotlib.pyplot as plt
17+
from pragma_sdk.common.types.types import AggregationMode
18+
from pragma_sdk.onchain.client import PragmaOnChainClient
19+
20+
PAIRS = [
21+
"CONVERSION_XSTRK/USD",
22+
"STRK/USD",
23+
]
24+
25+
26+
async def fetch_pair_data(client, pair_id: str, blocks: list[int]) -> dict:
27+
"""Fetch price data for a single pair across multiple blocks."""
28+
prices = []
29+
timestamps = []
30+
valid_blocks = []
31+
32+
print(f"\nFetching {pair_id}...")
33+
34+
for i, block in enumerate(blocks):
35+
try:
36+
response = await client.get_spot(
37+
pair_id=pair_id,
38+
aggregation_mode=AggregationMode.MEDIAN,
39+
block_id=block,
40+
)
41+
price = response.price / (10**response.decimals)
42+
prices.append(price)
43+
timestamps.append(response.last_updated_timestamp)
44+
valid_blocks.append(block)
45+
46+
if (i + 1) % 20 == 0:
47+
print(f" {pair_id}: {i + 1}/{len(blocks)} data points...")
48+
49+
except Exception as e:
50+
print(f" Error fetching {pair_id} at block {block}: {e}")
51+
continue
52+
53+
return {
54+
"pair_id": pair_id,
55+
"blocks": valid_blocks,
56+
"prices": prices,
57+
"timestamps": timestamps,
58+
}
59+
60+
61+
async def fetch_all_data():
62+
client = PragmaOnChainClient(network="mainnet")
63+
64+
current_block = await client.get_block_number()
65+
print(f"Current block: {current_block}")
66+
67+
# Fetch data for the last 20000 blocks (~5.5 hours with 1 sec block time)
68+
num_blocks = 20000
69+
start_block = current_block - num_blocks
70+
71+
# Sample every 100 blocks (~1.6 min intervals) = 200 data points
72+
step = 100
73+
blocks = list(range(start_block, current_block + 1, step))
74+
75+
print(f"Fetching data from block {start_block} to {current_block}")
76+
print(f"Data points per pair: {len(blocks)}")
77+
78+
results = {}
79+
for pair_id in PAIRS:
80+
data = await fetch_pair_data(client, pair_id, blocks)
81+
results[pair_id] = data
82+
83+
# Compute CONVERSION_XSTRK/STRK by dividing CONVERSION_XSTRK/USD by STRK/USD
84+
xstrk_usd = results["CONVERSION_XSTRK/USD"]
85+
strk_usd = results["STRK/USD"]
86+
87+
ratio_prices = []
88+
ratio_timestamps = []
89+
ratio_blocks = []
90+
91+
for i, block in enumerate(xstrk_usd["blocks"]):
92+
if block in strk_usd["blocks"]:
93+
j = strk_usd["blocks"].index(block)
94+
if strk_usd["prices"][j] > 0:
95+
ratio = xstrk_usd["prices"][i] / strk_usd["prices"][j]
96+
ratio_prices.append(ratio)
97+
ratio_timestamps.append(xstrk_usd["timestamps"][i])
98+
ratio_blocks.append(block)
99+
100+
results["CONVERSION_XSTRK/STRK"] = {
101+
"pair_id": "CONVERSION_XSTRK/STRK",
102+
"blocks": ratio_blocks,
103+
"prices": ratio_prices,
104+
"timestamps": ratio_timestamps,
105+
}
106+
107+
return results
108+
109+
110+
def plot_data(results: dict):
111+
fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True)
112+
113+
colors = {
114+
"CONVERSION_XSTRK/USD": "blue",
115+
"STRK/USD": "green",
116+
"CONVERSION_XSTRK/STRK": "purple",
117+
}
118+
119+
all_pairs = PAIRS + ["CONVERSION_XSTRK/STRK"]
120+
121+
for ax, pair_id in zip(axes, all_pairs):
122+
data = results[pair_id]
123+
if not data["prices"]:
124+
continue
125+
126+
datetimes = [datetime.fromtimestamp(ts) for ts in data["timestamps"]]
127+
color = colors[pair_id]
128+
129+
ax.plot(
130+
datetimes,
131+
data["prices"],
132+
"-",
133+
linewidth=1.5,
134+
marker="o",
135+
markersize=3,
136+
color=color,
137+
)
138+
ax.set_ylabel("Price")
139+
ax.set_title(pair_id)
140+
ax.grid(True, alpha=0.3)
141+
142+
if data["prices"]:
143+
ax.legend(
144+
[f"Range: {min(data['prices']):.6f} - {max(data['prices']):.6f}"],
145+
loc="upper right",
146+
)
147+
148+
axes[-1].set_xlabel("Time")
149+
plt.xticks(rotation=45)
150+
plt.tight_layout()
151+
152+
output_path = "xstrk_feeds.png"
153+
plt.savefig(output_path, dpi=150)
154+
print(f"\nPlot saved to {output_path}")
155+
156+
plt.show()
157+
158+
159+
async def main():
160+
results = await fetch_all_data()
161+
162+
for pair_id, data in results.items():
163+
if data["prices"]:
164+
print(
165+
f"\n{pair_id}: {len(data['prices'])} points, range: {min(data['prices']):.6f} - {max(data['prices']):.6f}"
166+
)
167+
168+
plot_data(results)
169+
170+
171+
if __name__ == "__main__":
172+
asyncio.run(main())

0 commit comments

Comments
 (0)