Skip to content

Commit c3ffe52

Browse files
committed
continue refactoring tools (incomplete)
1 parent c83559d commit c3ffe52

File tree

14 files changed

+1386
-1005
lines changed

14 files changed

+1386
-1005
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,5 @@ pnpm-debug.log*
151151

152152
# Agents
153153
agents/
154+
.codex/
155+
.codex-cache/

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ A portfolio management, analytics, and global tracking platform with SQLite-back
5353
- Global flight and maritime tracking (OpenSky-only)
5454
- Intel and news aggregation with filters
5555
- Diagnostics + system health views
56+
- Feed registry with health summary (CLI + API + UI)
5657
- Reports and exports (CLI + web)
5758
- Web API + WebSocket streaming trackers
5859

interfaces/settings.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from interfaces.menu_layout import build_sidebar, build_status_header, compact_for_width
1919
from interfaces.navigator import Navigator
2020
from modules.client_store import DbClientStore
21+
from modules.market_data.registry import build_feed_registry, summarize_feed_registry
2122

2223
class SettingsModule:
2324
def __init__(self):
@@ -1051,7 +1052,67 @@ def _run_deep_diagnostics(self):
10511052
mem_bar = Text("N/A")
10521053
table.add_row("Memory Load", sys_info['mem_usage'], mem_bar)
10531054

1054-
self.console.print(table)
1055+
feed_registry = build_feed_registry()
1056+
feed_summary = summarize_feed_registry(feed_registry)
1057+
health_counts = feed_summary.get("health_counts", {})
1058+
health_line = (
1059+
f"ok {health_counts.get('ok', 0)} | "
1060+
f"degraded {health_counts.get('degraded', 0)} | "
1061+
f"backoff {health_counts.get('backoff', 0)} | "
1062+
f"unknown {health_counts.get('unknown', 0)}"
1063+
)
1064+
1065+
feed_summary_table = Table(box=box.SIMPLE, show_header=False)
1066+
feed_summary_table.add_column("Metric", style="dim", width=16)
1067+
feed_summary_table.add_column("Value", style="white")
1068+
feed_summary_table.add_row(
1069+
"Sources",
1070+
f"{feed_summary.get('configured', 0)}/{feed_summary.get('total', 0)}",
1071+
)
1072+
feed_summary_table.add_row("Unconfigured", str(feed_summary.get("unconfigured", 0)))
1073+
feed_summary_table.add_row("Health", health_line)
1074+
1075+
category_panel = None
1076+
categories = feed_summary.get("categories", {}) or {}
1077+
if categories:
1078+
category_table = Table(box=box.SIMPLE, show_header=True)
1079+
category_table.add_column("Category", style="bold cyan")
1080+
category_table.add_column("Configured", justify="right")
1081+
category_table.add_column("Total", justify="right")
1082+
for name in sorted(categories.keys()):
1083+
stats = categories.get(name, {})
1084+
category_table.add_row(
1085+
name.title(),
1086+
str(stats.get("configured", 0)),
1087+
str(stats.get("total", 0)),
1088+
)
1089+
category_panel = Panel(
1090+
category_table,
1091+
title="Feed Categories",
1092+
border_style="cyan",
1093+
box=box.SIMPLE,
1094+
)
1095+
1096+
warnings_panel = None
1097+
warnings = feed_summary.get("warnings") or []
1098+
if warnings:
1099+
warning_text = "\n".join(f"- {warning}" for warning in warnings)
1100+
warnings_panel = Panel(
1101+
Text(warning_text, style="yellow"),
1102+
title="Feed Warnings",
1103+
border_style="yellow",
1104+
box=box.SIMPLE,
1105+
)
1106+
1107+
panels = [
1108+
table,
1109+
Panel(feed_summary_table, title="Feed Registry", border_style="cyan", box=box.SIMPLE),
1110+
]
1111+
if category_panel:
1112+
panels.append(category_panel)
1113+
if warnings_panel:
1114+
panels.append(warnings_panel)
1115+
self.console.print(Group(*panels))
10551116
InputSafe.pause()
10561117

10571118
def _duplicate_accounts_summary(self):

modules/client_mgr/calculations.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,40 +132,40 @@ def permutation_entropy(values: List[float], order: int = 3, delay: int = 1) ->
132132

133133

134134
def hurst_exponent(values: List[float]) -> float:
135-
if not values or len(values) < 20:
135+
if not values or len(values) < 100:
136136
return 0.5
137-
137+
138138
series = np.array(values, dtype=float)
139139
n_min = 10
140140
n_max = len(series) // 2
141-
lags = range(n_min, n_max)
142-
141+
lags_used = []
143142
rs_values = []
144-
for lag in lags:
145-
# Create sub-series of length `lag`
143+
for lag in range(n_min, n_max):
146144
sub_series_count = len(series) // lag
147145
if sub_series_count == 0:
148146
continue
149-
150147
rs_sub_values = []
151148
for i in range(sub_series_count):
152-
sub_series = series[i*lag : (i+1)*lag]
149+
sub_series = series[i * lag : (i + 1) * lag]
153150
mean = np.mean(sub_series)
154151
deviates = sub_series - mean
155152
cumulative_deviates = np.cumsum(deviates)
156153
r = np.max(cumulative_deviates) - np.min(cumulative_deviates)
157154
s = np.std(sub_series)
158155
if s > 0:
159156
rs_sub_values.append(r / s)
160-
161157
if rs_sub_values:
162158
rs_values.append(np.mean(rs_sub_values))
159+
lags_used.append(lag)
163160

164-
if not rs_values:
161+
if len(rs_values) < 2:
165162
return 0.5
166163

167-
poly = np.polyfit(np.log(lags[:len(rs_values)]), np.log(rs_values), 1)
168-
return float(poly[0])
164+
slope = np.polyfit(np.log(lags_used), np.log(rs_values), 1)[0]
165+
hurst = float(slope - 0.06)
166+
if math.isnan(hurst) or math.isinf(hurst):
167+
return 0.5
168+
return max(0.0, min(1.0, hurst))
169169

170170

171171
def fft_spectrum(values: List[float], top_n: int = 6) -> List[Tuple[float, float]]:

0 commit comments

Comments
 (0)