The chart shows you structure visually. CSV export gives you the raw data behind it — every swing, every cycle count, every hierarchy position — for analysis in spreadsheets, databases, Python, R, or any tool you prefer.
SSTP exports 63 columns of hierarchical swing data through TradingView's native "Export chart data" functionality. Unlike SSI PRO's single-timeframe export, SSTP's export captures the state of all 10 timeframes simultaneously on every bar, giving you a complete multi-timeframe dataset in one file.
How to Export
- Open your chart with SSTP applied
- In the indicator settings, navigate to Group ⑨ (CSV Export)
- Enable "CSV Export"
- Right-click anywhere on the chart
- Select "Export chart data"
- Choose your date range and save the CSV file
The export includes every bar in the selected range. On bars where no swing occurred, the event columns (Swing_Event, Swing_Type) contain NaN/empty values while the state columns retain their last-known values.
<!-- IMAGE: sstp-csv-export-menu.png — TradingView right-click menu with "Export chart data" highlighted. Show SSTP applied to the chart in the background. -->
Right-click the chart and select "Export chart data" to download the CSV file containing all 63 SSTP columns.
The 63 Columns
The export is organized into two categories: per-timeframe columns (6 columns × 10 timeframes = 60) and global columns (3).
Per-Timeframe Columns
Each of the 10 timeframes exports 6 columns using the naming pattern {TF}_{Field}:
| Column | Type | What It Contains |
|---|---|---|
{TF}_Cycle | Integer | The hierarchical cycle count — how many swings at this timeframe since the last parent-timeframe swing reset the counter. Resets to 1 when a parent swing confirms. |
{TF}_Phase | Integer | 1 = last swing was a High (market turned down), 0 = last swing was a Low (market turned up). Combined with Cycle, tells you both position and direction within the parent cycle. |
{TF}_Price | Float | The price at the most recent swing extreme for this timeframe. Updates when a new swing is confirmed. |
{TF}_Time | Unix timestamp | When the most recent swing extreme occurred. This is the timestamp of the bar where the high or low actually happened, not where it was confirmed. |
{TF}_Dir | Integer | The current swing direction: 1 = trending up (last swing was a low, price is moving higher), -1 = trending down (last swing was a high, price is moving lower). |
{TF}_TDays | Integer | Trading days elapsed since the previous swing at this timeframe. Only populated for Daily and intraday timeframes. Shows NaN for Weekly and above (use Time to calculate duration for those). |
Timeframe Prefixes
The 10 timeframe prefixes, from highest to lowest:
| Prefix | Timeframe | Example Column |
|---|---|---|
Y | Yearly | Y_Cycle, Y_Phase, Y_Price, Y_Time, Y_Dir, Y_TDays |
Q | Quarterly | Q_Cycle, Q_Phase, Q_Price, Q_Time, Q_Dir, Q_TDays |
M | Monthly | M_Cycle, M_Phase, M_Price, M_Time, M_Dir, M_TDays |
W | Weekly | W_Cycle, W_Phase, W_Price, W_Time, W_Dir, W_TDays |
3D | 3-Day | 3D_Cycle, 3D_Phase, 3D_Price, 3D_Time, 3D_Dir, 3D_TDays |
2D | 2-Day | 2D_Cycle, 2D_Phase, 2D_Price, 2D_Time, 2D_Dir, 2D_TDays |
D | Daily | D_Cycle, D_Phase, D_Price, D_Time, D_Dir, D_TDays |
4H | 4-Hour | 4H_Cycle, 4H_Phase, 4H_Price, 4H_Time, 4H_Dir, 4H_TDays |
1H | 1-Hour | 1H_Cycle, 1H_Phase, 1H_Price, 1H_Time, 1H_Dir, 1H_TDays |
15m | 15-Minute | 15m_Cycle, 15m_Phase, 15m_Price, 15m_Time, 15m_Dir, 15m_TDays |
Global Columns
Three columns capture cross-timeframe information:
| Column | Type | What It Contains |
|---|---|---|
Full_Hierarchy | Integer | The odometer — a single number encoding all 10 cycle counts. Each digit position represents one timeframe's count (Y in billions, Q in hundred millions, down to 15m in ones). Decode by extracting digits. |
Swing_Event | Integer | Which timeframe fired a swing on this bar. Uses rank indices: 0 = 15m, 1 = 1H, 2 = 4H, 3 = D, 4 = 2D, 5 = 3D, 6 = W, 7 = M, 8 = Q, 9 = Y. NaN on bars with no swing event. |
Swing_Type | Integer | Direction of the swing that fired: 1 = Swing High, -1 = Swing Low. NaN on bars with no swing event. |
Understanding the Data
State Columns vs. Event Columns
This distinction is critical for working with the data correctly.
State columns (_Cycle, _Phase, _Price, _Time, _Dir, _TDays) persist their values across bars. Once a Weekly swing high confirms and sets W_Phase to 1, that value remains 1 on every subsequent bar until the next Weekly swing changes it. These columns represent the current state of each timeframe — what's true right now.
Event columns (Swing_Event, Swing_Type) are populated only on bars where a swing was confirmed. On all other bars, they contain NaN. These columns mark the moments when something happened.
Practical consequence: If you filter the CSV to rows where Swing_Event is not NaN, you get a table of all swing events with their full hierarchical context. If you read the data row-by-row, the state columns give you a snapshot of all 10 timeframes at every bar.
Reading the Odometer (Full_Hierarchy)
The Full_Hierarchy column encodes all 10 cycle counts into a single integer using positional notation:
Full_Hierarchy = Y×10⁹ + Q×10⁸ + M×10⁷ + W×10⁶ + 3D×10⁵ + 2D×10⁴ + D×10³ + 4H×10² + 1H×10¹ + 15m×10⁰
Example: Full_Hierarchy = 1203007014
| Position | Digit | Meaning |
|---|---|---|
| Billions | 1 | Y_Cycle = 1 (1st yearly swing) |
| Hundred millions | 2 | Q_Cycle = 2 (2nd quarterly swing) |
| Ten millions | 0 | M_Cycle = 0 (no monthly swing yet) |
| Millions | 3 | W_Cycle = 3 (3rd weekly swing) |
| Hundred thousands | 0 | 3D_Cycle = 0 (no 3D swing yet) |
| Ten thousands | 0 | 2D_Cycle = 0 (no 2D swing yet) |
| Thousands | 7 | D_Cycle = 7 (7th daily swing) |
| Hundreds | 0 | 4H_Cycle = 0 (no 4H swing yet) |
| Tens | 1 | 1H_Cycle = 1 (1st hourly swing) |
| Ones | 4 | 15m_Cycle = 4 (4th 15m swing) |
To decode in Python:
def decode_hierarchy(value):
s = str(int(value)).zfill(10)
labels = ['Y', 'Q', 'M', 'W', '3D', '2D', 'D', '4H', '1H', '15m']
return {labels[i]: int(s[i]) for i in range(10)}
# decode_hierarchy(1203007014)
# → {'Y': 1, 'Q': 2, 'M': 0, 'W': 3, '3D': 0, '2D': 0, 'D': 7, '4H': 0, '1H': 1, '15m': 4}Note: The odometer uses single digits per position, so cycle counts above 9 at any level will overflow into the adjacent position. This is rare in practice — a timeframe would need 10+ swings before its parent resets the counter — but be aware of it when decoding very long datasets.
Reading Phase + Dir Together
_Phase and _Dir are related but subtly different:
_Phasetells you the direction of the last confirmed swing:1= the last swing was a High,0= the last swing was a Low_Dirtells you the current trend direction:1= trending up (last swing was Low, so price is now heading up),-1= trending down
They're inverses: when Phase = 1 (last swing was High), Dir = -1 (now trending down). When Phase = 0 (last swing was Low), Dir = 1 (now trending up).
The redundancy is intentional — depending on your analysis, one framing may be more intuitive than the other.
CSV Data Only Mode
For deep historical exports, SSTP offers a mode that bypasses TradingView's 500-label drawing limit.
The problem: TradingView limits visual labels to 500 per indicator instance. On a daily chart with 50 years of data and 4 active timeframes, you'd hit this limit quickly — meaning the indicator would only show labels for recent history.
The solution: Enable "CSV Data Only (No Labels)" in Group ⑨. This runs all swing detection, classification, hierarchy tracking, and CSV state computation on every bar — but skips label and line drawing entirely. Without visual objects consuming the 500-label budget, the indicator processes the full chart history.
What you get: A complete CSV with all 63 columns covering the entire visible date range, including decades of data on instruments with long histories (like major stock indices or commodities).
What you lose: No labels or lines appear on the chart. The chart looks as if the indicator isn't applied (except for the settings panel being visible). This mode is purely for data extraction.
When to use it: Building historical databases, backtesting across decades, academic research on cycle behavior, or any workflow where you need complete data and don't need visual chart output.
Working with the Data
Filtering to Swing Events
Most rows contain only state data — no new swing occurred on that bar. To extract just the swing events:
Python:
import pandas as pd
df = pd.read_csv('export.csv')
swings = df[df['Swing_Event'].notna()]Excel / Google Sheets:
Filter the Swing_Event column to exclude blanks/NaN.
R:
swings <- subset(data, !is.na(Swing_Event))The resulting table contains one row per swing event, with the full hierarchical state at the moment each swing confirmed.
Filtering by Timeframe
To extract swings from a specific timeframe, filter Swing_Event by its rank index:
# Weekly swings only (rank 6)
weekly_swings = df[df['Swing_Event'] == 6]
# Monthly swings only (rank 7)
monthly_swings = df[df['Swing_Event'] == 7]| Rank | Timeframe |
|---|---|
| 0 | 15-Minute |
| 1 | 1-Hour |
| 2 | 4-Hour |
| 3 | Daily |
| 4 | 2-Day |
| 5 | 3-Day |
| 6 | Weekly |
| 7 | Monthly |
| 8 | Quarterly |
| 9 | Yearly |
Converting Timestamps
The _Time columns use Unix timestamps (seconds since January 1, 1970). Convert to readable dates:
Python:
from datetime import datetime
timestamp = 1731801600
date = datetime.utcfromtimestamp(timestamp)
# → 2024-11-17 00:00:00JavaScript:
const timestamp = 1731801600;
const date = new Date(timestamp * 1000);Excel:
=A1/86400 + DATE(1970,1,1)
Format the cell as Date/Time.
Building a Swing Timeline
Combine Swing_Event, Swing_Type, and the relevant timeframe columns to build a chronological swing timeline:
swings = df[df['Swing_Event'].notna()].copy()
tf_map = {0: '15m', 1: '1H', 2: '4H', 3: 'D', 4: '2D', 5: '3D', 6: 'W', 7: 'M', 8: 'Q', 9: 'Y'}
swings['Timeframe'] = swings['Swing_Event'].map(tf_map)
swings['Direction'] = swings['Swing_Type'].map({1: 'High', -1: 'Low'})
# Get the price for each swing from its timeframe column
swings['Price'] = swings.apply(
lambda row: row[f"{tf_map[int(row['Swing_Event'])]}_Price"], axis=1
)
timeline = swings[['time', 'Timeframe', 'Direction', 'Price']].reset_index(drop=True)Detecting Cycle Resets
When a parent timeframe confirms a swing, all child counters reset. You can detect these resets by watching for drops in cycle counts:
# Detect weekly cycle resets (triggered by monthly swings)
df['W_Cycle_prev'] = df['W_Cycle'].shift(1)
resets = df[(df['W_Cycle'] == 1) & (df['W_Cycle_prev'] > 1)]Each reset row corresponds to a bar where a Monthly (or higher) swing confirmed and reset the Weekly counter to 1.
Measuring Cycle Maturity
The cycle count tells you where you are within a parent cycle. If historical Monthly cycles typically contain 8–12 Weekly swings, and the current W_Cycle is 11, the cycle is mature — a Monthly-level reversal may be approaching.
# Weekly cycle lengths (number of weekly swings per monthly cycle)
monthly_swings = df[df['Swing_Event'] == 7]
cycle_lengths = monthly_swings['W_Cycle'].tolist()
print(f"Average weekly swings per monthly cycle: {sum(cycle_lengths) / len(cycle_lengths):.1f}")
print(f"Range: {min(cycle_lengths)} to {max(cycle_lengths)}")SSTP + SSI PRO Dual Export
If you run both SSTP and SSI PRO on the same chart, both indicators contribute their columns to the CSV export. This gives you the best of both worlds:
- SSTP columns (63): Multi-timeframe hierarchy, cycle counts, cross-timeframe state
- SSI PRO columns: Single-timeframe detail — ExtremeTimestamp vs ConfirmTimestamp, pattern codes, bar index
The combined export lets you cross-reference single-timeframe swing detail (from SSI PRO) with multi-timeframe context (from SSTP) in the same dataset.
Workflow:
- Apply both indicators to the same chart
- Enable CSV Export in both indicators' settings
- Right-click → Export chart data
- The resulting CSV contains columns from both indicators plus TradingView's standard OHLCV
Running SSTP and SSI PRO together provides the most comprehensive swing data export — multi-timeframe hierarchy plus single-timeframe detail in one file.
Building a Swing Database
CSV export is ideal for initial database population or periodic full refreshes.
Suggested Schema
CREATE TABLE sstp_swings (
id SERIAL PRIMARY KEY,
symbol VARCHAR(20),
bar_time TIMESTAMP,
timeframe VARCHAR(5),
swing_type INTEGER,
swing_price DECIMAL(18, 8),
swing_time BIGINT,
cycle_count INTEGER,
phase INTEGER,
direction INTEGER,
full_hierarchy BIGINT,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(symbol, bar_time, timeframe)
);Import Workflow
- Export historical data — Use CSV Data Only mode for full history
- Parse the CSV — Filter to rows where Swing_Event is not NaN
- Map timeframe ranks — Convert Swing_Event integers to timeframe strings
- Extract per-timeframe fields — Pull the relevant
{TF}_Cycle,{TF}_Phase,{TF}_Price,{TF}_Timefor the active timeframe - Insert rows — One row per swing event with the full hierarchical context
- Add indexes — On symbol, timeframe, swing_time for query performance
Keeping It Updated
CSV export captures a snapshot in time. For ongoing updates, you have two options:
Periodic re-export: Export weekly or monthly and upsert new rows. The unique constraint prevents duplicates.
Manual addition: As new swings confirm on the chart, add them to the database manually or through a scripted workflow.
Complete Column Reference
All 63 columns in export order, from highest timeframe to lowest:
| # | Column | Type | Category |
|---|---|---|---|
| 1 | Y_Cycle | Integer | Yearly state |
| 2 | Y_Phase | Integer | Yearly state |
| 3 | Y_Price | Float | Yearly state |
| 4 | Y_Time | Unix timestamp | Yearly state |
| 5 | Y_Dir | Integer | Yearly state |
| 6 | Y_TDays | Integer | Yearly state |
| 7 | Q_Cycle | Integer | Quarterly state |
| 8 | Q_Phase | Integer | Quarterly state |
| 9 | Q_Price | Float | Quarterly state |
| 10 | Q_Time | Unix timestamp | Quarterly state |
| 11 | Q_Dir | Integer | Quarterly state |
| 12 | Q_TDays | Integer | Quarterly state |
| 13 | M_Cycle | Integer | Monthly state |
| 14 | M_Phase | Integer | Monthly state |
| 15 | M_Price | Float | Monthly state |
| 16 | M_Time | Unix timestamp | Monthly state |
| 17 | M_Dir | Integer | Monthly state |
| 18 | M_TDays | Integer | Monthly state |
| 19 | W_Cycle | Integer | Weekly state |
| 20 | W_Phase | Integer | Weekly state |
| 21 | W_Price | Float | Weekly state |
| 22 | W_Time | Unix timestamp | Weekly state |
| 23 | W_Dir | Integer | Weekly state |
| 24 | W_TDays | Integer | Weekly state |
| 25 | 3D_Cycle | Integer | 3-Day state |
| 26 | 3D_Phase | Integer | 3-Day state |
| 27 | 3D_Price | Float | 3-Day state |
| 28 | 3D_Time | Unix timestamp | 3-Day state |
| 29 | 3D_Dir | Integer | 3-Day state |
| 30 | 3D_TDays | Integer | 3-Day state |
| 31 | 2D_Cycle | Integer | 2-Day state |
| 32 | 2D_Phase | Integer | 2-Day state |
| 33 | 2D_Price | Float | 2-Day state |
| 34 | 2D_Time | Unix timestamp | 2-Day state |
| 35 | 2D_Dir | Integer | 2-Day state |
| 36 | 2D_TDays | Integer | 2-Day state |
| 37 | D_Cycle | Integer | Daily state |
| 38 | D_Phase | Integer | Daily state |
| 39 | D_Price | Float | Daily state |
| 40 | D_Time | Unix timestamp | Daily state |
| 41 | D_Dir | Integer | Daily state |
| 42 | D_TDays | Integer | Daily state |
| 43 | 4H_Cycle | Integer | 4-Hour state |
| 44 | 4H_Phase | Integer | 4-Hour state |
| 45 | 4H_Price | Float | 4-Hour state |
| 46 | 4H_Time | Unix timestamp | 4-Hour state |
| 47 | 4H_Dir | Integer | 4-Hour state |
| 48 | 4H_TDays | Integer | 4-Hour state |
| 49 | 1H_Cycle | Integer | 1-Hour state |
| 50 | 1H_Phase | Integer | 1-Hour state |
| 51 | 1H_Price | Float | 1-Hour state |
| 52 | 1H_Time | Unix timestamp | 1-Hour state |
| 53 | 1H_Dir | Integer | 1-Hour state |
| 54 | 1H_TDays | Integer | 1-Hour state |
| 55 | 15m_Cycle | Integer | 15-Min state |
| 56 | 15m_Phase | Integer | 15-Min state |
| 57 | 15m_Price | Float | 15-Min state |
| 58 | 15m_Time | Unix timestamp | 15-Min state |
| 59 | 15m_Dir | Integer | 15-Min state |
| 60 | 15m_TDays | Integer | 15-Min state |
| 61 | Full_Hierarchy | Integer | Global |
| 62 | Swing_Event | Integer | Global |
| 63 | Swing_Type | Integer | Global |
Next Steps
- Tooltips & Metrics — The same data shown visually in chart tooltips
- Settings — CSV Export settings (Group ⑨)
- Overview — How CSV Export fits into the broader SSTP system
- Glossary — Definitions for all terms used in this page