5eb3dec24b
- Add a /health ops page: snapshot freshness (last-capture-at, colour-coded), 24h vs total snapshots + anomalies, events tracked, sports covered, and the four worker on/off states. Nav entry under System; localized en+ru. - New IPipelineHealthService + ISnapshotRepository.GetLatestCapturedAtAsync (max CapturedAt via indexed ORDER BY/LIMIT 1), with a real-SQLite round-trip test.
513 lines
37 KiB
XML
513 lines
37 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<root>
|
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
<xsd:element name="root" msdata:IsDataSet="true">
|
|
<xsd:complexType>
|
|
<xsd:choice maxOccurs="unbounded">
|
|
<xsd:element name="metadata">
|
|
<xsd:complexType>
|
|
<xsd:sequence>
|
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
</xsd:sequence>
|
|
<xsd:attribute name="name" type="xsd:string" />
|
|
<xsd:attribute name="type" type="xsd:string" />
|
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
<xsd:attribute ref="xml:space" />
|
|
</xsd:complexType>
|
|
</xsd:element>
|
|
<xsd:element name="assembly">
|
|
<xsd:complexType>
|
|
<xsd:attribute name="alias" type="xsd:string" />
|
|
<xsd:attribute name="name" type="xsd:string" />
|
|
</xsd:complexType>
|
|
</xsd:element>
|
|
<xsd:element name="data">
|
|
<xsd:complexType>
|
|
<xsd:sequence>
|
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
</xsd:sequence>
|
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
<xsd:attribute name="type" type="xsd:string" />
|
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
<xsd:attribute ref="xml:space" />
|
|
</xsd:complexType>
|
|
</xsd:element>
|
|
<xsd:element name="resheader">
|
|
<xsd:complexType>
|
|
<xsd:sequence>
|
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
</xsd:sequence>
|
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
</xsd:complexType>
|
|
</xsd:element>
|
|
</xsd:choice>
|
|
</xsd:complexType>
|
|
</xsd:element>
|
|
</xsd:schema>
|
|
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
|
|
<resheader name="version"><value>2.0</value></resheader>
|
|
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
|
|
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
|
|
|
|
<data name="App.Title"><value>Marathon Odds Lab</value></data>
|
|
<data name="App.Tagline"><value>Odds analytics for marathonbet.by</value></data>
|
|
<data name="App.BrandMark"><value>Marathon</value></data>
|
|
<data name="App.Dateline"><value>Odds Laboratory</value></data>
|
|
|
|
<data name="Nav.Section.Analysis"><value>Analysis</value></data>
|
|
<data name="Nav.Section.System"><value>System</value></data>
|
|
<data name="Nav.Dashboard"><value>Dashboard</value></data>
|
|
<data name="Nav.PreMatch"><value>Pre-match</value></data>
|
|
<data name="Nav.Live"><value>Live</value></data>
|
|
<data name="Nav.Anomalies"><value>Anomalies</value></data>
|
|
<data name="Nav.Results"><value>Results</value></data>
|
|
<data name="Nav.Settings"><value>Settings</value></data>
|
|
<data name="Nav.Export"><value>Export</value></data>
|
|
<data name="Nav.Health"><value>Health</value></data>
|
|
|
|
<data name="Home.Kicker"><value>Briefing</value></data>
|
|
<data name="Home.Title"><value>Hunting odds-flip anomalies</value></data>
|
|
<data name="Home.Lede"><value>We snapshot marathonbet.by lines on a schedule, watch for favorite-underdog reversals, and keep evidence for every anomaly.</value></data>
|
|
<data name="Home.Stat.Events"><value>Events tracked</value></data>
|
|
<data name="Home.Stat.Snapshots"><value>Snapshots today</value></data>
|
|
<data name="Home.Stat.Anomalies"><value>Anomalies flagged</value></data>
|
|
<data name="Home.Stat.Coverage"><value>Sports covered</value></data>
|
|
<data name="Home.Section.Latest"><value>Latest signals</value></data>
|
|
<data name="Home.Section.Pipeline"><value>Capture pipeline</value></data>
|
|
<data name="Home.Pipeline.Step1"><value>Schedule capture (`/su`)</value></data>
|
|
<data name="Home.Pipeline.Step2"><value>Odds snapshot</value></data>
|
|
<data name="Home.Pipeline.Step3"><value>Flip detector</value></data>
|
|
<data name="Home.Pipeline.Step4"><value>XLSX export</value></data>
|
|
<data name="Home.Empty"><value>No data yet. Enable the background pollers in Settings to start the feed.</value></data>
|
|
<data name="Home.Empty.Heading"><value>Nothing captured yet</value></data>
|
|
<data name="Home.Empty.Cta"><value>Open Settings</value></data>
|
|
<data name="Home.NoSignals"><value>Capturing lines — no flips flagged yet.</value></data>
|
|
<data name="Home.ViewAll"><value>View all signals</value></data>
|
|
<data name="Home.Stat.NewToday"><value>{0} new today</value></data>
|
|
<data name="Scraping.On"><value>Capturing</value></data>
|
|
<data name="Scraping.Off"><value>Paused</value></data>
|
|
<data name="Scraping.Aria"><value>Data capture status</value></data>
|
|
|
|
<data name="Settings.Kicker"><value>Configuration</value></data>
|
|
<data name="Settings.Title"><value>Settings</value></data>
|
|
<data name="Settings.Lede"><value>Every scraper, storage, detector, and locale parameter. Changes are written to appsettings.Local.json and applied live.</value></data>
|
|
<data name="Settings.Section.Scraping"><value>Scraping</value></data>
|
|
<data name="Settings.Section.Workers"><value>Background workers</value></data>
|
|
<data name="Settings.Section.Storage"><value>Storage</value></data>
|
|
<data name="Settings.Section.Anomaly"><value>Anomaly detector</value></data>
|
|
<data name="Settings.Section.Localization"><value>Localization</value></data>
|
|
<data name="Settings.Action.Reset"><value>Reset section</value></data>
|
|
<data name="Settings.Action.Save"><value>Save</value></data>
|
|
<data name="Settings.Action.SaveAll"><value>Save all</value></data>
|
|
<data name="Settings.Confirm.Title"><value>Confirm changes</value></data>
|
|
<data name="Settings.Confirm.Body"><value>Settings will be written to appsettings.Local.json and re-read by services. Continue?</value></data>
|
|
<data name="Settings.Saved"><value>Settings saved.</value></data>
|
|
<data name="Settings.SaveFailed"><value>Failed to save settings.</value></data>
|
|
|
|
<data name="Settings.Scraping.PollingIntervalSeconds"><value>Polling interval (sec)</value></data>
|
|
<data name="Settings.Scraping.PollingIntervalSeconds.Hint"><value>How often to refresh the schedule. Minimum 5 seconds.</value></data>
|
|
<data name="Settings.Scraping.MaxConcurrentRequests"><value>Concurrent requests</value></data>
|
|
<data name="Settings.Scraping.MaxConcurrentRequests.Hint"><value>Cap at 8 to avoid throttling.</value></data>
|
|
<data name="Settings.Scraping.UserAgents"><value>User-Agent pool</value></data>
|
|
<data name="Settings.Scraping.UserAgents.Hint"><value>One UA per line. Rotated per request.</value></data>
|
|
<data name="Settings.Scraping.RetryMaxAttempts"><value>Retry attempts</value></data>
|
|
<data name="Settings.Scraping.RetryBaseDelayMs"><value>Base delay (ms)</value></data>
|
|
<data name="Settings.Scraping.RateLimitRps"><value>Rate limit (RPS)</value></data>
|
|
<data name="Settings.Scraping.RateLimitRps.Hint"><value>Requests per second. 1 is recommended.</value></data>
|
|
<data name="Settings.Scraping.BaseUrl"><value>Base URL</value></data>
|
|
<data name="Settings.Scraping.BaseUrl.Hint"><value>Must be an absolute http(s) URL, e.g. https://www.marathonbet.by</value></data>
|
|
<data name="Settings.Scraping.BaseUrl.Invalid"><value>Base URL must be an absolute http(s) address.</value></data>
|
|
<data name="Settings.Workers.Cron.Invalid"><value>Schedule must be a 5- or 6-field cron expression.</value></data>
|
|
<data name="Settings.Scraping.RequestTimeoutSeconds"><value>Request timeout (sec)</value></data>
|
|
<data name="Settings.Scraping.UsePlaywright"><value>Use Playwright</value></data>
|
|
|
|
<data name="Settings.Workers.UpcomingScheduleCron"><value>Schedule cron (UPCOMING)</value></data>
|
|
<data name="Settings.Workers.UpcomingScheduleCron.Hint"><value>Standard cron. Defaults to every 5 minutes.</value></data>
|
|
<data name="Settings.Workers.LivePollerEnabled"><value>Live poller enabled</value></data>
|
|
<data name="Settings.Workers.UpcomingPollerEnabled"><value>Schedule poller enabled</value></data>
|
|
<data name="Settings.Workers.LivePollIntervalSeconds"><value>Live poll interval (sec)</value></data>
|
|
<data name="Settings.Workers.LivePollIntervalSeconds.Hint"><value>Delay between live-odds polling cycles. Default 30 s.</value></data>
|
|
<data name="Settings.Workers.ResultsPollerEnabled"><value>Results poller enabled</value></data>
|
|
<data name="Settings.Workers.ResultsPollerEnabled.Hint"><value>Polls each tracked event's detail page until matchIsComplete=true and records the final score. Safe to enable.</value></data>
|
|
<data name="Settings.Workers.ResultsPollIntervalSeconds"><value>Results poll interval (sec)</value></data>
|
|
<data name="Settings.Workers.AnomalyDetectionEnabled"><value>Anomaly detection enabled</value></data>
|
|
<data name="Settings.Workers.AnomalyDetectionEnabled.Hint"><value>Runs the suspension-flip detector on every cycle. Disable to pause analysis without losing collected snapshots.</value></data>
|
|
|
|
<data name="Settings.Storage.DatabasePath"><value>SQLite path</value></data>
|
|
<data name="Settings.Storage.ExportDirectory"><value>Export directory</value></data>
|
|
<data name="Settings.Storage.SnapshotRetentionDays"><value>Snapshot retention (days)</value></data>
|
|
<data name="Settings.Storage.Validation.DatabasePathRequired"><value>SQLite path is required.</value></data>
|
|
<data name="Settings.Storage.Validation.ExportDirectoryRequired"><value>Export directory is required.</value></data>
|
|
<data name="Settings.Storage.Validation.DatabasePathInvalid"><value>SQLite path must stay inside the application directory and may not contain "..".</value></data>
|
|
<data name="Settings.Storage.Validation.ExportDirectoryInvalid"><value>Export directory must stay inside the application directory and may not contain "..".</value></data>
|
|
|
|
<data name="Settings.Anomaly.SuspensionGapSeconds"><value>Suspension window (sec)</value></data>
|
|
<data name="Settings.Anomaly.OddsFlipThreshold"><value>Flip threshold (Δ probability)</value></data>
|
|
<data name="Settings.Anomaly.MinSnapshotCount"><value>Min snapshot count</value></data>
|
|
<data name="Settings.Anomaly.DetectionIntervalSeconds"><value>Detection interval (sec)</value></data>
|
|
|
|
<data name="Settings.Localization.DefaultCulture"><value>Default UI language</value></data>
|
|
|
|
<data name="Locale.Russian"><value>RU</value></data>
|
|
<data name="Locale.English"><value>EN</value></data>
|
|
<data name="Locale.Tooltip.Switch"><value>Switch language</value></data>
|
|
|
|
<data name="Theme.Toggle.Light"><value>Light theme</value></data>
|
|
<data name="Theme.Toggle.Dark"><value>Dark theme</value></data>
|
|
|
|
<data name="Common.Save"><value>Save</value></data>
|
|
<data name="Common.Cancel"><value>Cancel</value></data>
|
|
<data name="Common.Reset"><value>Reset</value></data>
|
|
<data name="Common.Loading"><value>Loading…</value></data>
|
|
<data name="Common.Empty"><value>No data</value></data>
|
|
<data name="Common.Yes"><value>Yes</value></data>
|
|
<data name="Common.No"><value>No</value></data>
|
|
|
|
<data name="Anomaly.Live"><value>Anomaly</value></data>
|
|
<data name="Anomaly.Kind.SuspensionFlip"><value>Suspension flip</value></data>
|
|
<data name="Anomaly.Kind.SteamMove"><value>Steam move</value></data>
|
|
<data name="Anomaly.Kind.SuspensionFreeze"><value>Suspension freeze</value></data>
|
|
<data name="Anomaly.Score"><value>Confidence</value></data>
|
|
|
|
<!-- Phase 7 — Anomaly feed UI -->
|
|
<data name="Anomaly.Title"><value>Anomaly feed</value></data>
|
|
<data name="Anomaly.Lede"><value>Real-time signal log of suspension-flip events. The detector runs every cycle, computes implied probabilities before and after each market freeze, and surfaces flips ranked by confidence.</value></data>
|
|
<data name="Anomaly.Severity.Low"><value>Low</value></data>
|
|
<data name="Anomaly.Severity.Medium"><value>Medium</value></data>
|
|
<data name="Anomaly.Severity.High"><value>High</value></data>
|
|
<data name="Anomaly.Filter.AnySeverity"><value>Any</value></data>
|
|
<data name="Anomaly.Filter.Severity"><value>Min severity</value></data>
|
|
<data name="Anomaly.Filter.Sport"><value>Sport</value></data>
|
|
<data name="Anomaly.Filter.From"><value>Detected from</value></data>
|
|
<data name="Anomaly.Filter.To"><value>Detected to</value></data>
|
|
<data name="Anomaly.Filter.DateRange"><value>Date range</value></data>
|
|
<data name="Anomaly.Filter.MarkRead"><value>Mark all read</value></data>
|
|
<data name="Anomaly.Card.DetectedAt"><value>Detected</value></data>
|
|
<data name="Anomaly.Card.Score"><value>Confidence</value></data>
|
|
<data name="Anomaly.Card.Kind"><value>Kind</value></data>
|
|
<data name="Anomaly.Card.GapSeconds"><value>Suspension gap</value></data>
|
|
<data name="Anomaly.Evidence.Pre"><value>Before suspension</value></data>
|
|
<data name="Anomaly.Evidence.Post"><value>After suspension</value></data>
|
|
<data name="Anomaly.Evidence.Probability"><value>Implied prob.</value></data>
|
|
<data name="Anomaly.Evidence.Rate"><value>Rate</value></data>
|
|
<data name="Anomaly.Evidence.SuspensionDuration"><value>Suspension duration</value></data>
|
|
<data name="Anomaly.Evidence.FavouriteSwap"><value>Favourite swap</value></data>
|
|
<data name="Anomaly.Detail.EvidenceTitle"><value>Evidence timeline</value></data>
|
|
<data name="Anomaly.Detail.LinkBackToEvent"><value>Open event</value></data>
|
|
<data name="Action.LogBet"><value>Log bet</value></data>
|
|
<data name="Anomaly.Detail.BackToFeed"><value>Back to feed</value></data>
|
|
<data name="Anomaly.Detail.NotFound"><value>Anomaly not found — it may have been pruned.</value></data>
|
|
<data name="Anomaly.Empty.NoneInRange"><value>No anomalies match the current filters. Loosen the severity threshold or widen the date range.</value></data>
|
|
<data name="Anomaly.Stat.Total"><value>Total</value></data>
|
|
<data name="Anomaly.Nav.UnreadAria"><value>Unread anomalies</value></data>
|
|
|
|
<!-- Phase 6 — Pre-match list / Live list / Detail / Export -->
|
|
<data name="PreMatch.Title"><value>Pre-match schedule</value></data>
|
|
<data name="PreMatch.Lede"><value>Upcoming events with their latest pre-match Win-1 / Draw / Win-2 odds preview. Filter by sport, country, league, or team.</value></data>
|
|
<data name="PreMatch.Empty"><value>No events match the current filters. Loosen the date range or clear the chips above.</value></data>
|
|
<data name="PreMatch.Filter.Toolbar"><value>Filter toolbar</value></data>
|
|
<data name="PreMatch.Filter.From"><value>From</value></data>
|
|
<data name="PreMatch.Filter.To"><value>To</value></data>
|
|
<data name="PreMatch.Filter.Sport"><value>Sports</value></data>
|
|
<data name="PreMatch.Filter.Country"><value>Countries</value></data>
|
|
<data name="PreMatch.Filter.Search"><value>Search league or team</value></data>
|
|
<data name="PreMatch.Filter.Search.Placeholder"><value>e.g. Real Madrid, NBA, Roland Garros…</value></data>
|
|
<data name="PreMatch.Column.Time"><value>Time</value></data>
|
|
<data name="PreMatch.Column.Country"><value>Country</value></data>
|
|
<data name="PreMatch.Column.League"><value>League</value></data>
|
|
<data name="PreMatch.Column.Match"><value>Match</value></data>
|
|
<data name="PreMatch.Footer.Events"><value>events</value></data>
|
|
<data name="PreMatch.Footer.Refreshed"><value>refreshed at</value></data>
|
|
|
|
<data name="Live.Title"><value>Live odds feed</value></data>
|
|
<data name="Live.Lede"><value>Currently-live events with the most recent live snapshot. The list refreshes on the configured polling cadence; rows pulse when their odds move.</value></data>
|
|
<data name="Live.AutoRefresh"><value>Auto-refresh</value></data>
|
|
|
|
<data name="Detail.Title"><value>Event</value></data>
|
|
<data name="Detail.NotFound"><value>This event could not be loaded — it may have been removed from the source feed.</value></data>
|
|
<data name="Detail.BackToList"><value>Back to schedule</value></data>
|
|
<data name="Detail.Export"><value>Export</value></data>
|
|
<data name="Detail.Tabs.Aria"><value>Bet scope tabs</value></data>
|
|
<data name="Detail.Tabs.Match"><value>Match</value></data>
|
|
<data name="Detail.Tabs.Period"><value>Period {0}</value></data>
|
|
<data name="Detail.NoBoards"><value>No bets captured yet for this event.</value></data>
|
|
<data name="Detail.BetType"><value>Type</value></data>
|
|
<data name="Detail.Side"><value>Side</value></data>
|
|
<data name="Detail.Threshold"><value>Threshold</value></data>
|
|
<data name="Detail.Rate"><value>Rate</value></data>
|
|
<data name="Detail.BetType.Win"><value>Win</value></data>
|
|
<data name="Detail.BetType.Draw"><value>Draw</value></data>
|
|
<data name="Detail.BetType.WinFora"><value>Handicap</value></data>
|
|
<data name="Detail.BetType.Total"><value>Total</value></data>
|
|
<data name="Detail.Side.Side1"><value>1</value></data>
|
|
<data name="Detail.Side.Side2"><value>2</value></data>
|
|
<data name="Detail.Side.Draw"><value>X</value></data>
|
|
<data name="Detail.Side.Less"><value>Under</value></data>
|
|
<data name="Detail.Side.More"><value>Over</value></data>
|
|
<data name="Detail.Chart.Title"><value>Odds movement</value></data>
|
|
<data name="Detail.Chart.Empty"><value>No snapshots captured yet for this event.</value></data>
|
|
<data name="Detail.Chart.Time"><value>Time</value></data>
|
|
<data name="Detail.Chart.Win1"><value>Win 1</value></data>
|
|
<data name="Detail.Chart.Draw"><value>Draw</value></data>
|
|
<data name="Detail.Chart.Win2"><value>Win 2</value></data>
|
|
<data name="Detail.Chart.AccessibleSummary"><value>Show data table</value></data>
|
|
<data name="Detail.History.Title"><value>Snapshot history</value></data>
|
|
<data name="Detail.History.Source"><value>Source</value></data>
|
|
<data name="Detail.History.BetCount"><value>Bets</value></data>
|
|
<data name="Detail.History.Live"><value>LIVE</value></data>
|
|
<data name="Detail.History.PreMatch"><value>PRE</value></data>
|
|
|
|
<data name="Export.Kicker"><value>Export</value></data>
|
|
<data name="Export.Title"><value>Export to Excel</value></data>
|
|
<data name="Export.DateRange.From"><value>From date</value></data>
|
|
<data name="Export.DateRange.To"><value>To date</value></data>
|
|
<data name="Export.Kind.Label"><value>Snapshot kind</value></data>
|
|
<data name="Export.Kind.PreMatch"><value>Pre-match only</value></data>
|
|
<data name="Export.Kind.Live"><value>Live only</value></data>
|
|
<data name="Export.Kind.Combined"><value>Combined</value></data>
|
|
<data name="Export.Submit"><value>Export</value></data>
|
|
<data name="Export.Cancel"><value>Cancel</value></data>
|
|
<data name="Export.Success"><value>Export saved to {0}</value></data>
|
|
<data name="Export.Hub.Lede"><value>Export captured odds snapshots to an Excel workbook for any date range — no need to open a specific event first.</value></data>
|
|
<data name="Export.Hub.Action"><value>Configure export</value></data>
|
|
<data name="Export.Hub.FilenameHint"><value>Saved as Marathon_<from>_to_<to>.xlsx in the configured export directory.</value></data>
|
|
<data name="Health.Kicker"><value>Operations</value></data>
|
|
<data name="Health.Title"><value>Pipeline health</value></data>
|
|
<data name="Health.Lede"><value>Capture freshness, recent volumes, and worker status at a glance.</value></data>
|
|
<data name="Health.LastCapture"><value>Last capture</value></data>
|
|
<data name="Health.LastCapture.Never"><value>no captures yet</value></data>
|
|
<data name="Health.MinutesAgo"><value>{0} min ago</value></data>
|
|
<data name="Health.Stat.Snapshots"><value>Snapshots (24h)</value></data>
|
|
<data name="Health.Stat.Anomalies"><value>Anomalies (24h)</value></data>
|
|
<data name="Health.Stat.Events"><value>Events tracked</value></data>
|
|
<data name="Health.Stat.Sports"><value>Sports covered</value></data>
|
|
<data name="Health.Total"><value>{0} total</value></data>
|
|
<data name="Health.Workers"><value>Workers</value></data>
|
|
<data name="Health.Worker.Schedule"><value>Schedule poller</value></data>
|
|
<data name="Health.Worker.Live"><value>Live poller</value></data>
|
|
<data name="Health.Worker.Detection"><value>Anomaly detection</value></data>
|
|
<data name="Health.Worker.Results"><value>Results poller</value></data>
|
|
<data name="Health.Empty"><value>No data captured yet — enable the pollers in Settings.</value></data>
|
|
<data name="Export.Error.MissingDates"><value>Pick a start and end date.</value></data>
|
|
<data name="Export.Error.InvalidRange"><value>End date must be on or after the start date.</value></data>
|
|
<data name="Export.Error.Failed"><value>Export failed.</value></data>
|
|
|
|
<data name="Sport.Basketball"><value>Basketball</value></data>
|
|
<data name="Sport.Football"><value>Football</value></data>
|
|
<data name="Sport.Tennis"><value>Tennis</value></data>
|
|
<data name="Sport.Hockey"><value>Hockey</value></data>
|
|
|
|
<data name="Results.Title"><value>Match results</value></data>
|
|
<data name="Results.Lede"><value>Final scores of loaded events. We walk each event page, wait for matchIsComplete=true, and record the winning side.</value></data>
|
|
<data name="Results.Action.LoadNew"><value>Load results</value></data>
|
|
<data name="Results.Action.OpenList"><value>Back to list</value></data>
|
|
<data name="Results.Filter.From"><value>From</value></data>
|
|
<data name="Results.Filter.To"><value>To</value></data>
|
|
<data name="Results.Filter.Search"><value>Search</value></data>
|
|
<data name="Results.Filter.Search.Placeholder"><value>Team, league, category…</value></data>
|
|
<data name="Results.Filter.Sport"><value>Sport</value></data>
|
|
<data name="Results.Filter.Winner"><value>Winner</value></data>
|
|
<data name="Results.Filter.Winner.All"><value>Any</value></data>
|
|
<data name="Results.Filter.Winner.Side1"><value>Side 1</value></data>
|
|
<data name="Results.Filter.Winner.Side2"><value>Side 2</value></data>
|
|
<data name="Results.Filter.Winner.Draw"><value>Draw</value></data>
|
|
<data name="Results.Column.Time"><value>Time</value></data>
|
|
<data name="Results.Column.Country"><value>Country</value></data>
|
|
<data name="Results.Column.League"><value>League</value></data>
|
|
<data name="Results.Column.Match"><value>Match</value></data>
|
|
<data name="Results.Column.Score"><value>Score</value></data>
|
|
<data name="Results.Column.Winner"><value>Winner</value></data>
|
|
<data name="Results.Column.CompletedAt"><value>Completed</value></data>
|
|
<data name="Results.Empty"><value>No results loaded for this range yet. Run a load or wait for matches to complete.</value></data>
|
|
<data name="Results.Footer.Items"><value>results</value></data>
|
|
|
|
<data name="Results.Loader.Kicker"><value>Loader</value></data>
|
|
<data name="Results.Loader.Title"><value>Load results</value></data>
|
|
<data name="Results.Loader.Lede"><value>We poll each event page, capture the final score, and record the winning side. Pick a date range or specific events.</value></data>
|
|
<data name="Results.Loader.Mode"><value>Mode</value></data>
|
|
<data name="Results.Loader.Mode.AllInRange"><value>All in range</value></data>
|
|
<data name="Results.Loader.Mode.Selected"><value>Selected events</value></data>
|
|
<data name="Results.Loader.Selected.Empty"><value>Every event in this range already has a result.</value></data>
|
|
<data name="Results.Loader.Selected.CountFormat"><value>{0} selected</value></data>
|
|
<data name="Results.Loader.Action.Load"><value>Load</value></data>
|
|
<data name="Results.Loader.Action.Cancel"><value>Cancel</value></data>
|
|
<data name="Results.Loader.Action.Back"><value>Back</value></data>
|
|
<data name="Results.Loader.Progress.Format"><value>{0} / {1}</value></data>
|
|
<data name="Results.Loader.Progress.Loaded"><value>Loaded</value></data>
|
|
<data name="Results.Loader.Progress.AlreadyLoaded"><value>Already loaded</value></data>
|
|
<data name="Results.Loader.Progress.NotYetComplete"><value>Not yet complete</value></data>
|
|
<data name="Results.Loader.Progress.Failed"><value>Failed</value></data>
|
|
<data name="Results.Loader.Summary.Format"><value>Loaded {0}, skipped {1}, processed {2} total.</value></data>
|
|
<data name="Results.Loader.Empty.NoCandidates"><value>No events to load in this range.</value></data>
|
|
|
|
<data name="Nav.Insights"><value>Insights</value></data>
|
|
<data name="Insights.Kicker"><value>Calibration</value></data>
|
|
<data name="Insights.Title"><value>Did the flips predict the winner?</value></data>
|
|
<data name="Insights.Lede"><value>Every persisted suspension-flip anomaly joined against the final event result. The hit rate tells you whether the post-flip favourite is the side that actually won — the only metric that says the detector is doing its job.</value></data>
|
|
<data name="Insights.Stat.HitRate"><value>Hit rate</value></data>
|
|
<data name="Insights.Stat.HitRate.Hint"><value>Post-flip favourite won.</value></data>
|
|
<data name="Insights.Stat.Resolved"><value>Resolved</value></data>
|
|
<data name="Insights.Stat.Resolved.Hint"><value>Anomalies with a graded event.</value></data>
|
|
<data name="Insights.Stat.Unresolved"><value>Unresolved</value></data>
|
|
<data name="Insights.Stat.Unresolved.Hint"><value>Awaiting event result.</value></data>
|
|
<data name="Insights.Stat.Hits"><value>Hits</value></data>
|
|
<data name="Insights.Stat.Misses"><value>Misses</value></data>
|
|
<data name="Insights.Stat.Total"><value>Total anomalies</value></data>
|
|
<data name="Insights.Section.BySeverity"><value>By severity</value></data>
|
|
<data name="Insights.Section.BySport"><value>By sport</value></data>
|
|
<data name="Insights.Section.ByScore"><value>By confidence score</value></data>
|
|
<data name="Insights.Section.Resolved"><value>Resolved anomalies</value></data>
|
|
<data name="Insights.Section.Unresolved"><value>Awaiting results</value></data>
|
|
<data name="Insights.Column.DetectedAt"><value>Detected</value></data>
|
|
<data name="Insights.Column.Match"><value>Match</value></data>
|
|
<data name="Insights.Column.Sport"><value>Sport</value></data>
|
|
<data name="Insights.Column.Score"><value>Score</value></data>
|
|
<data name="Insights.Column.PreFavourite"><value>Pre-flip pick</value></data>
|
|
<data name="Insights.Column.PostFavourite"><value>Post-flip pick</value></data>
|
|
<data name="Insights.Column.Winner"><value>Actual winner</value></data>
|
|
<data name="Insights.Column.Outcome"><value>Verdict</value></data>
|
|
<data name="Insights.Column.Bucket"><value>Bucket</value></data>
|
|
<data name="Insights.Column.HitRate"><value>Hit rate</value></data>
|
|
<data name="Insights.Column.HitsOfTotal"><value>Hits / total</value></data>
|
|
<data name="Insights.Outcome.Hit"><value>Hit</value></data>
|
|
<data name="Insights.Outcome.Miss"><value>Miss</value></data>
|
|
<data name="Insights.Outcome.Unresolved"><value>Pending</value></data>
|
|
<data name="Insights.Side.Side1"><value>Side 1</value></data>
|
|
<data name="Insights.Side.Side2"><value>Side 2</value></data>
|
|
<data name="Insights.Side.Draw"><value>Draw</value></data>
|
|
<data name="Insights.Side.Unknown"><value>—</value></data>
|
|
<data name="Insights.Empty.None"><value>No anomalies have been recorded yet. Once the detector flags one and the matching event finishes, its verdict will appear here.</value></data>
|
|
<data name="Insights.Empty.NoneResolved"><value>Anomalies exist but no matching events have been graded yet. Run the results loader or wait for matches to complete.</value></data>
|
|
<data name="Insights.Action.Refresh"><value>Refresh</value></data>
|
|
<data name="Insights.Action.OpenAnomaly"><value>Open</value></data>
|
|
<data name="Insights.Bucket.NotApplicable"><value>—</value></data>
|
|
|
|
<data name="Nav.MyBets"><value>My bets</value></data>
|
|
<data name="Journal.Kicker"><value>Journal</value></data>
|
|
<data name="Journal.Title"><value>Your bets and CLV</value></data>
|
|
<data name="Journal.Lede"><value>Every wager you've recorded, graded against final results and scored against the closing line. Positive CLV is the leading indicator that says you're consistently beating the market.</value></data>
|
|
<data name="Journal.Stat.Roi"><value>ROI</value></data>
|
|
<data name="Journal.Stat.Roi.Hint"><value>Net profit ÷ total staked.</value></data>
|
|
<data name="Journal.Stat.StrikeRate"><value>Strike rate</value></data>
|
|
<data name="Journal.Stat.StrikeRate.Hint"><value>Wins ÷ (wins + losses).</value></data>
|
|
<data name="Journal.Stat.AvgClv"><value>Avg CLV</value></data>
|
|
<data name="Journal.Stat.AvgClv.Hint"><value>Mean closing-line implied-probability gain.</value></data>
|
|
<data name="Journal.Stat.NetProfit"><value>Net profit</value></data>
|
|
<data name="Journal.Stat.NetProfit.Hint"><value>Returns minus stakes (resolved bets).</value></data>
|
|
<data name="Journal.Stat.TotalBets"><value>Total bets</value></data>
|
|
<data name="Journal.Stat.Pending"><value>Pending</value></data>
|
|
<data name="Journal.Stat.Won"><value>Won</value></data>
|
|
<data name="Journal.Stat.Lost"><value>Lost</value></data>
|
|
<data name="Journal.Stat.Void"><value>Void</value></data>
|
|
<data name="Journal.Section.Add"><value>Record a bet</value></data>
|
|
<data name="Journal.Section.List"><value>Bet journal</value></data>
|
|
<data name="Journal.Action.Refresh"><value>Refresh</value></data>
|
|
<data name="Journal.Action.Resolve"><value>Resolve pending</value></data>
|
|
<data name="Journal.Action.Submit"><value>Record bet</value></data>
|
|
<data name="Journal.Action.Delete"><value>Delete</value></data>
|
|
<data name="Journal.Action.Confirm"><value>Confirm</value></data>
|
|
<data name="Journal.Action.Cancel"><value>Cancel</value></data>
|
|
<data name="Journal.Field.EventId"><value>Event ID</value></data>
|
|
<data name="Journal.Field.EventId.Hint"><value>Numeric ID from the event detail URL.</value></data>
|
|
<data name="Journal.Field.FindEvent"><value>Find event</value></data>
|
|
<data name="Journal.Field.FindEvent.Placeholder"><value>Search by team name…</value></data>
|
|
<data name="Journal.Field.FindEvent.Hint"><value>Pick an upcoming event to fill the ID, or type it below.</value></data>
|
|
<data name="Journal.Field.Type"><value>Bet type</value></data>
|
|
<data name="Journal.Field.Side"><value>Side</value></data>
|
|
<data name="Journal.Field.Value"><value>Threshold</value></data>
|
|
<data name="Journal.Field.Value.Hint"><value>Handicap or total line (e.g. -1.5, 2.5).</value></data>
|
|
<data name="Journal.Field.Rate"><value>Taken rate</value></data>
|
|
<data name="Journal.Field.Stake"><value>Stake</value></data>
|
|
<data name="Journal.Field.Notes"><value>Notes</value></data>
|
|
<data name="Journal.Field.Notes.Placeholder"><value>Strategy tag, bookmaker, or anything you want to remember…</value></data>
|
|
<data name="Journal.BetType.Win"><value>Win</value></data>
|
|
<data name="Journal.BetType.Draw"><value>Draw</value></data>
|
|
<data name="Journal.BetType.WinFora"><value>Handicap</value></data>
|
|
<data name="Journal.BetType.Total"><value>Total</value></data>
|
|
<data name="Journal.Side.Side1"><value>Side 1</value></data>
|
|
<data name="Journal.Side.Side2"><value>Side 2</value></data>
|
|
<data name="Journal.Side.Draw"><value>Draw</value></data>
|
|
<data name="Journal.Side.Less"><value>Under</value></data>
|
|
<data name="Journal.Side.More"><value>Over</value></data>
|
|
<data name="Journal.Outcome.Pending"><value>Pending</value></data>
|
|
<data name="Journal.Outcome.Won"><value>Won</value></data>
|
|
<data name="Journal.Outcome.Lost"><value>Lost</value></data>
|
|
<data name="Journal.Outcome.Void"><value>Void</value></data>
|
|
<data name="Journal.Column.PlacedAt"><value>Placed</value></data>
|
|
<data name="Journal.Column.Match"><value>Match</value></data>
|
|
<data name="Journal.Column.Selection"><value>Selection</value></data>
|
|
<data name="Journal.Column.Stake"><value>Stake</value></data>
|
|
<data name="Journal.Column.Rate"><value>Rate</value></data>
|
|
<data name="Journal.Column.Profit"><value>P&L</value></data>
|
|
<data name="Journal.Column.Clv"><value>CLV</value></data>
|
|
<data name="Journal.Column.Outcome"><value>Outcome</value></data>
|
|
<data name="Journal.Empty.None"><value>No bets recorded yet. Use the form above to log a wager — once the event finishes the journal will auto-grade it and compute closing-line value against the latest pre-match snapshot.</value></data>
|
|
<data name="Journal.Empty.NotApplicable"><value>—</value></data>
|
|
<data name="Journal.Error.Generic"><value>Failed to save bet — check the event ID and try again.</value></data>
|
|
<data name="Journal.Submitted"><value>Bet recorded.</value></data>
|
|
<data name="Journal.Kelly.Title"><value>Stake helper (¼-Kelly)</value></data>
|
|
<data name="Journal.Kelly.Bankroll"><value>Bankroll</value></data>
|
|
<data name="Journal.Kelly.Probability"><value>Win probability (%)</value></data>
|
|
<data name="Journal.Kelly.Suggestion"><value>Suggested stake: {0:0.00}</value></data>
|
|
<data name="Journal.Kelly.Apply"><value>Apply</value></data>
|
|
<data name="Journal.Kelly.NoEdge"><value>No positive edge at this price.</value></data>
|
|
<data name="Journal.Kelly.Hint"><value>Enter bankroll + win probability for a ¼-Kelly stake.</value></data>
|
|
<data name="Journal.Resolve.None"><value>No pending bets needed grading.</value></data>
|
|
<data name="Journal.Resolve.Done"><value>Graded {0} pending bet(s).</value></data>
|
|
<data name="Journal.Confirm.Delete"><value>Delete this bet permanently?</value></data>
|
|
|
|
<data name="Nav.Backtest"><value>Backtest</value></data>
|
|
<data name="Backtest.Kicker"><value>Simulator</value></data>
|
|
<data name="Backtest.Title"><value>Replay the detector against history</value></data>
|
|
<data name="Backtest.Lede"><value>Run a hypothetical strategy over every anomaly the detector has flagged. Choose a confidence threshold and a staking rule — the simulator settles every bet against the actual event result, compounds bankroll, and reports the headline numbers you need to judge edge.</value></data>
|
|
<data name="Backtest.Section.Strategy"><value>Strategy</value></data>
|
|
<data name="Backtest.Section.Headline"><value>Result</value></data>
|
|
<data name="Backtest.Section.Equity"><value>Equity curve</value></data>
|
|
<data name="Backtest.Section.Trace"><value>Trade trace</value></data>
|
|
<data name="Backtest.Field.Bankroll"><value>Starting bankroll</value></data>
|
|
<data name="Backtest.Field.From"><value>From date</value></data>
|
|
<data name="Backtest.Field.To"><value>To date</value></data>
|
|
<data name="Backtest.Field.DateRange.Hint"><value>Leave both empty to backtest every graded anomaly.</value></data>
|
|
<data name="Backtest.Field.MinScore"><value>Min anomaly score</value></data>
|
|
<data name="Backtest.Field.MinScore.Hint"><value>Only bet anomalies at or above this confidence.</value></data>
|
|
<data name="Backtest.Field.StakeRule"><value>Staking rule</value></data>
|
|
<data name="Backtest.Field.FlatStake"><value>Flat stake</value></data>
|
|
<data name="Backtest.Field.PercentOfBankroll"><value>Percent of bankroll</value></data>
|
|
<data name="Backtest.Field.KellyFraction"><value>Kelly fraction</value></data>
|
|
<data name="Backtest.Field.KellyFraction.Hint"><value>0.25 (quarter-Kelly) is the conservative default.</value></data>
|
|
<data name="Backtest.StakeRule.Flat"><value>Flat</value></data>
|
|
<data name="Backtest.StakeRule.PercentOfBankroll"><value>% of bankroll</value></data>
|
|
<data name="Backtest.StakeRule.Kelly"><value>Kelly</value></data>
|
|
<data name="Backtest.Action.Run"><value>Run simulation</value></data>
|
|
<data name="Backtest.Action.Running"><value>Simulating…</value></data>
|
|
<data name="Backtest.Action.Cancel"><value>Cancel</value></data>
|
|
<data name="Backtest.Stat.FinalBankroll"><value>Final bankroll</value></data>
|
|
<data name="Backtest.Stat.NetProfit"><value>Net profit</value></data>
|
|
<data name="Backtest.Stat.Roi"><value>ROI</value></data>
|
|
<data name="Backtest.Stat.MaxDrawdown"><value>Max drawdown</value></data>
|
|
<data name="Backtest.Stat.BetsPlaced"><value>Bets placed</value></data>
|
|
<data name="Backtest.Stat.Wins"><value>Wins</value></data>
|
|
<data name="Backtest.Stat.Losses"><value>Losses</value></data>
|
|
<data name="Backtest.Stat.Skipped"><value>Skipped</value></data>
|
|
<data name="Backtest.Stat.MaxWinStreak"><value>Max win streak</value></data>
|
|
<data name="Backtest.Stat.MaxLossStreak"><value>Max loss streak</value></data>
|
|
<data name="Backtest.Stat.TotalStaked"><value>Total staked</value></data>
|
|
<data name="Backtest.Stat.TotalReturned"><value>Total returned</value></data>
|
|
<data name="Backtest.Column.DetectedAt"><value>Detected</value></data>
|
|
<data name="Backtest.Column.Match"><value>Match</value></data>
|
|
<data name="Backtest.Column.Score"><value>Score</value></data>
|
|
<data name="Backtest.Column.Pick"><value>Pick</value></data>
|
|
<data name="Backtest.Column.Rate"><value>Rate</value></data>
|
|
<data name="Backtest.Column.Stake"><value>Stake</value></data>
|
|
<data name="Backtest.Column.Payout"><value>Payout</value></data>
|
|
<data name="Backtest.Column.Bankroll"><value>Bankroll</value></data>
|
|
<data name="Backtest.Column.Outcome"><value>Outcome</value></data>
|
|
<data name="Backtest.Outcome.Win"><value>Win</value></data>
|
|
<data name="Backtest.Outcome.Loss"><value>Loss</value></data>
|
|
<data name="Backtest.Empty.NoData"><value>No graded anomalies to simulate yet. Run the results loader so the detector has outcomes to replay against.</value></data>
|
|
<data name="Backtest.Empty.NoBetsPlaced"><value>The strategy placed zero bets — try lowering the score threshold, or switch staking rule.</value></data>
|
|
<data name="Backtest.Error.Generic"><value>Simulation failed — check the form values and try again.</value></data>
|
|
</root>
|