Price Trend Analysis with Volatility Indicators using CoinAPI

This tutorial demonstrates how to perform advanced price trend analysis with volatility indicators using the CoinAPI Market Data REST API. Price trend analysis is essential for understanding market movements and making informed trading decisions. Volatility indicators help traders identify periods of high or low market activity, potential trend reversals, and optimal entry/exit points.

  • How to fetch historical exchange rate data from CoinAPI
  • How to calculate various volatility indicators (ATR, normalized volatility)
  • How to detect and analyze price trends
  • How to create comprehensive visualizations
  • How to perform statistical analysis of market patterns
  • Python 3.7+
  • CoinAPI API key (get one at https://www.coinapi.io/)
  • Required packages: requests, pandas, numpy, matplotlib, seaborn
  1. Go to https://www.coinapi.io/
  2. Sign up for a free account
  3. Get your API key from the dashboard
  4. Replace YOUR_COINAPI_KEY_HERE in the code below with your actual API key

First, let's set up our environment with the necessary imports and API configuration.

1# Import required libraries
2import requests
3import pandas as pd
4import numpy as np
5import matplotlib.pyplot as plt
6import seaborn as sns
7from datetime import datetime, timedelta, timezone
8import json
9from typing import Optional, List
10
11# Set up plotting style
12plt.style.use('seaborn-v0_8')
13sns.set_palette("husl")
14plt.rcParams['figure.figsize'] = (12, 8)
15
16# CoinAPI configuration
17API_KEY = "YOUR_COINAPI_KEY_HERE"  # Replace with your actual API key
18BASE_URL = "https://rest.coinapi.io"
19
20print("āœ… Environment setup complete!")
21print(f"šŸ“Š Using CoinAPI base URL: {BASE_URL}")
22print(f"šŸ”‘ API Key configured: {'Yes' if API_KEY != 'YOUR_COINAPI_KEY_HERE' else 'No (Please update)'}")

āœ… Environment setup complete!
šŸ“Š Using CoinAPI base URL: https://rest.coinapi.io
šŸ”‘ API Key configured: Yes

We'll create a function to fetch historical exchange rate data from CoinAPI. This function will retrieve OHLC (Open, High, Low, Close) data which is perfect for calculating volatility indicators and analyzing price trends.

1def fetch_exchange_rate_data(asset_id_base: str, asset_id_quote: str, period_id: str, time_start: str, time_end: str) -> Optional[List[dict]]:
2    """
3    Fetch historical exchange rate data from CoinAPI
4    
5    Args:
6        asset_id_base: Base asset identifier (e.g., 'BTC')
7        asset_id_quote: Quote asset identifier (e.g., 'USDT')
8        period_id: Time period (e.g., '1HRS' for 1 hour)
9        time_start: Start time in ISO format
10        time_end: End time in ISO format
11    
12    Returns:
13        List of exchange rate data points with OHLC data
14    """
15    url = f"{BASE_URL}/v1/exchangerate/{asset_id_base}/{asset_id_quote}/history"
16    
17    params = {
18        'period_id': period_id,
19        'time_start': time_start,
20        'time_end': time_end,
21        'limit': 10000
22    }
23    
24    headers = {
25        'X-CoinAPI-Key': API_KEY
26    }
27    
28    try:
29        print(f"šŸ”„ Fetching data from {url}")
30        print(f"šŸ“… Time range: {time_start} to {time_end}")
31        
32        response = requests.get(url, params=params, headers=headers)
33        response.raise_for_status()
34        
35        data = response.json()
36        print(f"āœ… Successfully fetched {len(data)} data points")
37        return data
38        
39    except requests.exceptions.RequestException as e:
40        print(f"āŒ Error fetching data: {e}")
41        if hasattr(e, 'response') and e.response is not None:
42            print(f"Response status: {e.response.status_code}")
43            print(f"Response text: {e.response.text}")
44        return None
45
46print("šŸ“‹ Data fetching function created successfully!")

šŸ“‹ Data fetching function created successfully!

Now let's fetch historical exchange rate data for BTC/USDT. We'll request data at a 1-hour interval for the past 7 days.

1# Check if API key is configured
2if API_KEY == "YOUR_COINAPI_KEY_HERE":
3    print("āŒ ERROR: Please set your CoinAPI key in the previous cell!")
4    print("šŸ”— Get your API key at: https://www.coinapi.io/")
5    print("šŸ“ Replace 'YOUR_COINAPI_KEY_HERE' with your actual API key")
6else:
7    # Set up time range (last 7 days)
8    end_time = datetime.now(timezone.utc)
9    start_time = end_time - timedelta(days=7)
10    
11    # Format times for API
12    time_start = start_time.strftime('%Y-%m-%dT%H:%M:%S')
13    time_end = end_time.strftime('%Y-%m-%dT%H:%M:%S')
14    
15    # Fetch BTC/USDT data
16    asset_id_base = "BTC"
17    asset_id_quote = "USDT"
18    period_id = "1HRS"
19    
20    print(f"šŸŽÆ Fetching {asset_id_base}/{asset_id_quote} data")
21    print(f"ā±ļø  Period: {period_id}")
22    
23    exchange_rate_data = fetch_exchange_rate_data(asset_id_base, asset_id_quote, period_id, time_start, time_end)
24    
25    if exchange_rate_data:
26        print("\nšŸ“Š Sample data structure:")
27        print(json.dumps(exchange_rate_data[0], indent=2))
28    else:
29        print("\nāŒ Failed to fetch data. Please check your API key and try again.")

šŸŽÆ Fetching BTC/USDT data
ā±ļø Period: 1HRS
šŸ”„ Fetching data from https://rest.coinapi.io/v1/exchangerate/BTC/USDT/history
šŸ“… Time range: 2025-07-08T15:07:12 to 2025-07-15T15:07:12
āœ… Successfully fetched 168 data points

šŸ“Š Sample data structure:
{
"time_period_start": "2025-07-08T16:00:00.0000000Z",
"time_period_end": "2025-07-08T17:00:00.0000000Z",
"time_open": "2025-07-08T16:00:00.1000000Z",
"time_close": "2025-07-08T16:59:59.9000000Z",
"rate_open": 108273.16295175275,
"rate_high": 108559.27205797151,
"rate_low": 108089.54247934539,
"rate_close": 108446.6117630905
}

Now let's convert the raw API data into a pandas DataFrame for easier analysis and perform some data cleaning.

1if 'exchange_rate_data' in locals() and exchange_rate_data:
2    # Convert to DataFrame
3    df = pd.DataFrame(exchange_rate_data)
4    
5    print(f"šŸ“ˆ DataFrame created with shape: {df.shape}")
6    print(f"šŸ“‹ Columns: {list(df.columns)}")
7    
8    # Convert time columns to datetime
9    df['time_period_start'] = pd.to_datetime(df['time_period_start'])
10    df['time_period_end'] = pd.to_datetime(df['time_period_end'])
11    
12    # Rename columns for clarity
13    df = df.rename(columns={
14        'rate_open': 'open',
15        'rate_high': 'high',
16        'rate_low': 'low',
17        'rate_close': 'close'
18    })
19    
20    # Sort by time
21    df = df.sort_values('time_period_start')
22    
23    print("\nšŸ“Š First few rows:")
24    display(df.head())
25    
26    print("\nšŸ“‹ Data types:")
27    print(df.dtypes)
28    
29    print("\nšŸ“ˆ Summary statistics:")
30    display(df[['open', 'high', 'low', 'close']].describe())
31    
32    # Check for missing values
33    print("\nšŸ” Missing values check:")
34    missing_values = df.isnull().sum()
35    if missing_values.sum() > 0:
36        print(missing_values[missing_values > 0])
37    else:
38        print("āœ… No missing values found!")
39        
40else:
41    print("āŒ No data available for processing.")

šŸ“ˆ DataFrame created with shape: (168, 8)
šŸ“‹ Columns: ['time_period_start', 'time_period_end', 'time_open', 'time_close', 'rate_open', 'rate_high', 'rate_low', 'rate_close']

šŸ“Š First few rows:

time_period_start time_period_end time_opentime_closeopen high lowclose
02025-07-08 16:00:00+00:002025-07-08 17:00:00+00:002025-07-08T16:00:00.1000000Z2025-07-08T16:59:59.9000000Z108273.162952108559.272058108089.542479108446.611763
12025-07-08 17:00:00+00:002025-07-08 18:00:00+00:002025-07-08T17:00:00.0000000Z2025-07-08T17:59:59.9000000Z108446.560951 109118.903087108433.060883108992.512505
22025-07-08 18:00:00+00:002025-07-08 19:00:00+00:002025-07-08T18:00:00.0000000Z2025-07-08T18:59:59.8000000Z108992.511813109172.372158108914.395031 109160.054626
32025-07-08 19:00:00+00:002025-07-08 20:00:00+00:002025-07-08T19:00:00.0000000Z 2025-07-2025-07-08T19:59:59.9000000Z109160.054626109166.228089108747.781101108778.801776
42025-07-08 20:00:00+00:002025-07-08 21:00:00+00:002025-07-08T20:00:00.0000000Z2025-07-08T20:59:59.9000000Z108779.333043108949.665184108640.644820108680.949952

šŸ“‹ Data types:
time_period_start datetime64[ns, UTC]
time_period_end datetime64[ns, UTC]
time_open object
time_close object
open float64
high float64
low float64
close float64
dtype: object

šŸ“ˆ Summary statistics:

openhighlowclose
count168.000000168.000000168.000000168.000000
mean115701.871611 116019.444476115414.747858115748.644910
std4110.9609314130.6859094030.0088084069.899305
min108273.162952108559.272058108089.542479108375.914978
25% 111239.876258111430.712077111012.066202111242.310857
50% 117485.272231117663.490559117195.364793117485.272231
75% 118091.978431118453.823024117851.778283118091.183057
max122737.262279123225.589450 122281.080900122731.331256

šŸ” Missing values check:
āœ… No missing values found!

Volatility indicators help us understand the magnitude of price movements and market activity. We'll calculate several volatility-based indicators from the data:

  • Price Range: High - Low (absolute volatility)
  • Normalized Volatility: (High - Low) / Close (relative volatility)
  • Average True Range (ATR): A more sophisticated volatility measure
  • Volatility Ratio: Current volatility vs historical average
  • Moving Averages: Simple moving averages for trend analysis
1if 'df' in locals() and not df.empty:
2    print("šŸ”¢ Calculating volatility indicators...")
3    
4    # Basic volatility indicators
5    df['volatility'] = df['high'] - df['low']  # Price range
6    df['normalized_volatility'] = (df['high'] - df['low']) / df['close']  # Relative volatility
7    
8    # Calculate True Range (TR) for ATR
9    df['tr1'] = df['high'] - df['low']
10    df['tr2'] = abs(df['high'] - df['close'].shift(1))
11    df['tr3'] = abs(df['low'] - df['close'].shift(1))
12    df['true_range'] = df[['tr1', 'tr2', 'tr3']].max(axis=1)
13    
14    # Calculate ATR (14-period average)
15    df['atr'] = df['true_range'].rolling(window=14).mean()
16    
17    # Calculate volatility ratio (current vs historical average)
18    df['volatility_ratio'] = df['normalized_volatility'] / df['normalized_volatility'].rolling(window=20).mean()
19    
20    # Calculate simple moving averages
21    df['sma_20'] = df['close'].rolling(window=20).mean()
22    df['sma_50'] = df['close'].rolling(window=50).mean()
23    
24    print("āœ… Volatility indicators calculation complete!")
25    
26    print("\nšŸ“Š Sample data with volatility indicators:")
27    display(df[['time_period_start', 'close', 'volatility', 'normalized_volatility', 'atr', 'volatility_ratio']].head(10))
28    
29    # Show volatility statistics
30    print("\nšŸ“ˆ Volatility Statistics:")
31    print(f"Average Volatility: ${df['volatility'].mean():.2f}")
32    print(f"Average Normalized Volatility: {df['normalized_volatility'].mean():.4f}")
33    print(f"Average ATR: ${df['atr'].mean():.2f}")
34    print(f"Average Volatility Ratio: {df['volatility_ratio'].mean():.2f}")
35    
36    # Show moving average statistics
37    print("\nšŸ“Š Moving Average Statistics:")
38    print(f"20-period SMA: ${df['sma_20'].iloc[-1]:.2f}")
39    print(f"50-period SMA: ${df['sma_50'].iloc[-1]:.2f}")
40    
41else:
42    print("āŒ No data available for volatility calculation.")

šŸ”¢ Calculating volatility indicators...
āœ… Volatility indicators calculation complete!

šŸ“Š Sample data with volatility indicators:

time_period_startclosevolatilitynormalized_volatilityatrvolatility_ratio
02025-07-08 16:00:00+00:00108446.611763469.7295790.004331NaNNaN
12025-07-08 17:00:00+00:00108992.512505685.8422040.006293NaNNaN
22025-07-08 18:00:00+00:00109160.054626257.9771270.002363NaNNaN
32025-07-08 19:00:00+00:00108778.801776418.4469870.003847NaNNaN
42025-07-08 20:00:00+00:00108680.949952309.0203650.002843NaNNaN
52025-07-08 21:00:00+00:00108899.559914357.6659720.003284NaNNaN
62025-07-08 22:00:00+00:00108921.280819167.4934170.001538NaNNaN
72025-07-08 23:00:00+00:00108928.659916153.2509580.001407NaNNaN
82025-07-09 00:00:00+00:00108936.011746184.1631910.001691NaNNaN
92025-07-09 01:00:00+00:00108782.495298409.5001440.003764NaNNaN

šŸ“ˆ Volatility Statistics:
Average Volatility: $604.70
Average Normalized Volatility: 0.0052
Average ATR: $596.55
Average Volatility Ratio: 1.11

šŸ“Š Moving Average Statistics:
20-period SMA: $117862.17
50-period SMA: $119296.47

āš ļø Minimum Data Requirements for Rolling Indicators

  • ATR (14-period): Requires at least 14 data points (e.g., 14 hours for 1HRS interval) before the first valid value appears. The first 13 rows will be NaN.
  • Volatility Ratio (20-period): Requires at least 20 data points (e.g., 20 hours for 1HRS interval) before the first valid value appears. The first 19 rows will be NaN.
  • SMA 20: Requires 20 data points before the first valid value.
  • SMA 50: Requires 50 data points before the first valid value.

If you want all indicators to have valid values for the entire sample, expand your time range so you have at least 50 data points (e.g., 50 hours for 1HRS interval, or ~2.1 days).

We'll analyze price trends by comparing each value to the previous one and identify volatility patterns. This helps us understand market conditions and potential trading opportunities.

1if 'df' in locals() and 'normalized_volatility' in df.columns:
2    print("šŸ“ˆ Analyzing price trends and volatility patterns...")
3    
4    # Calculate price trend direction
5    df['price_change'] = df['close'].diff()
6    df['price_trend'] = np.where(df['price_change'] > 0, 'Upward', 'Downward')
7    
8    # Handle the first row (no previous value)
9    df.loc[df.index[0], 'price_trend'] = 'No Change'
10    
11    # Identify volatility regimes
12    volatility_threshold = df['normalized_volatility'].quantile(0.75)  # 75th percentile
13    df['volatility_regime'] = np.where(df['normalized_volatility'] > volatility_threshold, 'High', 'Low')
14    
15    # Calculate trend statistics
16    trend_counts = df['price_trend'].value_counts()
17    volatility_counts = df['volatility_regime'].value_counts()
18    
19    print("āœ… Trend analysis complete!")
20    
21    print(f"\nšŸ“Š Total periods analyzed: {len(df)}")
22    
23    print("\nšŸ“ˆ Price trend distribution:")
24    for trend, count in trend_counts.items():
25        percentage = (count / len(df)) * 100
26        print(f"  {trend}: {count} periods ({percentage:.1f}%)")
27    
28    print("\nšŸ“Š Volatility regime distribution:")
29    for regime, count in volatility_counts.items():
30        percentage = (count / len(df)) * 100
31        print(f"  {regime} Volatility: {count} periods ({percentage:.1f}%)")
32    
33    print("\nšŸ“‹ Sample data with trend and volatility analysis:")
34    display(df[['time_period_start', 'close', 'price_change', 'price_trend', 'normalized_volatility', 'volatility_regime']].head(10))
35    
36    # Calculate average price change by trend
37    print("\nšŸ“Š Average price change by trend:")
38    trend_stats = df.groupby('price_trend')['price_change'].agg(['mean', 'std', 'count'])
39    display(trend_stats)
40    
41else:
42    print("āŒ No data available for trend analysis.")

šŸ“ˆ Analyzing price trends and volatility patterns...
āœ… Trend analysis complete!

šŸ“Š Total periods analyzed: 168

šŸ“ˆ Price trend distribution:
Upward: 89 periods (53.0%)
Downward: 78 periods (46.4%)
No Change: 1 periods (0.6%)

šŸ“Š Volatility regime distribution:
Low Volatility: 126 periods (75.0%)
High Volatility: 42 periods (25.0%)

šŸ“‹ Sample data with trend and volatility analysis:

time_period_startcloseprice_changeprice_trendnormalized_volatilityvolatility_regime
02025-07-08 16:00:00+00:00108446.611763NaNNo Change 0.004331Low
12025-07-08 17:00:00+00:00108992.512505545.900742Upward0.006293Low
22025-07-08 18:00:00+00:00109160.054626167.542121Upward0.002363Low
32025-07-08 19:00:00+00:00108778.801776-381.252850Downward0.003847Low
42025-07-08 20:00:00+00:00108680.949952-97.851824 Downward0.002843Low
52025-07-08 21:00:00+00:00108899.559914218.609962Upward0.003284Low
62025-07-08 22:00:00+00:00108921.28081921.720905Upward0.001538Low
72025-07-08 23:00:00+00:00108928.6599167.379097Upward0.001407Low
82025-07-09 00:00:00+00:00108936.0117467.351830Upward0.001691Low
92025-07-09 01:00:00+00:00108782.495298-153.516448 Downward0.003764Low

šŸ“Š Average price change by trend:

meanstdcount
price_trend
Downward-276.674972330.352230 78
No ChangeNaNNaN0
Upward329.231522440.77501289

Let's create comprehensive visualizations to show price trends, volatility patterns, and their relationships. We'll create multiple charts to provide different perspectives on the data.

1if 'df' in locals() and not df.empty:
2    print("šŸŽØ Creating comprehensive visualizations...")
3    
4    # Create a comprehensive visualization with 4 subplots
5    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))
6    fig.suptitle('Price Trend Analysis with Volatility Indicators', fontsize=16, fontweight='bold')
7    
8    # Plot 1: Price with Moving Averages
9    ax1.plot(df['time_period_start'], df['close'], label='Close Price', linewidth=2, color='blue')
10    ax1.plot(df['time_period_start'], df['sma_20'], label='20-period SMA', linewidth=2, alpha=0.7, color='red')
11    ax1.plot(df['time_period_start'], df['sma_50'], label='50-period SMA', linewidth=2, alpha=0.7, color='green')
12    ax1.set_title('Price Trend with Moving Averages', fontweight='bold')
13    ax1.set_xlabel('Time')
14    ax1.set_ylabel('Price (USDT)')
15    ax1.legend()
16    ax1.grid(True, alpha=0.3)
17    
18    # Plot 2: Volatility
19    ax2.bar(df['time_period_start'], df['volatility'], alpha=0.7, color='lightblue')
20    ax2.set_title('Price Volatility Over Time', fontweight='bold')
21    ax2.set_xlabel('Time')
22    ax2.set_ylabel('Volatility (USDT)')
23    ax2.grid(True, alpha=0.3)
24    
25    # Plot 3: Normalized Volatility
26    ax3.plot(df['time_period_start'], df['normalized_volatility'], color='orange', linewidth=2)
27    ax3.axhline(y=df['normalized_volatility'].mean(), color='red', linestyle='--', alpha=0.7, label='Average')
28    ax3.set_title('Normalized Volatility Over Time', fontweight='bold')
29    ax3.set_xlabel('Time')
30    ax3.set_ylabel('Normalized Volatility')
31    ax3.legend()
32    ax3.grid(True, alpha=0.3)
33    
34    # Plot 4: ATR
35    ax4.plot(df['time_period_start'], df['atr'], color='green', linewidth=2)
36    ax4.set_title('Average True Range (ATR)', fontweight='bold')
37    ax4.set_xlabel('Time')
38    ax4.set_ylabel('ATR (USDT)')
39    ax4.grid(True, alpha=0.3)
40    
41    plt.tight_layout()
42    plt.show()
43    
44    print("āœ… Main visualization complete!")
45    
46else:
47    print("āŒ No data available for visualization.")

šŸŽØ Creating comprehensive visualizations...


āœ… Main visualization complete!

1if 'df' in locals() and not df.empty:
2    print("šŸŽØ Creating trend and volatility correlation plot...")
3    
4    # Create trend and volatility correlation plot
5    plt.figure(figsize=(12, 8))
6    
7    # Color code by trend
8    colors = {'Upward': 'green', 'Downward': 'red', 'No Change': 'gray'}
9    
10    for trend in df['price_trend'].unique():
11        mask = df['price_trend'] == trend
12        plt.scatter(df[mask]['normalized_volatility'], df[mask]['price_change'], 
13                   c=colors[trend], label=trend, alpha=0.6, s=50)
14    
15    plt.xlabel('Normalized Volatility')
16    plt.ylabel('Price Change (USDT)')
17    plt.title('Price Change vs Volatility by Trend', fontweight='bold')
18    plt.legend()
19    plt.grid(True, alpha=0.3)
20    plt.show()
21    
22    print("āœ… Correlation plot complete!")
23    
24else:
25    print("āŒ No data available for correlation plot.")

šŸŽØ Creating trend and volatility correlation plot...

āœ… Correlation plot complete!

Let's perform a comprehensive statistical analysis of our findings and provide insights about the price trend and volatility analysis.

1if 'df' in locals() and not df.empty:
2    print("šŸ“Š Performing comprehensive statistical analysis...")
3    
4    print("=" * 60)
5    print("PRICE TREND AND VOLATILITY ANALYSIS SUMMARY")
6    print("=" * 60)
7    
8    print(f"šŸ“… Analysis Period: {df['time_period_start'].min()} to {df['time_period_start'].max()}")
9    print(f"šŸ“Š Total Data Points: {len(df)}")
10    
11    print("\n" + "=" * 40)
12    print("PRICE STATISTICS")
13    print("=" * 40)
14    print(f"šŸ’° Starting Price: ${df['close'].iloc[0]:.2f}")
15    print(f"šŸ’° Ending Price: ${df['close'].iloc[-1]:.2f}")
16    print(f"šŸ“ˆ Total Price Change: ${df['close'].iloc[-1] - df['close'].iloc[0]:.2f}")
17    print(f"šŸ“Š Percentage Change: {((df['close'].iloc[-1] / df['close'].iloc[0]) - 1) * 100:.2f}%")
18    
19    print("\n" + "=" * 40)
20    print("VOLATILITY STATISTICS")
21    print("=" * 40)
22    print(f"šŸ“Š Average Volatility: {df['volatility'].mean():.4f}")
23    print(f"šŸ“Š Volatility Range: {df['volatility'].min():.4f} - {df['volatility'].max():.4f}")
24    print(f"šŸ“Š Average Normalized Volatility: {df['normalized_volatility'].mean():.4f}")
25    print(f"šŸ“Š Average ATR: {df['atr'].mean():.4f}")
26    
27    print("\n" + "=" * 40)
28    print("TREND ANALYSIS")
29    print("=" * 40)
30    trend_summary = df['price_trend'].value_counts()
31    for trend, count in trend_summary.items():
32        percentage = (count / len(df)) * 100
33        print(f"šŸ“ˆ {trend} Trend: {count} periods ({percentage:.1f}%)")
34    
35    print("\n" + "=" * 40)
36    print("VOLATILITY REGIME ANALYSIS")
37    print("=" * 40)
38    volatility_summary = df['volatility_regime'].value_counts()
39    for regime, count in volatility_summary.items():
40        percentage = (count / len(df)) * 100
41        print(f"šŸ“Š {regime} Volatility: {count} periods ({percentage:.1f}%)")
42    
43    # Calculate correlation between price change and volatility
44    correlation = df['price_change'].corr(df['normalized_volatility'])
45    print("\n" + "=" * 40)
46    print("CORRELATION ANALYSIS")
47    print("=" * 40)
48    print(f"šŸ“Š Price Change vs Volatility Correlation: {correlation:.4f}")
49    
50    if abs(correlation) > 0.3:
51        print("šŸ”— Strong correlation detected between price changes and volatility.")
52    elif abs(correlation) > 0.1:
53        print("šŸ”— Moderate correlation detected between price changes and volatility.")
54    else:
55        print("šŸ”— Weak correlation between price changes and volatility.")
56    
57    print("\n" + "=" * 60)
58    print("ANALYSIS COMPLETE!")
59    print("=" * 60)
60    
61else:
62    print("āŒ No data available for summary analysis.")

šŸ“Š Performing comprehensive statistical analysis...
============================================================
PRICE TREND AND VOLATILITY ANALYSIS SUMMARY
============================================================
šŸ“… Analysis Period: 2025-07-08 16:00:00+00:00 to 2025-07-15 15:00:00+00:00
šŸ“Š Total Data Points: 168

========================================
PRICE STATISTICS
========================================
šŸ’° Starting Price: $108446.61
šŸ’° Ending Price: $116167.57
šŸ“ˆ Total Price Change: $7720.96
šŸ“Š Percentage Change: 7.12%

========================================
VOLATILITY STATISTICS
========================================
šŸ“Š Average Volatility: 604.6966
šŸ“Š Volatility Range: 133.7623 - 3402.2335
šŸ“Š Average Normalized Volatility: 0.0052
šŸ“Š Average ATR: 596.5474

========================================
TREND ANALYSIS
========================================
šŸ“ˆ Upward Trend: 89 periods (53.0%)
šŸ“ˆ Downward Trend: 78 periods (46.4%)
šŸ“ˆ No Change Trend: 1 periods (0.6%)

========================================
VOLATILITY REGIME ANALYSIS
========================================
šŸ“Š Low Volatility: 126 periods (75.0%)
šŸ“Š High Volatility: 42 periods (25.0%)

========================================
CORRELATION ANALYSIS
========================================
šŸ“Š Price Change vs Volatility Correlation: 0.2708
šŸ”— Moderate correlation detected between price changes and volatility.

============================================================
ANALYSIS COMPLETE!
============================================================

Based on our analysis, here are the key insights we can draw:

  • The distribution of upward vs downward trends shows market sentiment
  • Moving averages help identify fair value and potential support/resistance levels
  • Price changes relative to moving averages indicate buying/selling pressure
  • Normalized Volatility: Shows relative price movement regardless of absolute price
  • ATR: Provides a smoothed measure of market volatility
  • Volatility Regimes: Help identify different market conditions (calm vs turbulent)
  • Volatility Ratio: Indicates if current volatility is above/below historical average
  • The correlation between price changes and volatility reveals market dynamics
  • Strong positive correlation might indicate momentum-driven markets
  • Weak correlation might suggest range-bound or news-driven markets
  • High volatility periods often present both risk and opportunity
  • Trend direction combined with volatility analysis provides better entry/exit signals
  • Moving averages can serve as dynamic support/resistance levels
  • ATR helps in setting appropriate stop-loss levels

You can modify this analysis by changing:

  • Trading Pair: Change asset_id_base and asset_id_quote (e.g., 'ETH', 'ADA')
  • Time Period: Modify the timedelta(days=7) to analyze different timeframes
  • Interval: Change period_id to '1MIN', '1HRS', '1DAY' for different granularity
  • Indicators: Add more technical indicators like RSI, MACD, Bollinger Bands
  1. Multi-timeframe Analysis: Compare different time periods
  2. Cross-asset Correlation: Analyze relationships between different cryptocurrencies
  3. Pattern Recognition: Implement candlestick pattern detection
  4. Backtesting: Test trading strategies based on the indicators

In this tutorial, we successfully:

āœ… Fetched historical exchange rate data using the CoinAPI Market Data REST API āœ… Calculated comprehensive volatility indicators including ATR and normalized volatility āœ… Detected and analyzed price trends with statistical rigor āœ… Created professional visualizations showing multiple perspectives on the data āœ… Performed correlation analysis to understand market dynamics āœ… Provided actionable insights for trading and investment decisions

  • Volatility indicators help identify periods of high and low market activity
  • Price trends combined with volatility analysis provide better trading insights
  • ATR (Average True Range) is a robust measure of market volatility
  • Moving averages serve as dynamic trend indicators
  • Volatility regimes help identify different market conditions

This tutorial demonstrates how to use the CoinAPI Market Data REST API for advanced price trend and volatility analysis, providing a solid foundation for cryptocurrency market analysis and trading strategy development.

Happy analyzing! šŸ“ˆšŸ“Š