Files
trading_analysis/COT_data_nasdaq_Silver.ipynb
2024-08-19 19:41:20 +02:00

351 KiB

Load NASDAQ API key (Data Link API) - Silver

In [22]:
from dotenv import load_dotenv
import os

# Load the environment variables from .env file
load_dotenv("api_keys")
Out [22]:
True
In [23]:
nasdaq_api_key = os.getenv('NASDAQ_API_KEY')
if len(nasdaq_api_key) > 0:
    print("loaded key")
loaded key

Retrieve 2 year of COT data (% shifts producers long / short)

In [40]:
import requests
import pandas as pd
from datetime import datetime
import urllib.parse

# API endpoint components
base_url = "https://data.nasdaq.com/api/v3/datasets/"
dataset = "CFTC/084691_F_ALL"
data_format = ".json"

# Parameters
params = {
    "start_date": "2022-01-01",
    "end_date": "2024-01-01",
    "api_key": nasdaq_api_key  # Make sure this variable is defined
}

# Construct the full URL with parameters
param_string = urllib.parse.urlencode(params)
url = f"{base_url}{dataset}{data_format}?{param_string}"

# Make the API request
response = requests.get(url)

# Check if the request was successful
if response.status_code == 200:
    # Parse the JSON response
    data = response.json()
    
    # Extract the dataset from the response
    dataset = data['dataset']
    
    # Create a pandas DataFrame
    df = pd.DataFrame(dataset['data'], columns=dataset['column_names'])
    
    # Convert the date column to datetime
    df['Date'] = pd.to_datetime(df['Date'])
    
    # Set the date as the index
    df.set_index('Date', inplace=True)
    
    # Sort the DataFrame by date
    df.sort_index(inplace=True)
    
    # Display the first few rows of the DataFrame
    print(df.tail())
    
    # You can now use this DataFrame for further analysis or visualization
    
else:
    print(f"Error fetching data: {response.status_code}")
    print(response.text)
            Open Interest  Producer/Merchant/Processor/User Longs  \
Date                                                                
2023-11-28       139144.0                                  3472.0   
2023-12-05       139753.0                                  4714.0   
2023-12-12       134281.0                                  4311.0   
2023-12-19       127549.0                                  3701.0   
2023-12-26       131408.0                                  4063.0   

            Producer/Merchant/Processor/User Shorts  Swap Dealer Longs  \
Date                                                                     
2023-11-28                                  40323.0            33045.0   
2023-12-05                                  41340.0            33328.0   
2023-12-12                                  38849.0            30707.0   
2023-12-19                                  39714.0            30908.0   
2023-12-26                                  41011.0            29911.0   

            Swap Dealer Shorts  Swap Dealer Spreads  Money Manager Longs  \
Date                                                                       
2023-11-28             44049.0               3770.0              45604.0   
2023-12-05             48716.0               2932.0              43852.0   
2023-12-12             43665.0               2832.0              33472.0   
2023-12-19             43686.0               1911.0              34931.0   
2023-12-26             45585.0               2415.0              36546.0   

            Money Manager Shorts  Money Manager Spreads  \
Date                                                      
2023-11-28               21842.0                 6885.0   
2023-12-05               22322.0                 7544.0   
2023-12-12               24805.0                 8439.0   
2023-12-19               20060.0                 6662.0   
2023-12-26               19749.0                 6847.0   

            Other Reportable Longs  Other Reportable Shorts  \
Date                                                          
2023-11-28                 17276.0                   6758.0   
2023-12-05                 19389.0                   4616.0   
2023-12-12                 22212.0                   2421.0   
2023-12-19                 17700.0                   2820.0   
2023-12-26                 18013.0                   2947.0   

            Other Reportable Spreads  Total Reportable Longs  \
Date                                                           
2023-11-28                    2445.0                112497.0   
2023-12-05                    1607.0                113366.0   
2023-12-12                    1706.0                103679.0   
2023-12-19                    1577.0                 97390.0   
2023-12-26                    2137.0                 99932.0   

            Total Reportable Shorts  Non Reportable Longs  \
Date                                                        
2023-11-28                 126072.0               26647.0   
2023-12-05                 129077.0               26387.0   
2023-12-12                 122717.0               30602.0   
2023-12-19                 116430.0               30159.0   
2023-12-26                 120691.0               31476.0   

            Non Reportable Shorts  
Date                               
2023-11-28                13072.0  
2023-12-05                10676.0  
2023-12-12                11564.0  
2023-12-19                11119.0  
2023-12-26                10717.0  
In [41]:
df.columns
Out [41]:
Index(['Open Interest', 'Producer/Merchant/Processor/User Longs',
       'Producer/Merchant/Processor/User Shorts', 'Swap Dealer Longs',
       'Swap Dealer Shorts', 'Swap Dealer Spreads', 'Money Manager Longs',
       'Money Manager Shorts', 'Money Manager Spreads',
       'Other Reportable Longs', 'Other Reportable Shorts',
       'Other Reportable Spreads', 'Total Reportable Longs',
       'Total Reportable Shorts', 'Non Reportable Longs',
       'Non Reportable Shorts'],
      dtype='object')
In [44]:
df.tail()
Out [44]:
Open Interest Producer/Merchant/Processor/User Longs Producer/Merchant/Processor/User Shorts Swap Dealer Longs Swap Dealer Shorts Swap Dealer Spreads Money Manager Longs Money Manager Shorts Money Manager Spreads Other Reportable Longs Other Reportable Shorts Other Reportable Spreads Total Reportable Longs Total Reportable Shorts Non Reportable Longs Non Reportable Shorts
Date
2023-11-28 139144.0 3472.0 40323.0 33045.0 44049.0 3770.0 45604.0 21842.0 6885.0 17276.0 6758.0 2445.0 112497.0 126072.0 26647.0 13072.0
2023-12-05 139753.0 4714.0 41340.0 33328.0 48716.0 2932.0 43852.0 22322.0 7544.0 19389.0 4616.0 1607.0 113366.0 129077.0 26387.0 10676.0
2023-12-12 134281.0 4311.0 38849.0 30707.0 43665.0 2832.0 33472.0 24805.0 8439.0 22212.0 2421.0 1706.0 103679.0 122717.0 30602.0 11564.0
2023-12-19 127549.0 3701.0 39714.0 30908.0 43686.0 1911.0 34931.0 20060.0 6662.0 17700.0 2820.0 1577.0 97390.0 116430.0 30159.0 11119.0
2023-12-26 131408.0 4063.0 41011.0 29911.0 45585.0 2415.0 36546.0 19749.0 6847.0 18013.0 2947.0 2137.0 99932.0 120691.0 31476.0 10717.0

Plot the data

In [45]:
import pandas as pd
import plotly.graph_objects as go
import numpy as np

# Assuming df is your DataFrame with the COT data
# If not, you'll need to load your data here

# Calculate percentages for producers
categories = [
    'Producer/Merchant/Processor/User Longs',
    'Producer/Merchant/Processor/User Shorts'
]

for category in categories:
    df[f'{category} %'] = df[category] / df['Open Interest'] * 100

# Create the main figure
fig = go.Figure()

# Add traces for each category
colors = ['blue', 'red']
for i, category in enumerate(categories):
    fig.add_trace(go.Scatter(
        x=df.index, 
        y=df[f'{category} %'], 
        mode='lines',
        name=category,
        line=dict(width=2, color=colors[i])
    ))

# Update layout
fig.update_layout(
    title='COT Data: Percentage of Open Interest for Producers',
    yaxis_title='Percentage of Open Interest',
    xaxis_title='Date',
    legend_title='Producer Categories',
    height=600,
    width=1200,
    hovermode='x unified'
)

# Improve date labeling for better readability
fig.update_xaxes(
    tickformat="%d %b %Y",
    tickangle=45,
    dtick="M1",
    ticklabelmode="period"
)

# Set y-axis to percentage
fig.update_yaxes(ticksuffix='%')

# Show the plot
fig.show()

# Calculate and print metrics
for category in categories:
    print(f"\nMetrics for {category}:")
    data = df[f'{category} %']
    
    print(f"Volatility (Standard Deviation): {data.std():.2f}%")
    print(f"Average: {data.mean():.2f}%")
    print(f"Median: {data.median():.2f}%")
    print(f"Minimum: {data.min():.2f}%")
    print(f"Maximum: {data.max():.2f}%")
    
    # Calculate typical range
    typical_low = np.percentile(data, 25)
    typical_high = np.percentile(data, 75)
    print(f"Typical Range: {typical_low:.2f}% to {typical_high:.2f}%")

# Calculate and print the correlation between longs and shorts
correlation = df[f'{categories[0]} %'].corr(df[f'{categories[1]} %'])
print(f"\nCorrelation between Longs and Shorts: {correlation:.2f}")
Metrics for Producer/Merchant/Processor/User Longs:
Volatility (Standard Deviation): 1.36%
Average: 3.23%
Median: 3.00%
Minimum: 0.64%
Maximum: 7.14%
Typical Range: 2.37% to 3.78%

Metrics for Producer/Merchant/Processor/User Shorts:
Volatility (Standard Deviation): 3.96%
Average: 25.57%
Median: 25.32%
Minimum: 18.08%
Maximum: 32.77%
Typical Range: 22.26% to 28.93%

Correlation between Longs and Shorts: -0.22
In [26]:
import pandas as pd
import plotly.graph_objects as go
import numpy as np
from scipy import signal

# Assuming df is your DataFrame with the COT data
# If not, you'll need to load your data here

# Create the main figure
fig = go.Figure()

# Add trace for Open Interest
fig.add_trace(go.Scatter(
    x=df.index, 
    y=df['Open Interest'], 
    mode='lines',
    name='Open Interest',
    line=dict(width=2, color='blue')
))

# Update layout
fig.update_layout(
    title='COT Data: Open Interest Over Time (Silver)',
    yaxis_title='Open Interest',
    xaxis_title='Date',
    height=600,
    width=800,
    hovermode='x unified'
)

# Improve date labeling for better readability
fig.update_xaxes(
    tickformat="%d %b %Y",
    tickangle=45,
    dtick="M1",
    ticklabelmode="period"
)

# Show the plot
fig.show()

# Calculate and print metrics
print("\nMetrics for Open Interest:")
data = df['Open Interest']

print(f"Volatility (Standard Deviation): {data.std():.2f}")
print(f"Average: {data.mean():.2f}")
print(f"Median: {data.median():.2f}")
print(f"Minimum: {data.min():.2f}")
print(f"Maximum: {data.max():.2f}")

# Calculate typical range
typical_low = np.percentile(data, 25)
typical_high = np.percentile(data, 75)
print(f"Typical Range: {typical_low:.2f} to {typical_high:.2f}")

# Identify trends
def identify_trend(series):
    # Calculate the overall trend
    trend = np.polyfit(range(len(series)), series, 1)[0]
    if trend > 0:
        return "Upward"
    elif trend < 0:
        return "Downward"
    else:
        return "Stable"

trend = identify_trend(data)
print(f"\nOverall trend: {trend}")

# Identify significant points
def find_peaks(series, prominence=1000):
    peaks, _ = signal.find_peaks(series, prominence=prominence)
    troughs, _ = signal.find_peaks(-series, prominence=prominence)
    return peaks, troughs

peaks, troughs = find_peaks(data)

print("\nSignificant points:")
for peak in peaks:
    print(f"Peak on {df.index[peak]}: {data.iloc[peak]:.2f}")
for trough in troughs:
    print(f"Trough on {df.index[trough]}: {data.iloc[trough]:.2f}")

# Identify sudden changes
pct_change = data.pct_change()
sudden_changes = pct_change[abs(pct_change) > 0.05]  # 5% threshold
if not sudden_changes.empty:
    print("\nSudden changes (>5% day-to-day):")
    for date, change in sudden_changes.items():
        print(f"{date}: {change*100:.2f}% change")
else:
    print("\nNo sudden changes above 5% threshold detected.")
Metrics for Open Interest:
Volatility (Standard Deviation): 5894.28
Average: 131794.00
Median: 131408.00
Minimum: 123640.00
Maximum: 144138.00
Typical Range: 126377.50 to 135836.50

Overall trend: Downward

Significant points:
Peak on 2023-10-10 00:00:00: 126971.00
Peak on 2023-12-05 00:00:00: 139753.00
Trough on 2023-09-12 00:00:00: 125292.00
Trough on 2023-10-17 00:00:00: 123640.00
Trough on 2023-12-19 00:00:00: 127549.00

Sudden changes (>5% day-to-day):
2023-12-19 00:00:00: -5.01% change
In [ ]: