The hourly score is a weighted blend of six sub-scorers, each 0–1. Daily averages and the “best window” rollups are computed from the hour-level scores.
The six sub-scorers
- 30% Tide movement
- Rate of change in tide height (m/hour). Moderate flow (~0.30 m/hr) beats both slack water and ripping current — fish feed actively when bait gets pushed around but can't hold position in extreme currents. Computed from local hourly tide heights.
- 15% Solunar timing
- Proximity to lunar transit (T), antitransit (A), moonrise (R), and moonset (S). Long-observed correlation: fish feed more during these periods. Majors (T/A) score higher than minors (R/S). Computed from JPL DE421 ephemeris via Skyfield.
- 15% Daylight position
- Within the daylight window, dawn and dusk score higher than midday. Low-angle light triggers more strikes in tropical waters where midday sun pushes fish deep.
- 15% Weather
- Wind speed/direction, precipitation probability, surface pressure trend, and cloud cover. Light–moderate wind is fine; gusts and sustained >15kn hurt. Falling pressure ahead of a front often triggers active feeding; rising pressure after rain is also strong.
- 10% Moon phase
- For daytime bottom-fishing in Singapore, new moon scores slightly higher than full (fish are less night-active and more daytime-receptive). A smooth cosine — not an on/off toggle.
- 10% Marine swell
- Wave height and sea surface temperature. Calm to lightly choppy (≤0.8m) is ideal for spot-lock and bait control. SST in the comfortable range (28–30°C) is best for target species; cold or very warm water suppresses bite.
Score thresholds
- ≥70 (green) — Go. Multiple favourable factors align.
- 60–69 (orange) — Borderline. Worth going if conditions match your style.
- 50–59 (light orange) — Marginal. Likely tough; one factor is usually limiting.
- <50 (red) — Skip. Stacked unfavourable conditions.
Glossary
- Avg score
- Mean hourly score across every daylight hour that day, including the mediocre ones. The number on each calendar cell, used to rank days against each other. Best for “which day this week is best overall?”
- Peak score
- Highest single-hour score of the day. A high peak with a low Avg means a narrow but excellent window.
- Best window
- The longest contiguous block of hours scoring ≥60 — the time range you'd actually plan around. Shown as “13:00–16:00”.
- Window avg
- Mean hourly score only inside the Best window. Always ≥ Avg score (since the window picks the good hours). Best for “if I only fish during the prime hours, how good are they?”
- Which to act on?
- Window avg + Best window time range. That's the actionable pair: when to go and how good it'll be once you're there. Use Avg score only to compare days at a glance in the calendar.
- Spring tide / neap tide
- Spring = larger tidal range (around new and full moons), stronger currents. Neap = smaller range (around quarter moons), gentler currents.
- Solunar major / minor period
- Major = when the moon is directly overhead (transit) or directly underfoot (antitransit). Minor = at moonrise or moonset. Both windows typically last about an hour around the event.
- Squall risk hour
- An hour where the forecast precipitation probability is high enough that a thunderstorm is plausible. Bar is red in the chart, regardless of the underlying score.
- Limiter
- The lowest-scoring sub-scorer during the best window — i.e., the one factor most holding the score back. Useful for “what's the catch?”.
Data sources
- Tide heights: MPA tide tables (West Tuas station) for Tuas Basin; Open-Meteo Marine (FES2022 / WorldTides-derived) for other spots.
- Weather: Open-Meteo hourly forecast (wind, precipitation, pressure, clouds), with NEA 4-day overlay layered on top.
- Marine: Open-Meteo Marine API (wave height, sea surface temperature).
- Solunar / sun: Skyfield + JPL DE421 ephemeris.
Honest limitations
- Scoring is heuristic. Weights are hand-set from angler convention and the author's experience, not regressed against catch outcomes yet. A calibration path is built in (
backtest.py --calibrate) — once we have ≥20 outings with star ratings, scipy will refit the weights against actual results. Real ML (boosted trees etc.) would need 100+ outings. - Bait, technique, target species, and local knowledge are not modelled — the score predicts conditions, not the day you personally will have.
- Open-Meteo's tide model is global; it can be 10–20 minutes off real local tides for spots outside Tuas Basin.
- Solunar timing is a soft signal — well-established but not deterministic. Other factors usually dominate.