207 lines
5.1 KiB
Plaintext
207 lines
5.1 KiB
Plaintext
{
|
|
"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
|
|
}
|