Search...Ctrl K

CSV Export

# → {'Y': 1, 'Q': 2, 'M': 0, 'W': 3, '3D': 0, '2D': 0, 'D': 7, '4H': 0, '1H': 1, '15m': 4}

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

  1. Open your chart with SSTP applied
  2. In the indicator settings, navigate to Group ⑨ (CSV Export)
  3. Enable "CSV Export"
  4. Right-click anywhere on the chart
  5. Select "Export chart data"
  6. 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.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}:

ColumnTypeWhat It Contains
{TF}_CycleIntegerThe 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}_PhaseInteger1 = 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}_PriceFloatThe price at the most recent swing extreme for this timeframe. Updates when a new swing is confirmed.
{TF}_TimeUnix timestampWhen 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}_DirIntegerThe 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}_TDaysIntegerTrading 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:

PrefixTimeframeExample Column
YYearlyY_Cycle, Y_Phase, Y_Price, Y_Time, Y_Dir, Y_TDays
QQuarterlyQ_Cycle, Q_Phase, Q_Price, Q_Time, Q_Dir, Q_TDays
MMonthlyM_Cycle, M_Phase, M_Price, M_Time, M_Dir, M_TDays
WWeeklyW_Cycle, W_Phase, W_Price, W_Time, W_Dir, W_TDays
3D3-Day3D_Cycle, 3D_Phase, 3D_Price, 3D_Time, 3D_Dir, 3D_TDays
2D2-Day2D_Cycle, 2D_Phase, 2D_Price, 2D_Time, 2D_Dir, 2D_TDays
DDailyD_Cycle, D_Phase, D_Price, D_Time, D_Dir, D_TDays
4H4-Hour4H_Cycle, 4H_Phase, 4H_Price, 4H_Time, 4H_Dir, 4H_TDays
1H1-Hour1H_Cycle, 1H_Phase, 1H_Price, 1H_Time, 1H_Dir, 1H_TDays
15m15-Minute15m_Cycle, 15m_Phase, 15m_Price, 15m_Time, 15m_Dir, 15m_TDays

Global Columns

Three columns capture cross-timeframe information:

ColumnTypeWhat It Contains
Full_HierarchyIntegerThe 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_EventIntegerWhich 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_TypeIntegerDirection 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

PositionDigitMeaning
Billions1Y_Cycle = 1 (1st yearly swing)
Hundred millions2Q_Cycle = 2 (2nd quarterly swing)
Ten millions0M_Cycle = 0 (no monthly swing yet)
Millions3W_Cycle = 3 (3rd weekly swing)
Hundred thousands03D_Cycle = 0 (no 3D swing yet)
Ten thousands02D_Cycle = 0 (no 2D swing yet)
Thousands7D_Cycle = 7 (7th daily swing)
Hundreds04H_Cycle = 0 (no 4H swing yet)
Tens11H_Cycle = 1 (1st hourly swing)
Ones415m_Cycle = 4 (4th 15m swing)

To decode in Python:

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:

  • _Phase tells you the direction of the last confirmed swing: 1 = the last swing was a High, 0 = the last swing was a Low
  • _Dir tells 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:

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:

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:

python
# Weekly swings only (rank 6) weekly_swings = df[df['Swing_Event'] == 6] # Monthly swings only (rank 7) monthly_swings = df[df['Swing_Event'] == 7]
RankTimeframe
015-Minute
11-Hour
24-Hour
3Daily
42-Day
53-Day
6Weekly
7Monthly
8Quarterly
9Yearly

Converting Timestamps

The _Time columns use Unix timestamps (seconds since January 1, 1970). Convert to readable dates:

Python:

python
from datetime import datetime timestamp = 1731801600 date = datetime.utcfromtimestamp(timestamp) # → 2024-11-17 00:00:00

JavaScript:

javascript
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:

python
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:

python
# 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.

python
# 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:

  1. Apply both indicators to the same chart
  2. Enable CSV Export in both indicators' settings
  3. Right-click → Export chart data
  4. The resulting CSV contains columns from both indicators plus TradingView's standard OHLCV
<!-- IMAGE: sstp-dual-export.png — TradingView chart with both SSTP and SSI PRO applied, showing labels from both indicators. A CSV file icon or spreadsheet preview alongside it showing the combined column headers. -->

Running SSTP and SSI PRO together provides the most comprehensive swing data export — multi-timeframe hierarchy plus single-timeframe detail in one file.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

sql
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

  1. Export historical data — Use CSV Data Only mode for full history
  2. Parse the CSV — Filter to rows where Swing_Event is not NaN
  3. Map timeframe ranks — Convert Swing_Event integers to timeframe strings
  4. Extract per-timeframe fields — Pull the relevant {TF}_Cycle, {TF}_Phase, {TF}_Price, {TF}_Time for the active timeframe
  5. Insert rows — One row per swing event with the full hierarchical context
  6. 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:

#ColumnTypeCategory
1Y_CycleIntegerYearly state
2Y_PhaseIntegerYearly state
3Y_PriceFloatYearly state
4Y_TimeUnix timestampYearly state
5Y_DirIntegerYearly state
6Y_TDaysIntegerYearly state
7Q_CycleIntegerQuarterly state
8Q_PhaseIntegerQuarterly state
9Q_PriceFloatQuarterly state
10Q_TimeUnix timestampQuarterly state
11Q_DirIntegerQuarterly state
12Q_TDaysIntegerQuarterly state
13M_CycleIntegerMonthly state
14M_PhaseIntegerMonthly state
15M_PriceFloatMonthly state
16M_TimeUnix timestampMonthly state
17M_DirIntegerMonthly state
18M_TDaysIntegerMonthly state
19W_CycleIntegerWeekly state
20W_PhaseIntegerWeekly state
21W_PriceFloatWeekly state
22W_TimeUnix timestampWeekly state
23W_DirIntegerWeekly state
24W_TDaysIntegerWeekly state
253D_CycleInteger3-Day state
263D_PhaseInteger3-Day state
273D_PriceFloat3-Day state
283D_TimeUnix timestamp3-Day state
293D_DirInteger3-Day state
303D_TDaysInteger3-Day state
312D_CycleInteger2-Day state
322D_PhaseInteger2-Day state
332D_PriceFloat2-Day state
342D_TimeUnix timestamp2-Day state
352D_DirInteger2-Day state
362D_TDaysInteger2-Day state
37D_CycleIntegerDaily state
38D_PhaseIntegerDaily state
39D_PriceFloatDaily state
40D_TimeUnix timestampDaily state
41D_DirIntegerDaily state
42D_TDaysIntegerDaily state
434H_CycleInteger4-Hour state
444H_PhaseInteger4-Hour state
454H_PriceFloat4-Hour state
464H_TimeUnix timestamp4-Hour state
474H_DirInteger4-Hour state
484H_TDaysInteger4-Hour state
491H_CycleInteger1-Hour state
501H_PhaseInteger1-Hour state
511H_PriceFloat1-Hour state
521H_TimeUnix timestamp1-Hour state
531H_DirInteger1-Hour state
541H_TDaysInteger1-Hour state
5515m_CycleInteger15-Min state
5615m_PhaseInteger15-Min state
5715m_PriceFloat15-Min state
5815m_TimeUnix timestamp15-Min state
5915m_DirInteger15-Min state
6015m_TDaysInteger15-Min state
61Full_HierarchyIntegerGlobal
62Swing_EventIntegerGlobal
63Swing_TypeIntegerGlobal

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