Guide 10 min read

Economic Calendar Trading: How to Automate News-Based Strategies

Learn how to integrate economic calendar data with technical indicators to build news-aware trading strategies using the TickAtlas API.

8Sections
5Code samples
10Min read
GuideCategory

Why the Calendar Matters

NFP, CPI, interest rate decisions — these events move markets more in 5 minutes than technical indicators move them in a week. A trading bot that ignores the economic calendar is flying blind. The TickAtlas API provides calendar data so your strategies can account for upcoming volatility.

This guide covers two approaches: the defensive approach (avoid trading around news) and the offensive approach (trade the news itself).

Fetching Calendar Data

Python Fetching Calendar Data
import requests
from datetime import datetime, timedelta

API_KEY = "your_api_key_here"
BASE_URL = "https://tickatlas.com/v1"
HEADERS = {"X-API-Key": API_KEY}

def get_upcoming_events(hours_ahead: int = 24) -> list[dict]:
    """Fetch economic events in the next N hours."""
    resp = requests.get(f"{BASE_URL}/calendar", params={
        "from": datetime.utcnow().isoformat(),
        "to": (datetime.utcnow() + timedelta(hours=hours_ahead)).isoformat()
    }, headers=HEADERS)
    return resp.json()["data"]["events"]

events = get_upcoming_events(24)
for event in events:
    print(f"{event['datetime']} | {event['currency']} | "
          f"{event['impact']} | {event['event']}")

API Response Format

JSON API Response Format
// GET /v1/calendar?from=2026-03-28T00:00:00Z&to=2026-03-29T00:00:00Z&offset=0&limit=100
{
  "success": true,
  "data": {
    "events": [
      {
        "datetime": "2026-03-28T12:30:00Z",
        "currency": "USD",
        "impact": "high",
        "event": "Non-Farm Payrolls",
        "forecast": "180K",
        "previous": "175K"
      },
      {
        "datetime": "2026-03-28T12:30:00Z",
        "currency": "USD",
        "impact": "high",
        "event": "Unemployment Rate",
        "forecast": "3.8%",
        "previous": "3.9%"
      },
      {
        "datetime": "2026-03-28T09:00:00Z",
        "currency": "EUR",
        "impact": "medium",
        "event": "CPI Flash Estimate",
        "forecast": "2.4%",
        "previous": "2.6%"
      }
    ],
    "pagination": {
      "offset": 0,
      "limit": 100,
      "total": 3,
      "has_more": false
    }
  }
}

Strategy 1: News Avoidance Filter

The simplest and safest approach: do not open new trades within 30 minutes of high-impact events. This prevents your bot from entering positions right before a spike.

Python Strategy 1: News Avoidance Filter
def is_safe_to_trade(symbol: str, buffer_minutes: int = 30) -> bool:
    """Check if any high-impact events are near for this symbol's currencies."""
    # Extract currencies from pair (e.g., EURUSD -> EUR, USD)
    base = symbol[:3]
    quote = symbol[3:]

    events = get_upcoming_events(hours_ahead=1)
    now = datetime.utcnow()

    for event in events:
        if event["impact"] != "high":
            continue
        if event["currency"] not in (base, quote):
            continue

        event_time = datetime.fromisoformat(event["datetime"].replace("Z", ""))
        minutes_until = (event_time - now).total_seconds() / 60

        # Too close to a high-impact event
        if -15 < minutes_until < buffer_minutes:
            print(f"Avoiding {symbol}: {event['event']} in {minutes_until:.0f}min")
            return False

    return True

# Usage in your trading bot
for pair in ["EURUSD", "GBPUSD", "USDJPY"]:
    if is_safe_to_trade(pair):
        # ... run your normal strategy
        pass
    else:
        print(f"Skipping {pair} — news event approaching")

Strategy 2: Pre-News Positioning

Before a major event, check where technical indicators stand. If RSI is already at an extreme and a high-impact event is approaching, the odds of a large move increase.

Python Strategy 2: Pre-News Positioning
def pre_news_analysis(symbol: str) -> dict:
    """Analyze technicals before an upcoming news event."""
    # Fetch current indicators
    ind_resp = requests.get(f"{BASE_URL}/indicators", params={
        "symbol": symbol,
        "timeframe": "H1",
    }, headers=HEADERS)
    data = ind_resp.json()["data"]
    indicators = data["indicators"]

    rsi = indicators["RSI_14"]
    atr = indicators["ATR_14"]
    close = data["ohlcv"]["close"]

    return {
        "symbol": symbol,
        "rsi": rsi,
        "rsi_zone": "oversold" if rsi < 30 else "overbought" if rsi > 70 else "neutral",
        "bb_position": "lower" if close < indicators["BB_lower"] else
                       "upper" if close > indicators["BB_upper"] else "middle",
        "expected_move": atr * 2,  # News events often produce 2x ATR moves
    }

Strategy 3: Post-News Momentum

Wait for the initial spike to settle (15-30 minutes after the event), then check if the move has created a new trend. Trade in the direction of the post-news momentum.

Python Strategy 3: Post-News Momentum
def post_news_momentum(symbol: str) -> str:
    """Check for post-news momentum after a high-impact event."""
    resp = requests.get(f"{BASE_URL}/indicators", params={
        "symbol": symbol,
        "timeframe": "M15",  # Use short timeframe for post-news
    }, headers=HEADERS)

    data = resp.json()["data"]["indicators"]
    rsi = data["RSI_14"]
    macd_hist = data["MACD_hist"]
    adx = data["ADX"]

    # Strong post-news trend: high ADX + aligned RSI and MACD
    if adx > 30:
        if macd_hist > 0 and rsi > 55:
            return "BUY — strong post-news bullish momentum"
        elif macd_hist < 0 and rsi < 45:
            return "SELL — strong post-news bearish momentum"

    return "WAIT — momentum not confirmed yet"

Impact Classification Guide

High Impact

NFP, CPI, interest rate decisions, GDP. Can move majors 50-200 pips. Always avoid or trade with extreme caution.

Medium Impact

PMI, retail sales, employment change. Typical move: 20-50 pips. Consider widening stops around these events.

Low Impact

Consumer confidence, trade balance. Usually less than 20 pips. Safe to trade through in most cases.

Further Reading

Run this against live data.

Every account starts pay-as-you-go with $2.50 of credit and no card. Paste the key into the samples above and the requests work unchanged.

Prefer the API to the article

Build it instead of reading about it.

Create a key, run the first request, then extend one layer at a time. Every account starts pay-as-you-go with $2.50 of credit — no card required.