theme-sticky-logo-alt
img automate macd analysis using n8n workflows candlestick macd analysis

Automate MACD analysis using n8n workflows

Creating a Custom Candlestick and MACD Analysis Tool in n8n

I built a compact workflow that turns raw stock charts into actionable candlestick MACD analysis inside n8n. The goal was simple. Fetch OHLCV data, calculate MACD, flag simple candlestick patterns, and produce tidy data insights that can feed a dashboard or alert. This write-up shows how I did it and the exact pieces I used.

Design and data flow

Keep the data flow linear. Fetch OHLCV. Normalise it. Calculate indicators. Run pattern checks. Emit results. I sketch that as four stages because clarity wins over cleverness.

What data you need

  • Time, open, high, low, close, volume for each bar. I call that OHLCV.
  • A consistent timeframe. Don’t mix minute bars with daily bars inside the same run.
  • A reliable source. Any REST API that returns JSON or CSV will work.

Indicator choices

  • I use standard MACD settings: 12, 26, 9. MACD is the difference between a short EMA and a long EMA. The signal line is an EMA of the MACD. The histogram is MACD minus signal. Those values are simple to compute in a Function node.
  • Candlestick patterns I check for are low-cost and deterministic: bullish engulfing, bearish engulfing, hammer, and shooting star. They are quick to compute and give immediate signals when combined with MACD crossovers.

Data flow in n8n

  • Trigger node: Cron or Webhook. Cron for scheduled batch runs. Webhook for on-demand checks.
  • HTTP Request node: Pull OHLCV from your chosen API. Keep your API key secret. Request only the fields you need.
  • Function node: Convert timestamps to ISO, sort bars ascending, and calculate EMAs, MACD, signal, histogram, and basic candlestick booleans.
  • IF node: Filter bars with the conditions you care about. Examples: bullish engulfing and MACD histogram turning positive on the same bar.
  • Output node: Post to an endpoint, save to Google Sheets, or write a JSON file. I tend to push an annotated CSV to an S3-compatible bucket for later charting.

Why this layout

  • It separates concerns. Fetching belongs to one node. Calculation to another. Decision logic to a third. That makes debugging trivial.
  • n8n nodes are easy to replace. If your API changes, only the HTTP Request node needs work.
  • The Function node keeps the heavy lifting local. That avoids round trips and reduces cost.

Concrete example of checks

  • Bullish signal: bullish engulfing + MACD histogram crossing from negative to positive on the same bar.
  • Bearish signal: bearish engulfing + MACD histogram crossing from positive to negative.
  • Weak signal: MACD histogram small absolute value. Log it but don’t act on it.

Step-by-step n8n implementation and verification

I describe the practical steps I used. Follow them in order. I include a concise JavaScript snippet for the MACD and EMA so you can drop it straight into a Function node.

1) Trigger and fetch

  • Add a Cron node to run at your chosen cadence.
  • Add an HTTP Request node. Point it at a provider that returns OHLCV. Set authentication and query parameters.
  • Map the response to the Function node. Ensure you pass only the array of bars.

2) Normalise and sort

  • In the Function node, coerce timestamps to ISO and sort ascending by time. This avoids off-by-one errors in EMA calculations.

3) EMA and MACD calculation (drop into a Function node)

  • Use the following logic:

function ema(prices, period) {
const k = 2 / (period + 1);
let emaPrev = prices[0];
const out = [emaPrev];
for (let i = 1; i < prices.length; i++) {
const v = prices[i] * k + emaPrev * (1 – k);
out.push(v);
emaPrev = v;
}
return out;
}

const closes = items.map(i => i.json.close);
const emaShort = ema(closes, 12);
const emaLong = ema(closes, 26);
const macd = emaShort.map((v, idx) => v – emaLong[idx]);
const signal = ema(macd, 9);
const hist = macd.map((v, idx) => v – (signal[idx] || 0));

  • Attach MACD, signal and histogram back to each bar object.

4) Candlestick pattern checks

  • Implement deterministic checks. Example for bullish engulfing:

const isBullishEngulfing = (prev, curr) =>
prev.close < prev.open && curr.close > curr.open &&
curr.open < prev.close && curr.close > prev.open;

  • Add booleans for patterns to each bar.

5) Decision logic

  • Use an IF node or continue logic inside the Function node.
  • Condition example: current.hist > 0 and previous.hist <= 0 and isBullishEngulfing(prev, curr).
  • When true, format an output message with timestamp, symbol, pattern, MACD, signal and histogram.

6) Output and storage

  • Output options: webhook POST, plain text file, CSV, spreadsheet row, or push to a time-series database.
  • I favour storing raw annotated OHLCV plus flags. It makes later charting and auditing painless.

Verification steps

  • Test with static sample data. Feed known OHLC sequences where expected MACD values are calculable by hand. Compare results.
  • Visual check: export output to CSV and overlay MACD and pattern flags on a charting tool.
  • Edge cases: missing bars, NaN from short input arrays, and timezone mismatches. Add guards in the Function node that skip insufficient data and log the issue.

Practical tips and pitfalls

  • Use UTC throughout. Local timezones lead to invisible bugs in intraday data.
  • Keep MACD parameters configurable. Different markets may prefer different settings.
  • If your data has gaps, fill or skip the gaps deliberately. EMA is sensitive to gaps.
  • Rate limits: fetch only what you need. Requesting decades of minute data hits limits and costs.
  • For speed, compute EMA iteratively and carry the last EMA forward between runs if you run the workflow frequently.

Concrete output examples

  • Single-row alert: { time: “2025-09-01T09:30:00Z”, symbol: “ABC”, signal: “bullishengulfing + MACDcross”, macd: 0.12, signalLine: 0.05, hist: 0.07 }
  • Daily CSV: time,open,high,low,close,volume,macd,signal,hist,bullishEngulfing,bearishEngulfing

What the tool delivers

  • Automated candlestick MACD analysis on a schedule.
  • Simple decision flags for immediate filtering.
  • Clean, auditable output for further charting or feeding into dashboards.
  • Raw annotated data that supports deeper data insights later.

Takeaways

  • Keep the Function node small and testable. Small functions are easier to validate.
  • Store annotated outputs. It saves hours when you need to prove why a signal fired.
  • MACD plus a single, clear candlestick pattern gives conservative and explainable signals.
  • Use n8n for orchestration, not as a charting service. Push results to the right tool for visualisation.

That is the setup I use. It runs on simple cron schedules, scales with data volume, and makes candlestick MACD analysis repeatable and transparent.

Share:
Category:AI, Lifestyle, Real Life
PREVIOUS POST
Argo CD | v3.1.4
NEXT POST
Understanding APT for Debian-based systems

0 Comment

LEAVE A REPLY

15 49.0138 8.38624 1 1 4000 1 https://lab53.uk 300 1