[Fintech · Backend · Automatyzacja danych]
Silnik analizy sygnałów tradingowych
Zautomatyzowany potok, który czyta dane rynkowe kryptowalut, zawęża szeroki zbiór instrumentów do wybranych kandydatów i zamienia je w ustrukturyzowane, zweryfikowane sygnały tradingowe.
01Przegląd projektu
Silnik sygnałów to analityczny rdzeń Astra Raven. Według harmonogramu pobiera dane rynkowe przez zewnętrzne API giełd, ocenia kontekst rynkowy i przepuszcza każdy instrument przez sekwencję filtrów, zanim cokolwiek trafi do użytkownika.
Wynikiem nie jest dowolna opinia, lecz ustrukturyzowany obiekt: instrument, kierunek, strefa wejścia, stop loss, cele i powody, dla których przeszedł weryfikację. Kolejne systemy mogą go zapisać, śledzić i ocenić.
02Wyzwanie inżynierskie
Dane rynkowe są zaszumione i pochodzą z zewnętrznych usług, które bywają wolne, ograniczają liczbę zapytań lub są chwilowo niedostępne. Silnik musi podejmować spójne decyzje w takich warunkach i zostawiać ślad, który każdą z nich wyjaśnia.
- A
Przetworzyć wiele instrumentów w zaplanowanym oknie, nie blokując się na wolnych odpowiedziach.
- B
Oddzielić rozpoznanie kontekstu rynkowego od oceny pojedynczego instrumentu, aby każdy etap dało się analizować osobno.
- C
Odrzucać niekompletnych lub sprzecznych kandydatów jak najwcześniej, zamiast generować słaby wynik.
- D
Zapisywać każdy sygnał z kontekstem wystarczającym do późniejszej oceny jego wyniku.
03Architektura rozwiązania
Najedź lub dotknij etapu.
Dane rynkowe
Świece, wolumeny i metadane instrumentów są pobierane z zewnętrznych API giełd z timeoutami i limitem ponowień.
04Główne komponenty
- 01
Warstwa pobierania danych
Asynchroniczne kolektory szeregów czasowych z kontrolą tempa zapytań, timeoutami i poprawną obsługą niepełnych odpowiedzi.
- 02
Moduł kontekstu rynkowego
Klasyfikuje bieżący stan rynku, aby kolejne filtry dostosowały swoje zachowanie.
- 03
Ranking kandydatów
Filtruje zbiór instrumentów i rangowo porządkuje resztę, utrzymując potok szybkim i skupionym.
- 04
Łańcuch walidacji
Uporządkowane, niezależnie testowalne kontrole. Kandydat, który nie przejdzie którejkolwiek, jest odrzucany z zapisanym powodem.
- 05
Zapis sygnałów
Magazyn SQL sygnałów, ich parametrów i cyklu życia, używany przez śledzenie i raporty.
- 06
Harmonogram i raporty
Uruchamianie według harmonogramu, śledzenie wyników i podsumowania diagnostyczne dla operatora.
05Stack technologiczny
Rdzeń
- Python
- asyncio
- dataclasses
Dane
- Exchange REST APIs
- Time-series processing
- SQLite / SQL
Eksploatacja
- Scheduled jobs
- Structured logging
- Reports
06Interaktywna demonstracja
Symulacja potoku sygnałów
IlustracjaDemo ilustracyjne. Syntetyczny instrument i generowane ceny — bez połączenia z rynkiem, bez prawdziwych parametrów strategii; to nie jest rekomendacja inwestycyjna.
- Dane rynkowe
- Analiza rynku
- Wybór kandydatów
- Walidacja sygnału
- Kontrola ryzyka
- Wydanie sygnału
- Monitoring
$ press “Run pipeline” to process a synthetic market snapshot
Wynik sygnału
—
07Decyzje inżynierskie
- 01
Najpierw kontekst, potem kandydaci
Jednorazowa ocena stanu rynku na początku upraszcza logikę dla pojedynczych instrumentów i czyni uzasadnienie każdego sygnału czytelniejszym.
- 02
Odrzucaj wcześnie, zapisuj powód
Każdy krok walidacji może odrzucić kandydata z jawnym powodem. Mniej sygnałów o jasnym pochodzeniu jest cenniejsze niż wiele niewyjaśnionych.
- 03
Tylko ustrukturyzowany wynik
Sygnały to typowane obiekty, a nie tekst. Dostarczanie, śledzenie i raporty korzystają z tej samej struktury.
- 04
Deterministyczny rdzeń
Ścieżka decyzyjna opiera się na regułach i jest powtarzalna dla tych samych danych, dzięki czemu regresje są wykrywalne.
08Niezawodność i testy
- Timeouty i ograniczone ponowienia dla każdego zewnętrznego zapytania.
- Walidacja kształtu danych wejściowych przed obliczeniami.
- Testy regresji przy zmianach logiki filtrów.
- Logi i raporty pozwalające wyjaśnić pominięty lub odrzucony instrument.
09Przykład kodu
from dataclasses import dataclass, field
from typing import Callable
@dataclass
class Candidate:
symbol: str
direction: str # "LONG" | "SHORT"
entry: float
stop_loss: float
reasons: list[str] = field(default_factory=list)
Check = Callable[[Candidate], str | None] # returns a rejection reason or None
def has_valid_direction(c: Candidate) -> str | None:
return None if c.direction in {"LONG", "SHORT"} else "unknown direction"
def stop_on_correct_side(c: Candidate) -> str | None:
ok = c.stop_loss < c.entry if c.direction == "LONG" else c.stop_loss > c.entry
return None if ok else "stop loss on wrong side of entry"
CHAIN: list[Check] = [has_valid_direction, stop_on_correct_side]
def run_chain(c: Candidate) -> tuple[bool, str | None]:
for check in CHAIN:
if (reason := check(c)) is not None:
return False, f"{check.__name__}: {reason}"
c.reasons.append(check.__name__)
return True, NoneIlustracja Przykład ilustracyjny — uproszczony łańcuch walidacji, nie kod produkcyjny.
Kod źródłowy produktu jest prywatny. Przykłady pokazują podejście inżynierskie, a nie wewnętrzną logikę. Więcej w Engineering Lab.
10Możliwe kierunki rozwoju
- Wtyczkowe źródła danych dla kolejnych giełd i klas aktywów.
- Środowisko backtestów odtwarzające zapisane dane przez ten sam łańcuch walidacji.
- Dashboard metryk etapów pokazujący, gdzie odpadają kandydaci.