Loading problem...
In quantitative finance and algorithmic trading, traditional candlestick charts are created at fixed time intervals (e.g., 1-minute, hourly, daily). However, this approach has a critical flaw: market activity is not evenly distributed over time. During high-volatility periods, a single 1-minute bar might contain hundreds of trades and significant price movements, while during quiet periods, bars might have minimal activity.
Monetary Volume Aggregated Bars (also known as dollar bars) offer an elegant solution by creating new price bars based on the cumulative monetary value of trades rather than elapsed time. A new bar is formed whenever a specified monetary threshold has been transacted, resulting in bars that contain roughly equal amounts of market activity regardless of timing.
How Monetary Bars Work:
For each trade in the sequence, the monetary value is calculated as:
$$\text{monetary_value} = \text{price} \times \text{volume}$$
Trades are accumulated until the cumulative monetary value meets or exceeds the specified threshold. At that point, a complete bar is created containing:
| Field | Description |
|---|---|
| open | The price of the first trade in the bar |
| high | The maximum price observed during the bar |
| low | The minimum price observed during the bar |
| close | The price of the last trade in the bar |
| volume | Total shares/units traded in the bar |
| monetary_value | Total monetary value accumulated in the bar |
After creating a bar, the accumulator resets and the process continues with subsequent trades.
Incomplete Bars: Trades at the end of the data that don't accumulate enough monetary value to meet the threshold are not included in any bar—only complete bars that meet the threshold are returned.
Your Task:
Write a Python function that processes a sequence of trades and generates monetary volume aggregated bars. Return a list of tuples where each tuple represents a complete bar in the format (open, high, low, close, volume, monetary_value). All numeric values should be rounded to 4 decimal places.
trades = [[100.0, 10], [101.0, 15], [99.0, 20], [102.0, 5]]
monetary_limit = 2000.0[(100.0, 101.0, 100.0, 101.0, 25, 2515.0), (99.0, 102.0, 99.0, 102.0, 25, 2490.0)]Processing the trades sequentially:
Bar 1 Formation: • Trade 1: price=100.0, volume=10 → monetary=1000.0, cumulative=1000.0 (below threshold) • Trade 2: price=101.0, volume=15 → monetary=1515.0, cumulative=2515.0 (≥ 2000, bar complete!)
Bar 1: open=100.0, high=101.0, low=100.0, close=101.0, volume=25, monetary=2515.0
Accumulator resets
Bar 2 Formation: • Trade 3: price=99.0, volume=20 → monetary=1980.0, cumulative=1980.0 (below threshold) • Trade 4: price=102.0, volume=5 → monetary=510.0, cumulative=2490.0 (≥ 2000, bar complete!)
Bar 2: open=99.0, high=102.0, low=99.0, close=102.0, volume=25, monetary=2490.0
Result: Two complete bars capturing market activity based on monetary volume.
trades = [[50.0, 20], [55.0, 10]]
monetary_limit = 1500.0[(50.0, 55.0, 50.0, 55.0, 30, 1550.0)]Processing the trades:
• Trade 1: price=50.0, volume=20 → monetary=1000.0, cumulative=1000.0 (below threshold) • Trade 2: price=55.0, volume=10 → monetary=550.0, cumulative=1550.0 (≥ 1500, bar complete!)
Bar 1: open=50.0, high=55.0, low=50.0, close=55.0, volume=30, monetary=1550.0
Result: A single bar with all trades included since the monetary threshold was met.
trades = [[100.0, 10], [100.0, 10], [100.0, 10], [100.0, 10], [100.0, 10]]
monetary_limit = 2000.0[(100.0, 100.0, 100.0, 100.0, 20, 2000.0), (100.0, 100.0, 100.0, 100.0, 20, 2000.0)]Processing trades with constant price:
Each trade has: price=100.0, volume=10 → monetary=1000.0 per trade
Bar 1 Formation: • Trade 1: cumulative=1000.0 (below) • Trade 2: cumulative=2000.0 (= 2000, bar complete!)
Bar 1: open=100.0, high=100.0, low=100.0, close=100.0, volume=20, monetary=2000.0
Bar 2 Formation: • Trade 3: cumulative=1000.0 (below) • Trade 4: cumulative=2000.0 (= 2000, bar complete!)
Bar 2: open=100.0, high=100.0, low=100.0, close=100.0, volume=20, monetary=2000.0
Trade 5 does not have enough subsequent trades to form a bar, so it is excluded.
Result: Two identical bars when price remains constant, with one trade remaining unused.
Constraints