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 candlestick and MACD analysis inside n8n. It pulls OHLCV data, calculates MACD, checks a few candlestick patterns, and writes out tidy results that can feed a dashboard or alert.

Design and data flow

Keep the flow linear: fetch OHLCV, normalise it, calculate indicators, run pattern checks, then emit the result. That keeps the workflow readable and easier to debug.

What data you need

  • Time, open, high, low, close, volume for each bar. That is OHLCV.
  • A consistent timeframe. Do not mix minute bars with daily bars in the same run.
  • A reliable source. Any REST API that returns JSON or CSV will do.

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. That is straightforward to compute in a Function node.
  • The candlestick patterns I check are low-cost and deterministic: bullish engulfing, bearish engulfing, hammer, and shooting star. They are quick to compute and give clear 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 the 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. For example, 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 works

  • It separates fetching, calculation, and decision logic. That makes debugging easier.
  • n8n nodes are easy to replace. If the 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 with a small absolute value. Log it, but do not act on it.

Step-by-step n8n implementation and verification

I used the steps below. The MACD and EMA logic can go 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. Pass only the array of bars.

2) Normalise and sort

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

3) EMA and MACD calculation

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

  • Use 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 the 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 easier.

Verification steps

  • Test with static sample data. Feed known OHLC sequences where the expected MACD values are calculable by hand. Compare results.
  • Export the output to CSV and overlay MACD and pattern flags on a charting tool.
  • Watch for 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 matter: fetch only what you need. Requesting decades of minute data hits limits and costs more.
  • For speed, compute EMA iteratively and carry the last EMA forward between runs if you run the workflow often.

Concrete output examples

  • Single-row alert: { time: “2025-09-01T09:30:00Z”, symbol: “ABC”, signal: “bullish_engulfing + MACD_cross”, 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 filtering.
  • Clean, auditable output for charting or feeding into dashboards.
  • Raw annotated data that supports later analysis.

Takeaways

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

That is the setup I use. It runs on simple cron schedules, handles more data without much fuss, and makes candlestick MACD analysis repeatable.

Related posts

Vector | vdev-v0.3.3

Vector vdev v0 3 3: patch release with crash, leak and parsing fixes, connector and tooling improvements, upgrade notes on prechecks, rolling updates, compat

Loki | v3.7.2

Loki v3 7 2: security and CVE fixes, updated S3 client to aws sdk v1 97 3, ruler panic fix for unset validation scheme, S3 Object Lock sends SHA256 checksum

Loki | v3.7.2

Loki v3 7 2: Patch release with CVE fixes, AWS S3 SDK update, ruler panic fix, S3 Object Lock SHA256 checksum support