Zurück zum Blog
Vibe Sense

Deine Plattform, die sich selbst überwacht.

Ich hab vor Jahren einen Trading-Bot aufgegeben. Seine Architektur wurde zum spannendsten Teil von next-vibe. Jede Node im Graph ist ein Endpoint - aufrufbar über die CLI, auffindbar für KI, direkt in die Plattform integriert.

14 Min. Lesezeit
Architektur

Der Trading-Bot, den ich aufgegeben hab

Vor ein paar Jahren hab ich OctoBot geforkt und daraus etwas gebaut, das ich Octane nannte. Python-Backend, React-Frontend. Man konnte technische Indikatoren auf eine Canvas ziehen, Evaluatoren verketten, Ausführungsregeln konfigurieren, Alerts einrichten, Orders abfeuern. Ein vollständiger visueller Strategy-Builder. Ich nutz ihn noch für mein eigenes Portfolio.

Als Codebase hab ich ihn aufgegeben. Das Python war ein Chaos, die Architektur hatte so viel technische Schulden angehäuft, dass sich jede Änderung teuer anfühlte.

Aber der Gedanke daran ließ mich nicht los. Vor allem nicht der Gedanke daran, was ihn als System zum Laufen gebracht hat.

Der Trading-Bot hatte die richtige Architektur. Mein Fehler war, ihn isoliert zu bauen.

Octane (OctoBot-Fork)

Visueller Strategy-Builder, Drag-and-Drop-Indikatoren, Python-Backend. Als Codebase aufgegeben.

Die Erkenntnis

Diese Struktur beschreibt nicht nur Trading. Sie beschreibt jeden Geschäftsprozess mit zeitbasierten Daten.

Neugebaut in next-vibe

Sauber typisiert. Jede Node ist ein Standard-Endpoint. Überall verfügbar, wo die Plattform läuft.

Jedes Business ist eine Zeitreihe

Bei einem Trading-Bot sind die Bausteine simpel. Eine Datenquelle: Preisdaten, Volumen, was auch immer man ausliest. Ein Indikator: Moving Average, RSI, MACD - nimmt Rohdaten, erzeugt ein abgeleitetes Signal. Ein Evaluator: Ist der schnelle MA über dem langsamen? Boolean-Bedingung. Eine Aktion: Wenn der Evaluator anschlägt, tu was.

Diese Struktur beschreibt nicht nur Trading. Sie beschreibt jeden Geschäftsprozess, bei dem du Daten über Zeit hast, Bedingungen die dir wichtig sind, und Aktionen die du auslösen willst, wenn diese Bedingungen eintreten.

Nutzerwachstum

Das ist eine Zeitreihe. Geht sie runter? Das ist ein Evaluator. Schick eine Win-back-Kampagne. Das ist eine Aktion.

E-Mail-Performance

Öffnungsraten, Bounce-Raten, Abmelderaten. Alles Zeitreihen. Alles auswertbare Bedingungen. Alles triggerbar.

Credit-Ökonomie

Ausgabegeschwindigkeit. Burn-Rate vs. Kaufrate. Alles.

Umsatzanomalien

Rückerstattungsrate steigt an einem Tag über 20 % - Thea kriegt Bescheid, bevor du es im Dashboard siehst.

Die vier Node-Typen

Drei Node-Typen, die du verstehen musst, um einen Graph zu lesen. Plus ein vierter, der den Kreis schließt.

DataSource

Ein domäneneigener Endpoint, der die Datenbank abfragt und { timestamp, value }[] für einen bestimmten Zeitraum und eine Auflösung zurückgibt. Lebt bei seiner Domäne. Kennt sein eigenes Schema.

Indicator

Ein reiner, wiederverwendbarer Berechnungs-Endpoint - EMA, RSI, MACD, Bollinger Bands, Clamp, Delta, Fensterdurchschnitt. Kein SQL. Kein Domänenwissen. Auf jede Datenquelle anwendbar.

Evaluator

Ein Schwellenwert oder eine Bedingung. Nimmt eine Reihe und stellt eine Frage. Liegt der Wert unter 0,7? Hat das Verhältnis 20 % überschritten? Gibt ein Signal aus - ausgelöst oder nicht.

Action

Wenn der vorgelagerte Evaluator auslöst, wird ein bestimmter Endpoint aufgerufen. In-Process. Kein HTTP. Gleiche Validierung, gleiche Auth, gleicher Response-Typ wie jeder andere Aufruf im System.

DataSource

Ein domäneneigener Endpoint, der die Datenbank abfragt und { timestamp, value }[] für einen bestimmten Zeitraum und eine Auflösung zurückgibt. Lebt bei seiner Domäne. Kennt sein eigenes Schema.

Indicator

Ein reiner, wiederverwendbarer Berechnungs-Endpoint - EMA, RSI, MACD, Bollinger Bands, Clamp, Delta, Fensterdurchschnitt. Kein SQL. Kein Domänenwissen. Auf jede Datenquelle anwendbar.

Evaluator

Ein Schwellenwert oder eine Bedingung. Nimmt eine Reihe und stellt eine Frage. Liegt der Wert unter 0,7? Hat das Verhältnis 20 % überschritten? Gibt ein Signal aus - ausgelöst oder nicht.

Action

Wenn der vorgelagerte Evaluator auslöst, wird ein bestimmter Endpoint aufgerufen. In-Process. Kein HTTP. Gleiche Validierung, gleiche Auth, gleicher Response-Typ wie jeder andere Aufruf im System.

Jede Node ist ein Endpoint

Das ist der wichtigste Punkt, den ich klären will, bevor wir weitermachen.

Alter Ansatz (Octane)

EMA existiert nur als Node in einem Graph. Man kann es nicht über die CLI aufrufen. Es taucht nicht als KI-Tool auf. Es ist ein internes Implementierungsdetail.

next-vibe Ansatz

Jede Vibe Sense Node ist ein Standard-Endpoint, definiert mit createEndpoint(), registriert in derselben Endpoint-Registry wie alles andere auf der Plattform.

bash
1$ vibe vibe-sense-ema --period=7
2
3  ┌─────────────────────────────────────────┐
4  │  analytics/indicators/ema               │
5  │  EMA (Exponential Moving Average)       │
6  ├─────────────────────────────────────────┤
7  │  period   7                             │
8  │  points   365 input → 365 output        │
9  │  result   [ { timestamp, value }, ... ] │
10  └─────────────────────────────────────────┘

Derselbe EMA-Endpoint, der als Node im Lead-Funnel-Graph läuft - gleiche Definition, gleiche Validierung, gleiche Auth - einzeln von der CLI aufrufbar.

DERSELBE Endpoint, der eine Node in deinem Lead-Funnel-Graph ist, ist gleichzeitig ein eigenständiges Tool auf 13 Plattformen.

Die Pipeline besteht einfach aus Endpoints, die andere Endpoints aufrufen.

Aber Aktionen sind keine Trades

Wenn ein Signal auslöst, ruft die Engine einen beliebigen Endpoint auf. In-Process. Kein HTTP-Roundtrip. Ein Alert. Ein Kampagnen-Trigger. Eine KI-Eskalation mit vorbefülltem Kontext. Thea wird benachrichtigt. Eine Win-back-Sequenz startet. Was auch immer am Evaluator hängt.

Kein Webhook.
Kein eigener Alerting-Service.
Kein Zapier.

Die Plattform ruft sich selbst auf.

Alert

complete-task aufrufen - Thea reagiert sofort.

Kampagne

Eine Conversion-Sequenz auslösen, wenn die Lead-Geschwindigkeit einen Schwellenwert überschreitet.

KI-Eskalation

Einen KI-Lauf mit vorbefülltem Kontext starten - inklusive Info, welches Signal ihn ausgelöst hat.

Den Lead-Funnel-Graph Schritt für Schritt

Das ist der Lead Acquisition Funnel. Er läuft alle sechs Stunden. Gehen wir ihn von oben nach unten durch.

Spalte 1: Datenquellen

Echte Endpoints. Jeder liegt unter leads/data-sources/. Sie nehmen einen Zeitraum und eine Auflösung entgegen, führen ihre SQL-Abfrage aus und liefern { timestamp, value }[] zurück.

leads.created

Fragt Leads nach created_at ab. Sparse - Stunden ohne neue Leads erzeugen keinen Datenpunkt.

leads.converted

Gruppiert nach converted_at, zählt Leads die den SIGNED_UP-Status erreicht haben.

leads.bounced

Leads mit gebounceter E-Mail pro Zeitfenster.

leads.active

Snapshot-Indikator bei ONE_DAY-Auflösung. Zählt alle Leads, die sich nicht in einem Endzustand befinden.

Spalte 2: Indikatoren

Reine Berechnung. Der EMA-Endpoint liegt unter analytics/indicators/ema. Seine Graph-Konfiguration ist schlicht { type: "indicator", indicatorId: "ema", params: { period: 7 } }.

leads_created_ema7

EMA-Indikator, period=7. Erweitert automatisch den Abrufbereich für den Warmup.

conversion_rate

Transformer: teilt leads.converted durch leads.created pro Zeitfenster. Auf 0–1 begrenzt.

Spalte 3: Evaluatoren

Schwellenwertbedingungen. Jeder gibt ein Signal aus - ausgelöst oder nicht.

eval_lead_drop

EMA(7) < 0,7 bei ONE_WEEK-Auflösung. Lead-Erstellungsrate, geglättet über 7 Perioden, fällt unter 70 %.

eval_zero_leads

leads.created < 1/Tag. Ein ganzer Tag ohne neue Leads.

eval_low_conversion

conversion_rate < 5 %/Woche. Funnel-Conversion fällt unter 5 %.

Jede Node ist ein Endpoint

Derselbe EMA-Endpoint, der als Node im Lead-Funnel-Graph läuft - gleiche Definition, gleiche Validierung, gleiche Auth - einzeln von der CLI aufrufbar.

typescript
1// analytics/indicators/ema/definition.ts
2const { POST } = createEndpoint({
3  scopedTranslation,
4  aliases: [EMA_ALIAS],
5  method: Methods.POST,
6  path: ["system", "unified-interface", "vibe-sense", "indicators", "ema"],
7  title: "post.title",
8  description: "post.description",
9  icon: "activity",
10  category: "endpointCategories.analyticsIndicators",
11  tags: ["tags.vibeSense"],
12  allowedRoles: [UserRole.ADMIN],
13  fields: objectField(scopedTranslation, {
14    usage: { request: "data", response: true },
15    children: {
16      source: timeSeriesRequestField(scopedTranslation, { ... }),
17      resolution: resolutionRequestField(scopedTranslation, { ... }),
18      range: rangeRequestField(scopedTranslation, { ... }),
19      lookback: lookbackRequestField(scopedTranslation, { ... }),
20      period: requestField(scopedTranslation, {
21        fieldType: FieldDataType.NUMBER,
22        schema: z.number().int().min(1).max(500),
23        label: "post.fields.period.label",
24        description: "post.fields.period.description",
25      }),
26      result: timeSeriesResponseField(scopedTranslation, { ... }),
27      meta: nodeMetaResponseField(scopedTranslation, { ... }),
28    },
29  }),
30  errorTypes: { /* all 9 required */ },
31  successTypes: { title: "post.success.title", ... },
32  examples: { requests: { default: { source: [...], period: 3 } }, ... },
33});

computeEma()

DERSELBE Endpoint, der eine Node in deinem Lead-Funnel-Graph ist, ist gleichzeitig ein eigenständiges Tool auf 13 Plattformen.

typescript
1// analytics/indicators/ema/repository.ts
2// Pure computation. No DB access.
3export class EmaIndicatorRepository {
4  static computeEma(points: TimeSeries, period: number): TimeSeries {
5    if (points.length === 0) return [];
6    const k = 2 / (period + 1);
7    const result: TimeSeries = [];
8    let ema: number | undefined;
9    for (const p of points) {
10      ema = ema === undefined ? p.value : p.value * k + ema * (1 - k);
11      result.push({ timestamp: p.timestamp, value: ema });
12    }
13    return result;
14  }
15}
16
17// route.ts wires it:
18// handler: ({ data }) => {
19//   const result = EmaIndicatorRepository.computeEma(data.source, data.period);
20//   return success({ result, meta: { ... } });
21// }

Domäneneigene Datenquellen

Eine meiner liebsten Architekturentscheidungen: Datenquellen leben bei ihrer Domäne, nicht in einem zentralen vibe-sense/-Verzeichnis.

Leads-Domäne
leads/data-sources/
leads-created/
constants.ts
definition.ts
i18n/
repository.ts
route.ts
leads-converted/
leads-bounced/
leads-active/
leads-campaign-running/
leads-email-opens/
leads-email-clicks/
leads-engagements/
leads-form-submits/
leads-website-visits/
... 15 Datenquellen insgesamt
Credits-Domäne
credits/data-sources/
credits-spent-total/
constants.ts
definition.ts
i18n/
repository.ts
route.ts
credits-purchased/
credits-earned/
credits-refunded/
credits-balance-total/
credits-subscription-revenue/
credits-transactions-count/
credits-wallets-total/
... 17 Datenquellen insgesamt

leads/data-sources/leads-created kennt die Leads-Tabelle. Es importiert aus leads/db. Es nutzt LeadStatus aus leads/enum. Wenn du das Leads-Modul löschst, verschwinden die Datenquellen gleich mit. Nichts bleibt verwaist.

Indikatoren unter analytics/indicators/

Reine Berechnung - EMA, RSI, MACD, Bollinger Bands, Clamp, Delta, Fensterdurchschnitt. Kein Domänenwissen. Auf jede Datenquelle anwendbar.

Beim Start erkennt die Indikator-Registry beide automatisch. Datenquellen-Endpoints registrieren sich als Node-Definitionen. Neue Domäne anlegen, data-sources/-Endpoints hinzufügen, graphSeeds exportieren. Sie tauchen einfach auf.

Die Domäne besitzt ihre eigene Observability.

Versionierung, Backtest, Persistenz

Drei Dinge, die Vibe Sense produktionssicher machen.

Versionierung

Graphs werden versioniert. Wenn du einen Graph bearbeitest, erstellst du eine neue Version - nie die aktive ändern. Die neue Version ist ein Entwurf. Promoten geht explizit. Rollback ist trivial.

Backtest

Vor dem Promoten kannst du über einen historischen Zeitraum backtesten. Bedingungen werden ausgewertet. Signale werden aufgezeichnet. Endpoints feuern nie. Gate geschlossen.

Persistenzmodi

always

Jeder berechnete Datenpunkt wird in den Datapoints-Store geschrieben. Für ereignisbasierte Indikatoren: erstellte Leads pro Minute, verbrauchte Credits pro Minute.

snapshot

Wird bei Bedarf berechnet, gecacht, aber nicht in die Haupttabelle geschrieben. Tagesgesamtwerte, kumulative Zählungen.

never

Wird immer live aus den Inputs neu berechnet. EMA-Outputs, Verhältnisse - keine Speicherkosten. Lookback wird automatisch für den Warmup erweitert.

Was heute da ist vs. was noch kommt

Heute produktionsbereit

Vollständige Engine: Datenquellen-Endpoints, Indikator-Endpoints (EMA, RSI, MACD, Bollinger, Clamp, Delta, Window), Schwellenwert-Evaluatoren, Transformer-Nodes, Endpoint-Action-Nodes.

Topologische Ausführung über den Graph-Walker. Multi-Resolution-Support mit automatischem Hoch-/Runterskalieren. Lookback-bewusste Bereichserweiterung.

Versionierung, Backtest-Modus mit vollständiger Run-Historie, Signal-Persistenz als Audit-Trail.

CLI-Zugriff - vibe vibe-sense-ema, vibe vibe-sense-rsi, jeder Indikator-Endpoint, einzeln aufrufbar.

MCP-Registrierung - Indikator-Endpoints tauchen in der Tool-Liste auf. Thea kann Indikatoren direkt aufrufen.

Seed-Graphs: 29 Graphs über 9 Domänen - Leads, Credits, Nutzer, Abonnements, Empfehlungen, Newsletter, Zahlungen, Messenger, KI-Chat und Systemgesundheit. Laufen alle sofort bei vibe dev.

Kommt als Nächstes

Visueller Drag-and-Drop-Graph-Builder. Die Engine steht. Der Canvas-Editor ist das nächste Kapitel.

Trading-Endpoints. Preis-Datenquellen-Endpoints, Exchange-API-Endpoints, Order-Ausführung als Endpoint-Nodes verdrahtet. Ein Trading-Graph ist einfach ein weiterer Graph.

Strategie-Marktplatz. Sobald du Graphs visuell bauen kannst, kannst du sie teilen. Eine fertige Lead-Monitoring-Strategie importieren. Forken, anpassen.

Was das Ganze wirklich ist

Jeder Geschäftsprozess, der sich so beschreiben lässt: Gegeben diese Daten - wenn diese Bedingungen eintreten - tu das - ist ein Vibe Sense Graph. Monitoring, klar. Alerting, klar. Aber auch: automatisierte Lead-Qualifizierung, Umsatzanomalie-Erkennung, Credit-Ökonomie-Balancierung, Marketing-Automatisierung.

Der Trading-Bot hatte die richtige Architektur. Indikatoren, Evaluatoren, Aktionen, Backtest-Modus. Mein Fehler war, ihn isoliert zu bauen. In Octane war EMA in der Pipeline eingesperrt. In next-vibe ist EMA ein vollwertiger Endpoint.

Du baust kein Monitoring-System. Du baust deine Plattform. Das Monitoring ist schon drin.

Quick Start
bash
1git clone https://github.com/techfreaque/next-vibe
2cd next-vibe
3cp .env.example .env
4bun install
5vibe dev

vibe dev startet PostgreSQL in Docker, führt Migrationen aus, seeded Daten, seeded die Vibe Sense Graphs, füllt 365 Tage historische Daten auf und startet den Dev-Server. Öffne localhost:3000. Die Graphs laufen.

Einmal definieren. Überall verfügbar. Die Pipeline besteht einfach aus Endpoints, die andere Endpoints aufrufen.