Skip to content

Commit e980229

Browse files
committed
fix: Update example 04 to correctly display real-time data stats
- Fixed system status display to use correct validation fields (is_running, ticks_processed) - Updated memory stats to use correct keys (total_bars_stored, quotes_processed, trades_processed) - Improved current prices display with better formatting and live price indicator - Fixed memory stats breakdown to directly access data manager timeframes - Removed unused imports and variables - Real-time data now correctly shows tick/quote/trade processing counts
1 parent eaa8f19 commit e980229

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

examples/04_realtime_data.py

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
TradingSuite,
3535
setup_logging,
3636
)
37-
from project_x_py.types.protocols import RealtimeDataManagerProtocol
3837

3938
if TYPE_CHECKING:
4039
from project_x_py.realtime_data_manager import RealtimeDataManager
@@ -46,16 +45,18 @@ async def display_current_prices(data_manager: "RealtimeDataManager") -> None:
4645

4746
current_price = await data_manager.get_current_price()
4847
if current_price:
49-
print(f" Current Price: ${current_price:.2f}")
48+
print(f" Live Price: ${current_price:.2f}")
5049
else:
51-
print(" Current Price: Not available")
50+
print(" Live Price: Not available")
5251

53-
# Get multi-timeframe data asynchronously - get 1 bar from each timeframe
52+
# Get multi-timeframe data asynchronously - get latest bars
5453
timeframes = ["15sec", "1min", "5min", "15min", "1hr"]
5554
mtf_tasks: list[Coroutine[Any, Any, pl.DataFrame | None]] = []
5655

5756
for tf in timeframes:
58-
mtf_tasks.append(data_manager.get_data(tf, bars=1))
57+
mtf_tasks.append(
58+
data_manager.get_data(tf)
59+
) # Get all data, we'll take the last bar
5960

6061
# Get data from all timeframes concurrently
6162
mtf_results = await asyncio.gather(*mtf_tasks, return_exceptions=True)
@@ -70,19 +71,26 @@ async def display_current_prices(data_manager: "RealtimeDataManager") -> None:
7071
continue
7172

7273
if data.is_empty():
73-
print(f" {timeframe:>6}: No data")
74+
print(f" {timeframe:>6}: Building bars...")
7475
continue
7576

77+
# Get the last complete bar
7678
latest_bar = data.tail(1)
7779
for row in latest_bar.iter_rows(named=True):
7880
timestamp = row["timestamp"]
7981
close = row["close"]
8082
volume = row["volume"]
83+
# Format timestamp more concisely
84+
time_str = (
85+
timestamp.strftime("%H:%M:%S")
86+
if hasattr(timestamp, "strftime")
87+
else str(timestamp)
88+
)
8189
print(
82-
f" {timeframe:>6}: ${close:8.2f} @ {timestamp} (Vol: {volume:,})"
90+
f" {timeframe:>6}: ${close:8.2f} @ {time_str} (Vol: {volume:,})"
8391
)
8492
else:
85-
print(f" {timeframe:>6}: No data")
93+
print(f" {timeframe:>6}: Initializing...")
8694

8795

8896
async def display_memory_stats(data_manager: "RealtimeDataManager") -> None:
@@ -91,17 +99,28 @@ async def display_memory_stats(data_manager: "RealtimeDataManager") -> None:
9199
# get_memory_stats is synchronous in async data manager
92100
stats = data_manager.get_memory_stats()
93101
print("\n💾 Memory Statistics:")
94-
print(f" Total Bars: {stats.get('total_bars', 0):,}")
102+
print(f" Total Bars Stored: {stats.get('total_bars_stored', 0):,}")
95103
print(f" Ticks Processed: {stats.get('ticks_processed', 0):,}")
96-
print(f" Bars Cleaned: {stats.get('bars_cleaned', 0):,}")
97-
print(f" Tick Buffer Size: {stats.get('tick_buffer_size', 0):,}")
98-
99-
# Show per-timeframe breakdown
100-
breakdown = stats.get("timeframe_breakdown", {})
101-
if breakdown:
102-
print(" Timeframe Breakdown:")
103-
for tf, count in breakdown.items():
104-
print(f" {tf}: {count:,} bars")
104+
print(f" Quotes Processed: {stats.get('quotes_processed', 0):,}")
105+
print(f" Trades Processed: {stats.get('trades_processed', 0):,}")
106+
107+
# Show per-timeframe breakdown (Note: this key doesn't exist in current implementation)
108+
# Will need to calculate it manually from the data
109+
print(" Bars per Timeframe:")
110+
for tf in data_manager.timeframes:
111+
if tf in data_manager.data:
112+
count = len(data_manager.data[tf])
113+
if count > 0:
114+
print(f" {tf}: {count:,} bars")
115+
116+
# Also show validation status for more insight
117+
validation = data_manager.get_realtime_validation_status()
118+
if validation.get("is_running"):
119+
print(
120+
f" Feed Active: ✅ (Processing {validation.get('instrument', 'N/A')})"
121+
)
122+
else:
123+
print(" Feed Active: ❌")
105124

106125
except Exception as e:
107126
print(f" ❌ Memory stats error: {e}")
@@ -113,11 +132,11 @@ async def display_system_statistics(data_manager: "RealtimeDataManager") -> None
113132
# Use validation status instead of get_statistics (which doesn't exist)
114133
stats = data_manager.get_realtime_validation_status()
115134
print("\n📈 System Status:")
116-
print(f" Instrument: {getattr(data_manager, 'instrument', 'Unknown')}")
117-
print(f" Contract ID: {getattr(data_manager, 'contract_id', 'Unknown')}")
118-
print(f" Real-time Enabled: {stats.get('realtime_enabled', False)}")
119-
print(f" Connection Valid: {stats.get('connection_valid', False)}")
120-
print(f" Data Valid: {stats.get('data_valid', False)}")
135+
print(f" Instrument: {stats.get('instrument', 'Unknown')}")
136+
print(f" Contract ID: {stats.get('contract_id', 'Unknown')}")
137+
print(f" Real-time Feed Active: {stats.get('is_running', False)}")
138+
print(f" Ticks Processed: {stats.get('ticks_processed', 0):,}")
139+
print(f" Bars Cleaned: {stats.get('bars_cleaned', 0):,}")
121140

122141
# Show data status per timeframe
123142
print(" Timeframe Status:")
@@ -224,7 +243,6 @@ async def main() -> bool:
224243

225244
# Components are now accessed as attributes
226245
data_manager = suite.data
227-
realtime_client = suite.realtime
228246

229247
print("\n✅ All components connected and subscribed:")
230248
print(" - Real-time client connected")

0 commit comments

Comments
 (0)