{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Streaming API — bar-by-bar live trading\n", "\n", "The `ferro_ta.streaming` module provides stateful classes that process\n", "data bar-by-bar, suitable for real-time feeds and live trading.\n", "\n", "Install:\n", "```bash\n", "pip install ferro-ta\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from ferro_ta.streaming import (\n", " StreamingATR,\n", " StreamingBBands,\n", " StreamingEMA,\n", " StreamingMACD,\n", " StreamingRSI,\n", " StreamingSMA,\n", ")\n", "\n", "# Simulate incoming bars\n", "np.random.seed(42)\n", "n = 50\n", "closes = np.cumprod(1 + np.random.randn(n) * 0.01) * 100\n", "highs = closes * 1.005\n", "lows = closes * 0.995\n", "\n", "print(f\"Simulated {n} bars\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## StreamingSMA and StreamingEMA" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sma = StreamingSMA(period=5)\n", "ema = StreamingEMA(period=5)\n", "\n", "sma_values = [sma.update(c) for c in closes]\n", "ema_values = [ema.update(c) for c in closes]\n", "\n", "print(\n", " \"SMA last 5:\", [f\"{v:.4f}\" if not np.isnan(v) else \"NaN\" for v in sma_values[-5:]]\n", ")\n", "print(\n", " \"EMA last 5:\", [f\"{v:.4f}\" if not np.isnan(v) else \"NaN\" for v in ema_values[-5:]]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## StreamingRSI" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rsi_stream = StreamingRSI(period=14)\n", "\n", "rsi_values = [rsi_stream.update(c) for c in closes]\n", "finite = [(i, v) for i, v in enumerate(rsi_values) if not np.isnan(v)]\n", "print(f\"First valid RSI at bar {finite[0][0]}: {finite[0][1]:.2f}\")\n", "print(\"RSI last 3:\", [f\"{v:.2f}\" for _, v in finite[-3:]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## StreamingBBands" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bbands = StreamingBBands(period=20)\n", "\n", "bb_results = [bbands.update(c) for c in closes]\n", "# Each result is (upper, middle, lower) or (nan, nan, nan) during warmup\n", "valid_bb = [\n", " (i, u, m, lower) for i, (u, m, lower) in enumerate(bb_results) if not np.isnan(m)\n", "]\n", "if valid_bb:\n", " i, u, m, lower = valid_bb[-1]\n", " print(f\"Latest Bollinger Bands at bar {i}:\")\n", " print(f\" Upper: {u:.4f}\")\n", " print(f\" Middle: {m:.4f}\")\n", " print(f\" Lower: {lower:.4f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## StreamingMACD" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "macd_stream = StreamingMACD(fastperiod=12, slowperiod=26, signalperiod=9)\n", "\n", "macd_results = [macd_stream.update(c) for c in closes]\n", "# Each result is (macd_line, signal, histogram)\n", "valid_macd = [\n", " (i, m, s, h) for i, (m, s, h) in enumerate(macd_results) if not np.isnan(m)\n", "]\n", "if valid_macd:\n", " i, m, s, h = valid_macd[-1]\n", " print(f\"Latest MACD at bar {i}:\")\n", " print(f\" MACD line: {m:.6f}\")\n", " print(f\" Signal: {s:.6f}\")\n", " print(f\" Histogram: {h:.6f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## StreamingATR" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "atr_stream = StreamingATR(period=14)\n", "\n", "atr_values = [atr_stream.update(h, low, c) for h, low, c in zip(highs, lows, closes)]\n", "finite_atr = [v for v in atr_values if not np.isnan(v)]\n", "if finite_atr:\n", " print(f\"Latest ATR: {finite_atr[-1]:.4f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reset and reuse\n", "\n", "All streaming classes support `reset()` to clear internal state and start fresh." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sma.reset()\n", "print(\"After reset, SMA(5.0):\", sma.update(5.0)) # NaN — warm-up restarted\n", "sma.update(6.0)\n", "sma.update(7.0)\n", "sma.update(8.0)\n", "print(\"SMA after 4 bars:\", sma.update(9.0)) # 7.0 = mean of [5,6,7,8,9]" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 4 }