NinjaTrader + OilPriceAPI
The physical market, drawn on your CL and NG charts
Your exchange feed shows every tick of the futures contract and nothing about the physical market behind it. WTI spot assessments, the Waha differential, Western Canadian Select, EIA report cadence - none of it is in the feed. NinjaScript is unsandboxed C#, so an indicator can pull all of it from a REST API and draw it on the chart. This page is the complete wiring.
NinjaTrader® is a trademark of its owner. OilPriceAPI is not affiliated with or endorsed by NinjaTrader; this page documents calling our API from their platform's scripting layer.
1. A spot-plus-basis indicator in one file
Paste this into a new NinjaScript indicator (New > NinjaScript Editor > Indicator), compile, and add it to a CL or MCL chart. Add Newtonsoft.Json.dll under References once (right-click in the editor - the DLL ships with NinjaTrader). On intraday charts (bars of 30 minutes or less) it fetches the WTI spot assessment every 30 minutes and prints spot and the chart-minus-spot basis in the corner of the chart.
// NinjaScript indicator: WTI physical spot + basis vs your CL chart.
// NinjaScript is unsandboxed C#, so standard .NET HTTP works. Polling
// every 30 minutes is 48 requests/day - inside the free tier's 50/day.
// ONE-TIME SETUP: NinjaScript Editor > right-click > References > add
// Newtonsoft.Json.dll (it ships in NinjaTrader's bin folder).
using System;
using System.Net.Http;
using Newtonsoft.Json.Linq;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.DrawingTools;
namespace NinjaTrader.NinjaScript.Indicators
{
public class OilPriceApiSpotBasis : Indicator
{
private static readonly HttpClient Http = new HttpClient();
private DateTime lastFetchUtc = DateTime.MinValue;
private double spot = double.NaN;
[NinjaScriptProperty]
public string ApiKey { get; set; }
[NinjaScriptProperty]
public string Code { get; set; } // e.g. WTI_CRUDE_USD
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "OilPriceApiSpotBasis";
Code = "WTI_CRUDE_USD";
IsOverlay = true;
Calculate = Calculate.OnBarClose;
}
}
protected override void OnBarUpdate()
{
// 30-minute throttle: 48 calls/day, free tier allows 50/day.
if ((DateTime.UtcNow - lastFetchUtc).TotalMinutes >= 30)
{
lastFetchUtc = DateTime.UtcNow;
FetchSpotAsync();
}
if (!double.IsNaN(spot) && CurrentBar > 0)
{
double basis = Close[0] - spot;
Draw.TextFixed(this, "opa_spot",
string.Format("{0} spot {1:F2} | chart-minus-spot {2:+0.00;-0.00}",
Code, spot, basis),
TextPosition.TopRight);
}
}
private async void FetchSpotAsync()
{
try
{
var req = new HttpRequestMessage(HttpMethod.Get,
"https://api.oilpriceapi.com/v1/prices/latest?by_code=" + Code);
req.Headers.TryAddWithoutValidation("Authorization", "Token " + ApiKey);
var resp = await Http.SendAsync(req);
var body = await resp.Content.ReadAsStringAsync();
// Response envelope: {"status":"success","data":{"price":82.13,
// "code":"...","currency":"USD","created_at":"..."}}
var json = JObject.Parse(body);
if ((string)json["status"] == "success")
spot = (double)json["data"]["price"];
}
catch (Exception e)
{
Print("OilPriceAPI fetch failed: " + e.Message);
}
}
}
}The 30-minute throttle is deliberate: 48 requests a day sits inside the free tier's 50-requests-per-day window, so the indicator runs indefinitely on a free key. The budget is per key, not per indicator: two instances doubles the calls, so give a second chart a slower throttle or a paid key. Paid tiers poll as often as their request budget allows.
2. Codes that pair with futures charts
Every code below is served by the same endpoint - swap the Code property on the indicator, or run several instances on one chart.
| API code | Pairs with | What it is |
|---|---|---|
WTI_CRUDE_USD | CL / MCL | WTI spot assessment - the physical side of your futures chart |
BRENT_CRUDE_USD | BRN, Brent-WTI spread work | Brent spot, multi-source |
NATURAL_GAS_USD | NG / MNG | US natural gas benchmark in $/MMBtu |
NATURAL_GAS_WAHA | NG basis trades | Waha hub - the Permian differential that can go negative |
WCS_CRUDE_USD | CL spread context | Western Canadian Select - the heavy-crude differential |
The interesting number is usually the difference, not the level: a CL chart with WTI spot drawn on it shows the physical premium or discount directly, and a Waha overlay on NG shows when the Permian basis detaches from Henry Hub - it has traded negative while the futures stayed positive.
3. EIA report days, without alt-tabbing
The weekly EIA petroleum status report (Wednesdays 10:30 ET) and natural gas storage report (Thursdays 10:30 ET) move CL and NG more than most technical levels. Our WTI and natural gas pages document how the physical series behave around those releases, and the same API serves EIA-derived series you can overlay the same way as the code above.
4. Want this as a packaged add-on instead of source code
We are gauging whether to ship a packaged NinjaTrader add-on - EIA report markers, spot overlays, and basis panels with no C# involved. If you would install that, tell us in one line. Enough hands raised is exactly how it gets built.
Start with a free key
50 requests a day, no card. The indicator above runs on it indefinitely.
Get an API key