TradingSignals.
TradingSignals is a personal buy/sell signal tool for crypto and equities — not a mass copy-trading bot, but a system built for one person, backtested against 2–5 years of real market data. NestJS scans simultaneously across multiple timeframes from 15 minutes to 1 month, running in parallel through 4 independent engines: <em>candlestick pattern, indicator, price action</em> and <em>volume analysis</em>. A signal is only recorded when multiple timeframes converge — cutting through noise and surfacing only the entry points genuinely worth attention. After 10 days, the system looks back at each signal — right or wrong — gradually sharpening its accuracy the longer it runs. Results are pushed directly to a personal Telegram the moment a signal fires, with patterns rendered in real time on a TradingView chart embedded in Next.js.
01.Overview
The big pictureMost signal tools share the same fatal flaw: they fire continuously, every timeframe tells a different story, and no one is accountable when they're wrong. A bullish 15m bar today can be forgotten noise by tomorrow — yet it still gets called out like it means something. TradingSignals was built to work the other way: fewer signals, but every signal that fires gets reviewed against what actually happened.
Trading-signals is a NestJS pipeline that scans crypto and Vietnamese equities across 6 timeframes (15m → 1month) through 4 engines (candlestick · indicator · price action · volume); only writes to DB when multiple timeframes reach consecutive multi-day consensus, and once a signal fires it self-monitors for 10 days to settle SUCCESS / FAIL. The Next.js front-end with TradingView Charting Library renders signals alongside shape patterns (neckline, support/resistance, divergence) drawn directly on the chart, real time via WebSocket. Currently running internally across ~30 crypto assets + ~50 Vietnamese equities.
02.Features
What it does- 01Multi-timeframe · 4 engines15m · 1h · 4h · 1d · 1w · 1month
Each asset is analysed across 6 timeframes; each timeframe passes through 4 engines:
CandlestickPatternService(doji, hammer, engulfing, star, three soldiers/crows),TechnicalIndicatorService(RSI · MACD · Bollinger),PriceActionService(support / resistance · neckline) andVolumeAnalysisService(spike, dry-up). Each engine returns an action + confidence + score — feeding into the multi-timeframe aggregation step that follows. - 02Cross-timeframe · multi-day consensus15m+1h · 1h+4h (3d) · 4h+1d (5d)
The daily state of each timeframe is stored in Redis DB9 under the key
crypto:stage:{symbol}:{tf}:{YYYY-MM-DD}with TTLs tuned per timeframe: 15m=1d, 1h=2d, 4h=5d, 1d=15d. Only when multiple timeframes agree on BUY or SELL across 1, 3 or 5 consecutive days does a signal get persisted to thesignalstable and POSTed toRESULT_API_URL— ensuring what gets recorded reflects a genuine trend, not a momentary fluctuation. - 03Duplicate guardSkip if seen in the prior 3 days
Before persisting a new consensus, the service checks whether the same signal already exists within the past 3 days. If it does → skip. The goal isn't to miss signals, but to avoid repeat notifications when the market is simply continuing in the same direction — the system only speaks up when the state genuinely changes.
- 0410-day self-evaluationDaily cron · SUCCESS / FAIL
Every day at 07:00 for crypto and 10:00 on weekdays for equities, a cron job triggers
SignalTrackingServiceto revisit every signal issued within the past 10 days. For each signal still under observation, the current price is appended tometadata.tracking10d— building a day-by-day price trail from the moment the signal was first fired. On day 10, the system compares againsttakeProfitPriceandstopLossPriceto deliver a final verdict:trackingStatus = SUCCESS / FAILED, stamped with anevaluatedAttimestamp. - 05Chart + pattern overlayTradingView Charting Library · ws stream
The front-end is built on Next.js with the TradingView Charting Library, powered by a custom
DatafeedService: HTTP for loading history bars, WebSocket for receiving real-time price updates.MobileCharttakes in aPatternDrawing[]array and renders shapes directly onto the chart — colours reflect signal bias (bullish#16a34a, bearish#dc2626, neutral#64748b); line style distinguishes pattern type: necklines and support/resistance use dashed lines, event-based patterns like RSI divergence and engulfing use thin solid lines.
03.Tech stack
Tools used| Backend | NestJS 10 · TypeScript · TypeORM · @nestjs/schedule (cron) · @nestjs/event-emitter · @nestjs/swagger · axios |
| Frontend | Next.js 15 · React 19 · TypeScript · TradingView Charting Library (custom DatafeedService) · WebSocket streaming · port 3019 |
| Storage | MySQL (signals table · enum dataSource/type/source · decimal(18,8) for crypto prices · JSON metadata · indexes on dataSource+symbolRef+date) |
| Stage cache | Redis DB9 with keys crypto:stage:{symbol}:{tf}:{date} and stock:stage:{symbol}:{tf}:{date} · rule-aware TTLs (15m=1d, 1h=2d, 4h=5d, 1d=15d) |
| Data sources | Binance API (crypto · spot OHLCV across 6 timeframes) · internal stock data (1h / 1d / 1w native, 15m proxied) · VN trading hours via trading-hours.helper |
| Reliability | isScanning flag to prevent overlap · cron 07:00 crypto / 10:00 weekday stock · POST RESULT_API_URL for external notify · 3-day duplicate guard |
04.How it works
ArchitectureThe backbone of the system is a state machine living silently in Redis. Each time a timeframe is scanned, the service writes {action, confidence, score, capturedAt} to the key {source}:stage:{symbol}:{tf}:{YYYY-MM-DD} with TTLs sized precisely so consensus rules can look back across multiple days: 15m lives 1 day, 1h lives 2 days, 4h lives 5 days, 1d lives 15 days. This structure makes evaluating a complex rule like 1h+4h across 3 consecutive days straightforward: read the 3 most recent 1h keys, read the 3 most recent 4h keys, then check whether any day has both agreeing on BUY or SELL — no DB queries, no table joins required.
When a signal is persisted, it carries the full price context at the moment it fired: priceAtSignal, entryPrice, takeProfitPrice, and stopLossPrice. From there, SignalTrackingService runs a daily cron (crypto at 07:00, equities at 10:00 on weekdays) to trace the price journey: for every signal under 10 days old, the current price is appended to metadata.tracking10d once per day. On day 10, the system computes the max/min across the entire array and compares against TP/SL: hitting takeProfitPrice first → SUCCESS, hitting stopLossPrice first → FAILED, neither reached → EXPIRED. The SUCCESS rate broken down by rule and by timeframe is queryable directly from SQL — no additional computation needed at the application layer.
Most signal tools fire endlessly then go quiet — no way to know what was right or wrong, nothing to learn from after each trade. tracking10d and the daily cron in TradingSignals exist to fix exactly that: every signal must have a definitive outcome, underperforming rules get called out by the data, and I update the code accordingly. Fewer signals over time, but the ones that fire are ones I can actually trust — that's what I needed when sitting down to trade.
ZoomBot is a pool of Chrome bots that automatically join Zoom meetings and wait for remote commands via HTTP API. Each bot runs on its own isolated Chrome instance with its own lock, fully thread-safe — bots don't interfere with each other even when running in parallel. A single API call can instruct any bot to send a chat message, toggle the mic, toggle video, leave the room, or rejoin. When a bot crashes, the system detects it automatically and restarts without any manual intervention. The entire stack is written in Python, Selenium, and Flask — lean enough to run on a standard server without complex infrastructure.
BankNotify turns an old Android phone into a DIY payment gateway for small merchants. A Flutter + Kotlin app runs in the background on the device, reads incoming balance change notifications from the banking app, and forwards them to a backend via HTTP. The backend receives the notification, matches it against a pending order, and fires a callback to complete the payment — all within seconds, no formal payment gateway integration required, no monthly fees.
A NestJS API that auto-logs into ChatGPT via puppeteer-real-browser (Cloudflare anti-bot bypass), supports email OTP, persists the session for route /ask reuse and directly promt promt, and runs an hourly cron that pings Telegram when the session expires. This allows me to send prompts and receive responses directly through the API without needing to open a browser.

RandomKit is a lightweight collection of randomisation tools that runs entirely client-side — no server, no data sent anywhere. It includes the tools people actually reach for: a customisable spinner with fair probabilities and transparent percentage display, duck racing, a draw lots picker, coin flip, dice roller, random number generator, password generator, and a random location picker on a map. The interface supports both Vietnamese and English, with clean SEO structure so each individual tool is independently discoverable.
05.Comments
Leave a few wordsNo comments yet.