Aggregate Actuals Prices
Aggregate Actuals Prices
This endpoint transforms prices to desired form for a desired electrical entity node in a specified ISO.
Key Parameters: - startdate/enddate: Date filters for the calculation period - curves: Determines what prices to consider (e.g., dam, rtm) - agg: Aggregation operation to apply (e.g., min, max, mean, std, sum) - groupby: Groups the time series by frequency before applying aggregation (e.g., yearly, monthly, daily, hourly) - start_hour/end_hour: Filter by hour range (1-24) - dow: Filter by day of week (mon, tue, wed, thu, fri, sat, sun) - include_nerc_holidays: Include or exclude NERC holidays from the calculation - unit: Desired unit for the results. Note: When unit is specified, agg is forced to 'sum' and groupby is ignored (data is grouped by day). - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (specified electrical entity) |
node | string | Yes | Electrical entity node name |
curves | string | Yes | Comma-separated list of curves to consider (e.g., dam, rtm) or 'all' for all available curves |
agg | string | Yes | Aggregation operation to apply (e.g., min, max, mean, std, sum, median). Note: When 'unit' is specified, agg is forced to 'sum'. |
group_by | string | No | Groups the time series by frequency before applying aggregation (e.g., yearly, monthly, daily, hourly). Note: Ignored when 'unit' is specified. |
start_hour | integer | No | Start hour for filtering (1-24) |
end_hour | integer | No | End hour for filtering (1-24) |
dow | string | No | Comma-separated list of days of the week (mon, tue, wed, thu, fri, sat, sun) |
include_nerc_holidays | boolean | No | Include NERC holidays in the calculation (true), exclude them (false), or ignore holiday filtering (omit parameter) |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). When specified, agg is forced to 'sum' and group_by is ignored. |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
quantile_value | float | No | Value for quantile calculations (when using quantile aggregation, default:0.5) |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/aggregate/?curves=dam&agg=mean&start_date=2023-01-01&end_date=2023-01-31&group_by=day&start_hour=7&end_hour=22&dow=mon,tue,wed,thu,fri&include_nerc_holidays=false&data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/aggregate/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"curves": "dam",
"agg": "mean",
"start_date": "2023-01-01",
"end_date": "2023-01-31",
"group_by": "day",
"start_hour": 7,
"end_hour": 22,
"dow": "mon,tue,wed,thu,fri",
"include_nerc_holidays": False,
"data_format": "json"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[
{"date": "2023-01-01", "value": 15.9141},
{"date": "2023-01-02", "value": 15.2149}
]Calculate Actuals Basis
Calculate Actuals Basis
This endpoint calculates price difference between specified super and sub electrical entities. The super is considered as the hub, and the sub is considered as the node.
Entity Types: - hub: Can be an electrical Hub, Load Zone or Node (super entity) - node: Can be an electrical Load Zone, Node or Bus (sub entity)
Key Parameters: - startdate/enddate: Date filters for the calculation period - curve: Determines what prices to consider (e.g., dam, rtm) - agg: Post calculation operation that returns a single value for the specified date range (e.g., min, max, mean, std) - block_level: Get data in a block level form. Examples of blocks - 7x24 (ATC), 2x16 (Weekend peak hours), 7x8 (Nights), etc.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market |
node | string | Yes | Sub electrical entity (Load Zone, Node or Bus) |
hub | string | Yes | Super electrical entity (Hub, Load Zone or Node) |
curve | string | Yes | Determines what prices to consider (e.g., dam, rtm) |
agg | string | No | Post calculation operation that returns a single value for the specified date range (e.g., min, max, mean, std) |
block_level | boolean | No | Get data in a block level form. Examples: 7x24 (ATC), 2x16 (Weekend peak hours), 7x8 (Nights) |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/basis/?hub=HB_HOUSTON&curve=dam&agg=mean&block_level=false&data_format=json&start_date=2023-01-01&end_date=2023-01-31" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/basis/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"hub": "HB_HOUSTON",
"curve": "dam",
"agg": "mean",
"block_level": False,
"data_format": "json",
"start_date": "2023-01-01",
"end_date": "2023-01-31"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
{
"basis": -1.4997
}Calculate Actuals EOn
Calculate Actuals EOn
This endpoint calculates an SOC feasible Top Bottom Spread for a desired electrical entity node in a specified ISO. SOC feasibility implies charging (bottom) must occur before discharging (top). The results are calculated using an LP (Linear Programming). It is important to note that the TB operation is performed on daily data to give a single value per day, that can be resampled as desired.
Key Parameters: - startdate/enddate: Date filters for the calculation period - curve: Determines what prices to consider (e.g., dam, rtm, dart) - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - cycles: Number of cycles of the hypothetical BESS - chgeff: Charging efficiency of the BESS - dischgeff: Discharging efficiency of the BESS - runfrequency: Optimization window (e.g., daily, monthly) - details: Enable detailed hourly dispatch results - unit: Desired unit for the results - dataformat: Format of the response (json or zip) - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
cycles | float | No | Number of cycles of the hypothetical BESS per day (default: 1.0) |
chg_eff | float | No | Charging efficiency of the BESS (default: 0.94) |
dischg_eff | float | No | Discharging efficiency of the BESS (default: 0.94) |
curve | string | No | Determines what prices to consider (e.g., dam, rtm, dart). Default: dart |
data_format | string | No | Format of the response (json or zip, default: json) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
run_frequency | string | No | Optimization window (daily or monthly, default: daily) |
details | boolean | No | Enable detailed hourly dispatch results in the response (default: false) |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). Default: $/kw-mo. Only applicable when 'run_frequency' is 'daily'. |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/eon/?duration=1.0&cycles=2.0&curve=dart&data_format=json&start_date=2023-01-01&end_date=2023-01-31&run_frequency=daily&details=true&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/eon/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"duration": 1.0,
"cycles": 2.0,
"curve": "dart",
"data_format": "json",
"start_date": "2023-01-01",
"end_date": "2023-01-31",
"run_frequency": "daily",
"details": "true",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
For JSON format:
{
"eon": [
{"date": "2023-01-01", "EOn ($/kw-mo)": 28.13},
{"date": "2023-01-02", "EOn ($/kw-mo)": 36.41}
],
"hourly_results": [
{"date": "2023-01-01 00:00:00", "charging_volume": 0.0, "discharging_volume": 1.0, "charging_revenue": 0.0, "discharging_revenue": 25.50, "total_revenue": 25.50, "total_cycles": 0.5, "soc": 0.0},
{"date": "2023-01-01 01:00:00", "charging_volume": 1.0, "discharging_volume": 0.0, "charging_revenue": 18.75, "discharging_revenue": 0.0, "total_revenue": 18.75, "total_cycles": 1.0, "soc": 1.0}
],
"daily_results": [
{"date": "2023-01-01", "charging_volume": 1.0, "discharging_volume": 1.0, "charging_revenue": 18.75, "discharging_revenue": 25.50, "total_revenue": 44.25, "total_cycles": 1.0}
]
}
For ZIP format:
Returns a ZIP file containing three CSV files:
- eon.csv: Contains daily EOn values
- hourly_results.csv: Contains hourly operational details
- daily_results.csv: Contains daily aggregated resultsCalculate Actuals RPO
Calculate Actuals RPO
This endpoint calculates the Revenue Put Option based on the provided parameters for a desired electrical entity node in a specified ISO. The RPO calculation combines Ancillary Services and TB revenue components.
RPO Calculation Formula: - RPO = tbcomponent + ascomponent - ascomponent= agg(curves included) + offset - tbcomponent = Max(TBi, as_component at the TBi hours) - TBi = TB calculation at the ith level (e.g., TB2nd = TB2 - TB1)
Key Parameters: - startdate/enddate: Date filters for the calculation period - agg: Aggregation method to be used in the RPO calculation - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - unit: Desired unit for the results - data_format: Format of the response - regup/regdown/spin/nonspin/ecrs/reg: Include relevant curves in the calculation - offset: Additional curve to be used in the RPO calculation (e.g., regup, regdown, etc - all AS) - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
agg | string | Yes | Aggregation method to be used in the RPO calculation. Valid values: sum, mean, median, min, max, count, std, var, prod, mad, mode, skew, kurt, nunique, first, last |
regup | boolean | No | Include regup curve in the calculation (default: true). For ERCOT/CAISO/SPP, automatically included when reg=true |
regdown | boolean | No | Include regdown curve in the calculation (default: true). For ERCOT/CAISO/SPP, automatically included when reg=true |
spin | boolean | No | Include spin curve in the calculation (default: true) |
nonspin | boolean | No | Include nonspin curve in the calculation (default: true) |
ecrs | boolean | No | Include ecrs curve in the calculation (default: true) |
reg | boolean | No | Include reg curve in the calculation (default: true). For ERCOT, CAISO, and SPP, automatically includes regup and regdown |
offset | string | No | Additional curve to be used in the RPO calculation (e.g., regup, regdown, etc - all AS) |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
unit | string | No | Desired unit for the results. Valid values: $/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr. Default: $/kw-mo |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/rpo/?duration=1.0&agg=max&start_date=2023-01-01&end_date=2023-06-30®up=true®down=true&offset=ecrs&data_format=json&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/rpo/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"duration": 1.0,
"agg": "max",
"start_date": "2023-01-01",
"end_date": "2023-06-30",
"regup": "true",
"regdown": "true",
"offset": "ecrs",
"data_format": "json",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[{
"date": "2023-01-01T00:00:00",
"RPO ($/kw-mo)": 4.8019,
"as_component": 3604.32,
"tbn_component": 1197.54
}, {
"date": "2023-02-01T00:00:00",
"RPO ($/kw-mo)": 6.9602,
"as_component": 6035.16,
"tbn_component": 925.01
}, {
"date": "2023-03-01T00:00:00",
"RPO ($/kw-mo)": 6.4657,
"as_component": 4753.93,
"tbn_component": 1711.76
}]Calculate Actuals TBn
Calculate Actuals TBn
This endpoint calculates the top bottom spread, representing revenue potential for a desired electrical entity node in a specified ISO. It is important to note that the TB operation is performed on daily data to give a single value per day, that can be resampled as desired.
Key Parameters: - startdate/enddate: Date filters for the calculation period - curve: Determines what prices to consider (e.g., dam, rtm, dart) - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - unit: Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr) - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
curve | string | Yes | Determines what prices to consider (e.g., dam, rtm, dart) |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). Default: $/kw-mo |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/tbn/?duration=1.0&curve=dam&data_format=json&start_date=2023-01-01&end_date=2023-01-31&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/HB_NORTH/tbn/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"duration": 1.0,
"curve": "dam",
"data_format": "json",
"start_date": "2023-01-01",
"end_date": "2023-12-31",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[
{"date": "2023-01-01T00:00:00", "TB1.0 ($/kw-mo)": 1.2203},
{"date": "2023-02-01T00:00:00", "TB1.0 ($/kw-mo)": 0.8892},
{"date": "2023-03-01T00:00:00", "TB1.0 ($/kw-mo)": 1.701},
{"date": "2023-04-01T00:00:00", "TB1.0 ($/kw-mo)": 1.753},
{"date": "2023-05-01T00:00:00", "TB1.0 ($/kw-mo)": 1.9475},
{"date": "2023-06-01T00:00:00", "TB1.0 ($/kw-mo)": 7.9343},
{"date": "2023-07-01T00:00:00", "TB1.0 ($/kw-mo)": 5.8335},
{"date": "2023-08-01T00:00:00", "TB1.0 ($/kw-mo)": 42.5852},
{"date": "2023-09-01T00:00:00", "TB1.0 ($/kw-mo)": 10.2563},
{"date": "2023-10-01T00:00:00", "TB1.0 ($/kw-mo)": 3.6226},
{"date": "2023-11-01T00:00:00", "TB1.0 ($/kw-mo)": 2.8613},
{"date": "2023-12-01T00:00:00", "TB1.0 ($/kw-mo)": 0.9403}
]Multi-node Aggregate Insights
Multi-node Aggregate Insights
Compute cross-node insights over a window of historical actuals for a group of nodes in one ISO. Companion to the single-node Aggregate Actuals Prices endpoint: this collapses many nodes into comparison analytics rather than returning raw rows. Actuals only, JSON only, whole window aggregated in one response (no pagination).
Insight blocks: - pernodestats: per node x curve -> mean/median/min/max/std/p25/p75/count (all requested curves) - ranking: nodes ranked by mean of focuscurve, with best/worst and spread (max mean - min mean) - correlation: pairwise Pearson matrix on focuscurve, aligned on (date, repeatedhourflag); omittednodes lists nodes lacking focuscurve - volatility: per node x curve std and cv (std/mean; null when mean ~ 0), plus meandailyspread on focus_curve
Partial results: unknown/empty nodes are skipped and reported in nodes.errors; they never fail the request. 404 only when no node produced data; 400 on validation errors (missing/empty nodes, node cap, bad freq, enddate < startdate, focus_curve not in curves).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (path parameter): ercot, caiso, isone, miso, nyiso, pjm |
nodes | string | Yes | Comma-separated list of node names (e.g. 'HB_NORTH,HB_WEST'). Max 50 (MAX_COMPARE_NODES). Duplicates/aliases deduped. |
start_date | string | Yes | Window start (YYYY-MM-DD). Must be <= end_date. |
end_date | string | Yes | Window end (YYYY-MM-DD). |
curves | string | No | Comma-separated curves (e.g. 'dam,rtm'). Default 'all' expands to the ISO default set. Duplicates deduped. per_node_stats and volatility cover every requested curve. |
focus_curve | string | No | Single curve used by ranking and correlation. Default = first resolved curve (usually 'dam'). Must be one of the resolved curves, else 400. |
data_frequency | string | No | Source granularity: 1h, 5m, 15m (default 1H). |
resample_frequency | string | No | Resample target, ' |
apply_exclusion | boolean | No | Apply Katana exclusion-date masking on underlying prices (default true). |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/history/ercot/nodes/aggregate/?nodes=HB_NORTH,HB_WEST&curves=dam,rtm&focus_curve=dam&start_date=2024-01-01&end_date=2024-12-31" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/history/ercot/nodes/aggregate/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"nodes": "HB_NORTH,HB_WEST",
"curves": "dam,rtm",
"focus_curve": "dam",
"start_date": "2024-01-01",
"end_date": "2024-12-31"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
{
"iso": "ercot",
"curves": ["dam", "rtm"],
"focus_curve": "dam",
"window": {"start": "2024-01-01", "end": "2024-12-31"},
"nodes": {
"returned": ["HB_NORTH", "HB_WEST"],
"errors": {"BADNODE": "node not found"}
},
"insights": {
"per_node_stats": {
"HB_NORTH": {"dam": {"mean": 30.1, "median": 28.0, "min": -5.0, "max": 250.0, "std": 22.4, "p25": 18.0, "p75": 38.0, "count": 8760}}
},
"ranking": {"focus_curve": "dam", "by_mean": [{"node": "HB_WEST", "mean": 31.7}, {"node": "HB_NORTH", "mean": 30.1}], "best": "HB_WEST", "worst": "HB_NORTH", "spread": 1.6},
"correlation": {"focus_curve": "dam", "matrix": {"HB_NORTH": {"HB_NORTH": 1.0, "HB_WEST": 0.94}, "HB_WEST": {"HB_NORTH": 0.94, "HB_WEST": 1.0}}},
"volatility": {"HB_NORTH": {"dam": {"std": 22.4, "cv": 0.74}, "mean_daily_spread": 41.2}}
}
}Aggregate Forward Prices
Aggregate Forward Prices
This endpoint transforms prices to desired form for a desired electrical entity node in a specified ISO.
Key Parameters: - refdate: Reference date for generation of futures (query parameter) - exchange: Exchange of the futures - startdate/enddate: Date filters for the calculation period - curves: Determines what prices to consider (e.g., dam, rtm) - agg: Aggregation operation to apply (e.g., min, max, mean, std, sum) - groupby: Groups the time series by frequency before applying aggregation (e.g., yearly, monthly, daily, hourly) - start_hour/end_hour: Filter by hour range (1-24) - dow: Filter by day of week (mon, tue, wed, thu, fri, sat, sun) - include_nerc_holidays: Include or exclude NERC holidays from the calculation - unit: Desired unit for the results. Note: When unit is specified, agg is forced to 'sum' and groupby is ignored (data is grouped by day). - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
refdate | string | Yes | Reference date for generation of futures in YYYY-MM-DD format (query parameter) |
curves | string | Yes | Comma-separated list of curves to consider (e.g., dam, rtm) or 'all' for all available curves |
agg | string | Yes | Aggregation operation to apply (e.g., min, max, mean, std, sum, median). Note: When 'unit' is specified, agg is forced to 'sum'. |
exchange | string | No | Exchange of the futures (default: IFED) |
group_by | string | No | Groups the time series by frequency before applying aggregation (e.g., yearly, monthly, daily, hourly). Note: Ignored when 'unit' is specified. |
start_hour | integer | No | Start hour for filtering (1-24) |
end_hour | integer | No | End hour for filtering (1-24) |
dow | string | No | Comma-separated list of days of the week (mon, tue, wed, thu, fri, sat, sun) |
include_nerc_holidays | boolean | No | Include NERC holidays in the calculation (true), exclude them (false), or ignore holiday filtering (omit parameter) |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). When specified, agg is forced to 'sum' and group_by is ignored. |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
quantile_value | float | No | Value for quantile calculations (when using quantile aggregation, default:0.5) |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/aggregate/?refdate=2025-06-09&curves=dam&agg=mean&start_date=2025-07-01&end_date=2025-07-31&group_by=day&start_hour=7&end_hour=22&dow=mon,tue,wed,thu,fri&include_nerc_holidays=false&exchange=IFED&data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/aggregate/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"refdate": "2025-06-09",
"curves": "dam",
"agg": "mean",
"start_date": "2025-07-01",
"end_date": "2025-07-31",
"group_by": "day",
"start_hour": 7,
"end_hour": 22,
"dow": "mon,tue,wed,thu,fri",
"include_nerc_holidays": False,
"exchange": "IFED",
"data_format": "json"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[
{"date": "2023-01-01", "value": 15.9141},
{"date": "2023-01-02", "value": 15.2149}
]Calculate Forward EOn
Calculate Forward EOn
This endpoint calculates an SOC feasible Top Bottom Spread for a desired electrical entity node in a specified ISO. SOC feasibility implies charging (bottom) must occur before discharging (top). The results are calculated using an LP (Linear Programming). It is important to note that the TB operation is performed on daily data to give a single value per day, that can be resampled as desired.
Key Parameters: - refdate: Reference date for generation of futures (query parameter) - exchange: Exchange of the futures - startdate/enddate: Date filters for the calculation period - curve: Determines what prices to consider (e.g., dam, rtm, dart) - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - cycles: Number of cycles of the hypothetical BESS - chgeff: Charging efficiency of the BESS - dischgeff: Discharging efficiency of the BESS - degradation: Annual duration degradation rate applied to the battery - runfrequency: Optimization window (e.g., daily, monthly) - details: Enable detailed hourly dispatch results - unit: Desired unit for the results - dataformat: Format of the response - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
refdate | string | Yes | Reference date for generation of futures in YYYY-MM-DD format (query parameter) |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
cycles | float | No | Number of cycles of the hypothetical BESS per day (default: 1.0) |
chg_eff | float | No | Charging efficiency of the BESS (default: 0.94) |
dischg_eff | float | No | Discharging efficiency of the BESS (default: 0.94) |
degradation | float | No | Annual duration degradation rate applied to the battery (percentage expressed as a decimal). |
curve | string | No | Determines what prices to consider (e.g., dam, rtm, dart). Default: dart |
exchange | string | No | Exchange of the futures (default: IFED) |
data_format | string | No | Format of the response (json or zip, default: json) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
run_frequency | string | No | Optimization window (daily or monthly, default: daily) |
details | boolean | No | Enable detailed hourly dispatch results in the response (default: false) |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). Default: $/kw-mo. Only applicable when 'run_frequency' is 'daily'. |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/eon/?refdate=2025-06-09&duration=1.0&cycles=2.0&curve=dart&exchange=IFED&data_format=json&start_date=2025-01-01&end_date=2027-12-31&run_frequency=daily&details=true&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/eon/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"refdate": "2025-06-09",
"duration": 1.0,
"cycles": 2.0,
"curve": "dart",
"exchange": "IFED",
"data_format": "json",
"start_date": "2025-01-01",
"end_date": "2027-12-31",
"run_frequency": "daily",
"details": "true",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
For JSON format:
{
"eon": [
{"date": "2023-01-01", "EOn ($/kw-mo)": 28.13},
{"date": "2023-01-02", "EOn ($/kw-mo)": 36.41}
],
"hourly_results": [
{"date": "2023-01-01 00:00:00", "charging_volume": 0.0, "discharging_volume": 1.0, "charging_revenue": 0.0, "discharging_revenue": 25.50, "total_revenue": 25.50, "total_cycles": 0.5, "soc": 0.0},
{"date": "2023-01-01 01:00:00", "charging_volume": 1.0, "discharging_volume": 0.0, "charging_revenue": 18.75, "discharging_revenue": 0.0, "total_revenue": 18.75, "total_cycles": 1.0, "soc": 1.0}
],
"daily_results": [
{"date": "2023-01-01", "charging_volume": 1.0, "discharging_volume": 1.0, "charging_revenue": 18.75, "discharging_revenue": 25.50, "total_revenue": 44.25, "total_cycles": 1.0}
]
}
For ZIP format:
Returns a ZIP file containing three CSV files:
- eon.csv: Contains daily EOn values
- hourly_results.csv: Contains hourly operational details
- daily_results.csv: Contains daily aggregated resultsCalculate Forward RPO
Calculate Forward RPO
This endpoint calculates the Revenue Put Option based on the provided parameters for a desired electrical entity node in a specified ISO. The RPO calculation combines Ancillary Services and TB revenue components.
RPO Calculation Formula: - RPO = tbcomponent + ascomponent - ascomponent= agg(curves included) + offset - tbcomponent = Max(TBi, as_component at the TBi hours) - TBi = TB calculation at the ith level (e.g., TB2nd = TB2 - TB1)
Key Parameters: - refdate: Reference date for generation of futures (query parameter) - exchange: Exchange of the futures - startdate/enddate: Date filters for the calculation period - agg: Aggregation method to be used in the RPO calculation - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - unit: Desired unit for the results - data_format: Format of the response - regup/regdown/spin/nonspin/ecrs/reg: Include relevant curves in the calculation - offset: Additional curve to be used in the RPO calculation (e.g., regup, regdown, etc - all AS) - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
refdate | string | Yes | Reference date for generation of futures in YYYY-MM-DD format (query parameter) |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
agg | string | Yes | Aggregation method to be used in the RPO calculation. Valid values: sum, mean, median, min, max, count, std, var, prod, mad, mode, skew, kurt, nunique, first, last |
regup | boolean | No | Include regup curve in the calculation (default: true). For ERCOT/CAISO/SPP, automatically included when reg=true |
regdown | boolean | No | Include regdown curve in the calculation (default: true). For ERCOT/CAISO/SPP, automatically included when reg=true |
spin | boolean | No | Include spin curve in the calculation (default: true) |
nonspin | boolean | No | Include nonspin curve in the calculation (default: true) |
ecrs | boolean | No | Include ecrs curve in the calculation (default: true) |
reg | boolean | No | Include reg curve in the calculation (default: true). For ERCOT, CAISO, and SPP, automatically includes regup and regdown |
exchange | string | No | Exchange of the futures (default: IFED) |
offset | string | No | Additional curve to be used in the RPO calculation (e.g., regup, regdown, etc - all AS) |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
unit | string | No | Desired unit for the results. Valid values: $/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr. Default: $/kw-mo |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/rpo/?refdate=2025-06-09&duration=1.0&agg=max&start_date=2025-07-01&end_date=2025-12-31®up=true®down=true&offset=ecrs&data_format=json&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/rpo/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"refdate": "2025-06-09",
"duration": 1.0,
"agg": "max",
"start_date": "2025-07-01",
"end_date": "2025-12-31",
"regup": "true",
"regdown": "true",
"offset": "ecrs",
"data_format": "json",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[{
"date": "2023-01-01T00:00:00",
"RPO ($/kw-mo)": 4.8019,
"as_component": 3604.32,
"tbn_component": 1197.54
}, {
"date": "2023-02-01T00:00:00",
"RPO ($/kw-mo)": 6.9602,
"as_component": 6035.16,
"tbn_component": 925.01
}, {
"date": "2023-03-01T00:00:00",
"RPO ($/kw-mo)": 6.4657,
"as_component": 4753.93,
"tbn_component": 1711.76
}]Calculate Forward TBn
Calculate Forward TBn
This endpoint calculates the top bottom spread, representing revenue potential for a desired electrical entity node in a specified ISO. It is important to note that the TB operation is performed on daily data to give a single value per day, that can be resampled as desired.
Key Parameters: - refdate: Reference date for generation of futures (query parameter) - exchange: Exchange of the futures (default: IFED) - startdate/enddate: Date filters for the calculation period - curve: Determines what prices to consider (e.g., dam, rtm, dart) - duration: Duration of the hypothetical BESS (Battery Energy Storage System) - unit: Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr) - step: Whether to return step data (default: false)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the specified electrical entity market |
node | string | Yes | Desired electrical entity node name |
refdate | string | Yes | Reference date for generation of futures in YYYY-MM-DD format (query parameter) |
duration | float | Yes | Duration of the hypothetical BESS (Battery Energy Storage System) in hours |
curve | string | Yes | Determines what prices to consider (e.g., dam, rtm, dart) |
exchange | string | No | Exchange of the futures (default: IFED) |
data_format | string | No | Format of the response (json or csv) |
start_date | string | Yes | Start date filter for the calculation period in YYYY-MM-DD format |
end_date | string | Yes | End date filter for the calculation period in YYYY-MM-DD format |
unit | string | No | Desired unit for the results ($/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr). Default: $/kw-mo |
step | boolean | No | Whether to return step data (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/tbn/?refdate=2025-06-09&duration=1.0&curve=dam&exchange=IFED&data_format=json&start_date=2025-07-01&end_date=2025-12-31&unit=$/kw-mo" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/futures/ercot/HB_NORTH/tbn/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"refdate": "2025-06-09",
"duration": 1.0,
"curve": "dam",
"exchange": "IFED",
"data_format": "json",
"start_date": "2025-07-01",
"end_date": "2025-12-31",
"unit": "$/kw-mo"
}
response = requests.get(url, params=params, headers=headers)
print(response.json())Response
[
{"date": "2023-01-01T00:00:00", "TB1.0 ($/kw-mo)": 1.2203},
{"date": "2023-02-01T00:00:00", "TB1.0 ($/kw-mo)": 0.8892},
{"date": "2023-03-01T00:00:00", "TB1.0 ($/kw-mo)": 1.701},
{"date": "2023-04-01T00:00:00", "TB1.0 ($/kw-mo)": 1.753}
]Calculate CYCn (Annual Cycle Revenue Optimizer)
Calculate CYCn (Annual Cycle Revenue Optimizer)
This endpoint calculates revenue through optimizing battery operations across annual cycles to maximize revenue.
Requirements: - You will have to provide daily revenue numbers along with cycle counts for all possible cycle scenarios (1 through max_cycles) in a CSV file - Max Cycles = CEIL(24 / 2 / duration) - The API returns optimized revenue and cycle counts within the annual cycle limit
Key Parameters: - annualcycles: Upper bound on maximum number of cycles per year - dataformat: Format of the response (json or csv)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
annual_cycles | integer | Yes | Upper bound on maximum number of cycles per year (passed in URL path) |
file | file | Yes | CSV file containing daily revenue numbers along with cycle counts for all possible cycle scenarios (1 through max_cycles). Columns: date, rev_X_cycle, count_X_cycle (where X is cycle numbers from 1 to max_cycles) |
data_format | string | No | Format of the response (json or csv, default: json) |
Example Request
curl -X POST "https://beast.batteryos.dev/api/v1/analysis/cycn/500/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}" \
-F "file=@/path/to/cycle_data.csv" \
-F "data_format=json"import requests
url = "https://beast.batteryos.dev/api/v1/analysis/cycn/500/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
files = {
"file": open("/path/to/cycle_data.csv", "rb")
}
data = {
"data_format": "json"
}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())Response
[
{
"date": "2023-01-01",
"total_revenue": 1250.75,
"total_cycles": 2.5
},
{
"date": "2023-01-02",
"total_revenue": 980.25,
"total_cycles": 1.8
}
]Compare Contract Prices
Compare Contract Prices
This endpoint compares contract prices from one exchange with forward prices from another exchange for the same delivery period. The comparison includes the price difference in both absolute and percentage terms. This is useful for analyzing price disparities between different sources.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
contract_exchange | string | Yes | Exchange code (MIC) for the contract |
symbol | string | Yes | Contract symbol |
price_exchange | string | Yes | Exchange code (MIC) to compare prices against |
refdate | string | Yes | Reference date in YYYY-MM-DD format |
data_format | string | No | Format of the response (json or csv, default: json) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/kronos/compare/IFED/EVN/IFED/2024-06-01/?data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/kronos/compare/IFED/EVN/IFED/2024-06-01/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"data_format": "json"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())Response
[
{
"fordate": "2024-07-01",
"price_contract": 45.78,
"price_forward": 46.25,
"delta": 0.47,
"diff%": 1.03
},
{
"fordate": "2024-08-01",
"price_contract": 53.91,
"price_forward": 52.80,
"delta": -1.11,
"diff%": -2.06
}
]Get Contract Data
Get Contract Data
This endpoint retrieves contract price data for a specific contract. If date parameters are provided, it returns the contract prices for those dates. Otherwise, it returns the available dates for the contract. The endpoint supports strip pattern processing for contract data and can return results in either JSON or CSV format.
When using strip parameter, if startref and endref are not provided, the API will return results for the entire available reference date range.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
exchange_code | string | Yes | Exchange code (MIC) |
symbol | string | Yes | Contract symbol |
refdate | string | No | Reference date in YYYY-MM-DD format |
fordate | string | No | Forward date in YYYY-MM-DD format |
startref | string | No | Start reference date in YYYY-MM-DD format. Optional when using strip parameter. |
endref | string | No | End reference date in YYYY-MM-DD format. Optional when using strip parameter. |
strip | string | No | Strip pattern for processing contract data. Supports multiple formats: - Month codes: N25 (July 2025), NQ25 (July-Aug 2025), N25Q25 (Jul-Aug 2025) - Date strings: 20250701, 20250701_20250801 - Combined patterns: N25+Q25 (July 2025 and August 2025) ICE Month Codes: - F: January - G: February - H: March - J: April - K: May - M: June - N: July - Q: August - U: September - V: October - X: November - Z: December |
freq | string | No | Frequency for filtering data based on date patterns. Available options: - sow: Start of week (Monday) - eow: End of week (Friday) - som: First Monday of month - eom: Last Friday of month - soq: First Monday of quarter - eoq: Last Friday of quarter - soy: First Monday of year - eoy: Last Friday of year |
step | boolean | No | Whether to create step data by duplicating with shifted values (default: false) |
data_format | string | No | Response format (json or csv) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/kronos/contracts/IFED/EVN/?strip=Q1_2024-01-01_2024-03-31&freq=som&step=true&data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/kronos/contracts/IFED/EVN/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
# Example using month codes
params = {
"strip": "NQ25", # July and August 2025
"startref": "2024-03-20", # Optional: start reference date
"endref": "2024-03-31", # Optional: end reference date
"freq": "som", # Optional: filter data to first Monday of each month
"step": "true", # Optional: create step data
"data_format": "json"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())Response
For specific dates:
[
{
"exchange": "IFED",
"symbol": "EVN",
"refdate": "2024-03-20",
"fordate": "2024-03-01",
"price": "24.89",
"open": null,
"high": null,
"low": null,
"close": null,
"volume": 0,
"open_interest": 1050
}
]
For available dates:
[
{
"refdate": "2022-10-07",
"min_fordate": "2022-09-01",
"max_fordate": "2034-12-01"
}
]
For strip pattern processing:
[
{
"refdate": "2024-03-20",
"NQ25": 25.45
},
{
"refdate": "2024-03-21",
"NQ25": 25.12
}
]List Contracts by Exchange
List Contracts by Exchange
This endpoint retrieves a list of all available contracts for a specific exchange. Contracts can be filtered by various attributes using optional query parameters.
Filter Parameters: - iso: Filter by ISO code (case-insensitive) - node: Filter by node name (case-insensitive) - dart_mode: Filter by day-ahead/real-time mode (case-insensitive) - settlement: Filter by settlement type (case-insensitive)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
exchange_code | string | Yes | Exchange code (MIC) |
iso | string | No | Filter by ISO code (e.g., ERCOT, PJM, CAISO). Case-insensitive. |
node | string | No | Filter by node name (e.g., HB_NORTH, HB_WEST). Case-insensitive. |
dart_mode | string | No | Filter by day-ahead/real-time mode (e.g., Day Ahead, Real Time). Case-insensitive. |
settlement | string | No | Filter by settlement type (e.g., Daily, Monthly). Case-insensitive. |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/kronos/contracts/IFED/?iso=ercot&node=HB_NORTH&dart_mode=Day%20Ahead&settlement=Daily" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/kronos/contracts/IFED/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
# Optional: Add filter parameters
params = {
"iso": "ercot",
"node": "HB_NORTH",
"dart_mode": "Day Ahead",
"settlement": "Daily"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())Response
[
{
"symbol": "NDC",
"name": "ERCOT North 345KV Hub Day-Ahead Off-Peak Daily Fixed Price Future",
"url": "https://www.ice.com/products/6590494",
"iso": "ERCOT",
"node": "HB_NORTH",
"shape": "OffPeak",
"fo_type": "Future",
"phys_type": "Financial",
"dart_mode": "Day Ahead",
"settlement": "Daily"
},
{
"symbol": "NDA",
"name": "ERCOT North 345KV Hub Day-Ahead Peak Daily Fixed Price Future",
"url": "https://www.ice.com/products/6590466",
"iso": "ERCOT",
"node": "HB_NORTH",
"shape": "Peak",
"fo_type": "Future",
"phys_type": "Financial",
"dart_mode": "Day Ahead",
"settlement": "Daily"
}
]List Exchanges
List Exchanges
This endpoint retrieves a list of all available exchanges.
Parameters
| Name | Type | Required | Description |
|---|
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/kronos/contracts/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/kronos/contracts/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
response = requests.get(url, headers=headers)
print(response.json())Response
[
{
"mic": "IFED",
"name": "Intercontinental Exchange",
"url": "https://www.theice.com/"
},
{
"mic": "IFED",
"name": "Chicago Mercantile Exchange",
"url": "https://www.cmegroup.com/"
}
]Get Historical Data
Get Historical Price Data
This endpoint retrieves historical price data based on the provided parameters. The response can be either a JSON object or a ZIP file containing the data in CSV format.
If merge=true and multiple curves are requested, all curves will be merged into a single dataframe with the format ISO_NODE.csv.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market |
node | string | Yes | Node name |
resample_frequency | string | No | Resample target, ' |
data_frequency | string | No | Data frequency (default: '1H') |
node_type | string | No | Type of the node |
curve_type | string | No | Type of the curve |
curves | array | No | List of curves to retrieve |
years | array | No | List of years to retrieve data for |
merge | boolean | No | Whether to merge multiple curves into one dataframe |
format | string | No | Response format (json or zip, default: json) |
Example Request
curl -X POST "https://beast.batteryos.dev/api/v1/prices/history/ercot/HB_NORTH/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}" \
-F "curves=dam" \
-F "curves=rtm" \
-F "years=2023" \
-F "years=2024" \
-F "data_frequency=1H" \
-F "merge=true" \
-F "format=json"import requests
url = "https://beast.batteryos.dev/api/v1/prices/history/ercot/HB_NORTH/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
data = [
('curves', 'dam'),
('curves', 'rtm'),
('years', '2023'),
('years', '2024'),
('data_frequency', '1H'),
('merge', 'true'),
('format', 'json')
]
response = requests.post(url, headers=headers, data=data)
print(response.json())Response
For JSON format:
{
"ERCOT_HB_NORTH": [
{
"date": "2025-01-01T00:00:00",
"dam": 22.85,
"rtm": 18.0708,
"repeated_hour_flag": 0
},
{
"date": "2025-01-01T01:00:00",
"dam": 20.9,
"rtm": 17.6833,
"repeated_hour_flag": 0
}
],
"dirty_data": []
}
or
ZIP file containing CSV files with the historical price dataGet Multi-node Historical Prices
Get Multi-node Historical Prices
Retrieve historical actuals for a group of nodes in one call (single ISO, single curve), nested per node. Built for comparison and as a base for higher-level operations. The single-node historical endpoint is unchanged.
Time window: provide either years (contiguous) or a start/end date range; start/end wins when both are present. Pagination (JSON): results are calendar chunks. Omit cursor for page 1, then repeat with cursor = meta.next_cursor until meta.has_more is false. format=zip returns the full window (one CSV per node) and ignores paging. Bad nodes: unknown/empty nodes are skipped and listed in meta.errors — they never fail the request. Only a malformed request or exceeding the node cap (MAXCOMPARENODES, default 50) returns 400.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (path parameter): ercot, caiso, isone, miso, nyiso, pjm |
curve | string | Yes | Single curve, e.g. dam, rtm |
nodes | array[string] | Yes | JSON array of node names (not CSV). Max 50 (MAX_COMPARE_NODES). Duplicates/aliases deduped. Response keys are the curated (uppercased) node names. |
start | string | No | Window start (YYYY-MM-DD). With end, defines the window; wins over years. |
end | string | No | Window end (YYYY-MM-DD). Required if start given; start <= end. |
years | array[string] | No | e.g. ["2023","2024"]. Used only if start/end absent. Must be contiguous (no gaps). |
page_span | string | No | JSON page size: month (default), week, or day. |
cursor | string | No | Start of the page to fetch (YYYY-MM-DD). Must fall inside the window. See pagination. |
format | string | No | json (default, paged) or zip (full window, one CSV per node). |
resample_frequency | string | No | Resample target, ' |
data_frequency | string | No | Source granularity (default 1H). |
node_type | string | No | Optional node-type filter. |
curve_type | string | No | Optional curve-type filter. |
market_type | string | No | Optional market-type filter. |
apply_exclusion | boolean | No | Apply Katana exclusion-date masking (default true). Only literal false disables it. |
Example Request
curl -X POST "https://beast.batteryos.dev/api/v1/prices/history/ercot/nodes/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"curve":"dam","nodes":["HB_NORTH","HB_WEST"],"start":"2024-01-01","end":"2024-03-31"}'import requests
url = "https://beast.batteryos.dev/api/v1/prices/history/ercot/nodes/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}",
"Content-Type": "application/json"
}
payload = {
"curve": "dam",
"nodes": ["HB_NORTH", "HB_WEST"],
"start": "2024-01-01",
"end": "2024-03-31"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
{
"iso": "ercot",
"curve": "dam",
"data": {
"HB_NORTH": [
{"date": "2024-01-01T00:00:00", "dam": 22.1, "repeated_hour_flag": 0},
{"date": "2024-01-01T01:00:00", "dam": 19.4, "repeated_hour_flag": 0}
],
"HB_WEST": []
},
"meta": {
"window": {"start": "2024-01-01", "end": "2024-01-31"},
"next_cursor": "2024-02-01",
"has_more": true,
"page_span": "month",
"returned_nodes": ["HB_NORTH", "HB_WEST"],
"errors": {"BADNODE": "node not found"}
}
}
or, with format=zip: a ZIP of one CSV per node (<ISO>_<NODE>.csv) for the full window.Get Forwards Data
Get Forwards Data
This endpoint retrieves forward curve data. If the requested data is already available, it returns a ZIP file containing the data. If the data is not yet calculated, it enqueues the request and returns a JSON response with a slug to track the status.
Note: If a refdate is provided in the params array for a specific curve, it will override the refdate provided in the URL parameters for that curve.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (lowercase) |
node | string | Yes | Node name (uppercase) |
refdate | string | Yes | Default reference date in YYYY-MM-DD format |
params | array | Yes | Array of parameter objects containing: curve (required, string, e.g. 'dam'), exchange (required, string), method (optional, string, enum: ['basic', 'bos_adjusted'], default: 'basic'), refdate (optional, string, YYYY-MM-DD format - overrides URL refdate) |
merge | boolean | No | Whether to merge multiple curves into one (default: false) |
force | boolean | No | Whether to force recalculation (default: false) |
details | boolean | No | Whether to include additional details in response (default: false) |
Example Request
curl -X POST "https://beast.batteryos.dev/api/v1/prices/futures/ercot/HB_NORTH/2025-06-09/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"params": [
{
"curve": "dam",
"exchange": "IFED",
"method": "basic",
"refdate": "2025-06-08"
},
{
"curve": "dam",
"exchange": "IFED",
"method": "basic"
}
],
"merge": false,
"force": false,
"details": false
}'import requests
import json
url = "https://beast.batteryos.dev/api/v1/prices/futures/ercot/HB_NORTH/2025-06-09/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}",
"Content-Type": "application/json"
}
data = {
"params": [
{
"curve": "dam",
"exchange": "IFED",
"method": "basic",
"refdate": "2025-06-08"
},
{
"curve": "dam",
"exchange": "IFED",
"method": "basic"
}
],
"merge": False,
"force": False,
"details": False
}
response = requests.post(url, headers=headers, data=json.dumps(data))
print(response.json())Response
If data is available:
Returns a ZIP file containing the forward curves data.
If calculation is pending:
{
"slug": "forward-request-slug",
"status": "calc_requested"
}Get Scenario Status
Get Scenario Status
Returns the current status of a scenario calculation request. Poll this endpoint after receiving a slug from EO500 or CO500 to determine when results are ready.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Scenario request slug returned by the EO500 or CO500 endpoint |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/scenario/abc123xyz/status/" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/scenario/abc123xyz/status/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
response = requests.get(url, headers=headers)
print(response.json())Response
{
"status": "Results Processed"
}
Possible status values: Received, Calc Requested, Data Requested, Data Received, Data Error, Results Processed, Results ErrorRun COnCYC500 Scenario
Run COnCYC500 Scenario (Co-optimized, 500 cycles/yr)
Runs a co-optimized battery dispatch (energy + ancillary services jointly) capped at 500 annual cycles. Returns results immediately when already computed; otherwise enqueues and returns a slug to poll.
Modes (provide one combination): - Futures: exchange + refdate — forward price period - Historical: start_date + end_date — actuals-only period - Combo: all four — actuals up to refdate stitched to forward prices
Key Parameters: - duration: Battery duration in hours (default: 4 h) - chgeff / dischgeff: Charging and discharging efficiency (default: 0.94) - data_format: json (default) or zip
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (e.g. ercot, caiso, pjm) |
node | string | Yes | Electrical entity node name (e.g. HB_NORTH) |
exchange | string | No | Exchange code required for futures/combo mode (e.g. IFED, BOS) |
refdate | string | No | Forward curve reference date in YYYY-MM-DD format. Required for futures/combo mode. |
start_date | string | No | Start date in YYYY-MM-DD format. Required for historical/combo mode. |
end_date | string | No | End date in YYYY-MM-DD format. Required for historical/combo mode. |
duration | float | No | Battery duration in hours (default: 4.0) |
chg_eff | float | No | Charging efficiency (default: 0.94, range: 0.0-1.0) |
dischg_eff | float | No | Discharging efficiency (default: 0.94, range: 0.0-1.0) |
data_format | string | No | Response format: json (default) or zip |
unit | string | No | Convert revenue to desired unit. Options: $/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/scenario/concyc500/ercot/HB_NORTH/?exchange=IFED&refdate=2025-06-15&duration=4&chg_eff=0.94&dischg_eff=0.94&data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/scenario/concyc500/ercot/HB_NORTH/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"exchange": "IFED",
"refdate": "2025-06-15",
"duration": 4,
"chg_eff": 0.94,
"dischg_eff": 0.94,
"data_format": "json"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())Response
When results are ready (JSON):
[
{"date": "2025-07-01", "revenue": 14230.50, "cycles": 1.8},
{"date": "2025-08-01", "revenue": 19870.00, "cycles": 2.0}
]
For ZIP format:
Returns a ZIP file containing results.csv with the same data.
When calculation is pending:
{
"slug": "abc123xyz",
"message": "Received"
}Run EOnCYC500 Scenario
Run EOnCYC500 Scenario (Energy Only, 500 cycles/yr)
Runs an energy-only battery dispatch optimisation capped at 500 annual cycles. Returns results immediately when already computed; otherwise enqueues and returns a slug to poll.
Modes (provide one combination): - Futures: exchange + refdate — forward price period - Historical: start_date + end_date — actuals-only period - Combo: all four — actuals up to refdate stitched to forward prices
Key Parameters: - curve: Price curve to optimise against (dam, rtm, dart, or comma-separated). dart uses both DAM and RTM. - duration: Battery duration in hours (default: 4 h) - chgeff / dischgeff: Charging and discharging efficiency (default: 0.94) - data_format: json (default) or zip - details: When true, response includes hourly and daily dispatch breakdown (JSON only)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
iso | string | Yes | ISO code for the market (e.g. ercot, caiso, pjm) |
node | string | Yes | Electrical entity node name (e.g. HB_NORTH) |
exchange | string | No | Exchange code required for futures/combo mode (e.g. IFED, BOS) |
refdate | string | No | Forward curve reference date in YYYY-MM-DD format. Required for futures/combo mode. |
start_date | string | No | Start date in YYYY-MM-DD format. Required for historical/combo mode. |
end_date | string | No | End date in YYYY-MM-DD format. Required for historical/combo mode. |
duration | float | No | Battery duration in hours (default: 4.0) |
chg_eff | float | No | Charging efficiency (default: 0.94, range: 0.0-1.0) |
dischg_eff | float | No | Discharging efficiency (default: 0.94, range: 0.0-1.0) |
curve | string | No | Price curve: dam, rtm, dart, or comma-separated combination. dart optimises against both DAM and RTM. Default: dam |
data_format | string | No | Response format: json (default) or zip |
unit | string | No | Convert revenue to desired unit. Options: $/kw-dy, $/kw-mo, $/kw-mo-yr, $/kw-yr-yr, $/mwh-dy, $/mwh-mo, $/mwh-yr |
details | boolean | No | Include hourly_results and daily_results in JSON response (default: false) |
Example Request
curl -X GET "https://beast.batteryos.dev/api/v1/scenario/eoncyc500/ercot/HB_NORTH/?exchange=IFED&refdate=2025-06-15&duration=4&chg_eff=0.94&dischg_eff=0.94&curve=dart&data_format=json" \
-H "Authorization: Token ${FINMACHINES_TOKEN}"import requests
url = "https://beast.batteryos.dev/api/v1/scenario/eoncyc500/ercot/HB_NORTH/"
headers = {
"Authorization": f"Token {FINMACHINES_TOKEN}"
}
params = {
"exchange": "IFED",
"refdate": "2025-06-15",
"duration": 4,
"chg_eff": 0.94,
"dischg_eff": 0.94,
"curve": "dart",
"data_format": "json"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())Response
When results are ready (JSON, details=false):
{
"eon": [
{"date": "2025-07-01T00:00:00", "node": "HB_NORTH", "curve": "dart", "duration": 4.0, "cycles": 2.0, "value": 0.4521, "unit": "$/kw-dy"},
{"date": "2025-07-02T00:00:00", "node": "HB_NORTH", "curve": "dart", "duration": 4.0, "cycles": 2.0, "value": 0.6183, "unit": "$/kw-dy"}
]
}
When results are ready (JSON, details=true):
{
"eon": [
{"date": "2025-07-01T00:00:00", "node": "HB_NORTH", "curve": "dart", "duration": 4.0, "cycles": 2.0, "value": 0.4521, "unit": "$/kw-dy"}
],
"hourly_results": [
{"date": "2025-07-01T00:00:00", "charging_volume": 0.0, "discharging_volume": 1.0, "charging_revenue": 0.0, "discharging_revenue": 45.21, "total_revenue": 45.21, "total_cycles": 0.5, "soc": 0.0}
],
"daily_results": [
{"date": "2025-07-01", "charging_volume": 1.0, "discharging_volume": 1.0, "charging_revenue": -18.40, "discharging_revenue": 45.21, "total_revenue": 26.81, "total_cycles": 1.0}
]
}
When calculation is pending:
{
"slug": "abc123xyz",
"message": "Received"
}