note: betting against black markets
In the biotech industry, phase III clinical trials make or break a company. Selling call options is a nice way to make a premium on biotech startups since the calls are not affected by the increased implied volatilty of these trials the way that put options are. With nine in ten biotech startups failing, this is a good way to have a nice run of positive returns before facing the unbounded drawdown for the 10% of biotech startups that don't fail at phase III clinical trials. So unless you have 30 years of experience working in biotech, it is practically gambling to short biotech startups. It is not as risky as 0-DTE out of the money SPY calls (betting against the brokers on how much the S&P will drop today), but that is not saying much.
A similar strategy might be to sell calls against bitcoin when black markets crash. The dark web makes up a small fraction of the internet, with estimates ranging from less than 0.01% to about 5% of the total content. This is different from the deep web which is much larger, making up about 90% of the internet with private databases, email, subscription content, and so on. The marketshare of black markets on the web has fluctuated between 1 to 2 billion USD over the past ten years. Most transactions on the dark web use cryptocurrency, so it might be reasonable to ask whether shutdowns of major marketplaces affect the volatility of a popular cryptocurrency like bitcoin. The answer may surprise you.
There is the risk of being added to a government watchlist for using the router needed to access darkweb sites, and being added to another list for downloading the live operating system you need to better protect yourself from bad actors on the darkweb. But this is not an issue if you are not doing anything illegal. And these bad actors will likely still get personal information through social engineering while you are tring to predict any major crashes. But here is an analysis in the event that you do want to scrape black markets to identify canaries before shutdowns become public knowledge.
Is there a chance to profit from the financial risks in betting against bitcoin when the black markets crash?
This is not finanicial advice, and the following code was made with a lot of assistance from an LLM.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
from datetime import datetime, timedelta
import requests
import warnings
warnings.filterwarnings('ignore')
class BitcoinVolatilityAnalysis:
def __init__(self):
self.dnm_events = {
'Silk Road 1.0': '2013-10-02',
'Silk Road 2.0': '2014-11-06',
'AlphaBay': '2017-07-04',
'Hansa': '2017-07-20',
'Wall Street Market': '2019-04-01',
'Hydra': '2022-04-05'
}
def get_bitcoin_data(self, start_date='2013-01-01', end_date=None):
"""Get Bitcoin price data from Yahoo Finance"""
if end_date is None:
end_date = datetime.now().strftime('%Y-%m-%d')
print("Downloading Bitcoin price data...")
btc = yf.download('BTC-USD', start=start_date, end=end_date, progress=False)
return btc
def calculate_historical_volatility(self, prices, window=30):
"""Calculate historical volatility (as proxy for implied volatility)"""
# Ensure we're working with a Series
if isinstance(prices, pd.DataFrame):
prices = prices.iloc[:, 0] # Take first column if it's a DataFrame
returns = np.log(prices / prices.shift(1))
volatility = returns.rolling(window=window).std() * np.sqrt(365) * 100 # Annualized percentage
return volatility
def plot_volatility_with_events(self, btc_data, volatility):
"""Plot volatility with DNM events marked"""
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10))
# Plot 1: Price and volatility
color = 'tab:blue'
ax1.set_xlabel('Date')
ax1.set_ylabel('BTC Price (USD)', color=color)
ax1.plot(btc_data.index, btc_data['Close'], color=color, alpha=0.7, linewidth=1)
ax1.tick_params(axis='y', labelcolor=color)
ax1.set_yscale('log') # Log scale for better visualization
# Add volatility on second y-axis
ax1b = ax1.twinx()
color = 'tab:red'
ax1b.set_ylabel('30-Day Volatility (%)', color=color)
ax1b.plot(volatility.index, volatility.values, color=color, alpha=0.8, linewidth=1.5, label='Volatility')
ax1b.tick_params(axis='y', labelcolor=color)
ax1b.grid(True, alpha=0.3)
# Plot 2: Just volatility with events
ax2.plot(volatility.index, volatility.values, color='red', linewidth=2, label='30-Day Historical Volatility')
ax2.set_xlabel('Date')
ax2.set_ylabel('Volatility (%)')
ax2.set_title('Bitcoin Volatility with Darknet Market Shutdown Events', fontsize=14, fontweight='bold')
ax2.grid(True, alpha=0.3)
# Add vertical lines for events
colors = ['red', 'blue', 'green', 'orange', 'purple', 'brown']
for i, (event, date) in enumerate(self.dnm_events.items()):
event_date = pd.to_datetime(date)
if event_date >= volatility.index[0] and event_date <= volatility.index[-1]:
# Find the closest volatility value
closest_idx = volatility.index[volatility.index.get_indexer([event_date], method='nearest')[0]]
closest_vol = volatility.loc[closest_idx]
ax2.axvline(x=event_date, color=colors[i % len(colors)], linestyle='--',
alpha=0.8, linewidth=2, label=f'{event} ({date})')
ax2.annotate(event, xy=(closest_idx, closest_vol),
xytext=(10, 10), textcoords='offset points', fontsize=8,
bbox=dict(boxstyle='round,pad=0.3', facecolor=colors[i % len(colors)], alpha=0.1),
arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0', color=colors[i % len(colors)]))
ax2.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
return fig
def plot_event_study_comparison(self, volatility):
"""Plot side-by-side comparison of events"""
fig, axes = plt.subplots(2, 3, figsize=(18, 10))
axes = axes.flatten()
for i, (event, date) in enumerate(self.dnm_events.items()):
if i >= len(axes):
break
event_date = pd.to_datetime(date)
# Get event window data
start_date = event_date - timedelta(days=45)
end_date = event_date + timedelta(days=45)
# Filter volatility data for the event window
mask = (volatility.index >= start_date) & (volatility.index <= end_date)
event_volatility = volatility[mask].copy()
if not event_volatility.empty:
# Convert to Series if it's a DataFrame
if isinstance(event_volatility, pd.DataFrame):
event_volatility = event_volatility.iloc[:, 0]
days_from_event = [(idx - event_date).days for idx in event_volatility.index]
ax = axes[i]
ax.plot(days_from_event, event_volatility.values, color='blue', linewidth=2)
ax.axvline(x=0, color='red', linestyle='--', linewidth=2, label='Event Date')
ax.set_title(f'{event}\n{date}', fontweight='bold', fontsize=10)
ax.set_xlabel('Days from Event')
ax.set_ylabel('Volatility (%)')
ax.grid(True, alpha=0.3)
ax.legend()
else:
axes[i].set_title(f'{event}\nNo data', fontweight='bold')
axes[i].text(0.5, 0.5, 'No volatility data\nfor this period',
ha='center', va='center', transform=axes[i].transAxes)
plt.suptitle('Bitcoin Volatility Around Darknet Market Shutdowns\n45-Day Event Windows',
fontsize=16, fontweight='bold')
plt.tight_layout()
return fig
def calculate_abnormal_volatility(self, volatility):
"""Calculate abnormal volatility around events"""
results = {}
# Ensure volatility is a Series
if isinstance(volatility, pd.DataFrame):
volatility = volatility.iloc[:, 0]
for event, date in self.dnm_events.items():
event_date = pd.to_datetime(date)
# Check if event date is within our data range
if event_date < volatility.index[0] or event_date > volatility.index[-1]:
print(f"Skipping {event} - event date outside data range")
continue
# Estimation window (30 days before event, excluding immediate pre-event period)
est_start = event_date - timedelta(days=45)
est_end = event_date - timedelta(days=15)
estimation_mask = (volatility.index >= est_start) & (volatility.index <= est_end)
estimation_data = volatility[estimation_mask]
if len(estimation_data) > 5: # Need sufficient data
baseline_vol = estimation_data.mean()
# Event window (15 days before and after)
event_window_start = event_date - timedelta(days=15)
event_window_end = event_date + timedelta(days=15)
event_mask = (volatility.index >= event_window_start) & (volatility.index <= event_window_end)
event_data = volatility[event_mask].copy()
if len(event_data) > 0:
# Calculate abnormal volatility
abnormal_vol = event_data - baseline_vol
# Create a clean series with days as integers
days_from_event = [(idx - event_date).days for idx in abnormal_vol.index]
abnormal_vol_clean = pd.Series(abnormal_vol.values, index=days_from_event, name=event)
# Get event date volatility
event_vol_value = None
if event_date in volatility.index:
event_vol_value = volatility.loc[event_date]
else:
# Find closest date
closest_idx = volatility.index[volatility.index.get_indexer([event_date], method='nearest')[0]]
event_vol_value = volatility.loc[closest_idx]
results[event] = {
'baseline_vol': baseline_vol,
'abnormal_vol': abnormal_vol_clean,
'event_date': event_date,
'event_volatility': event_vol_value
}
print(f"Processed {event}")
else:
print(f"No event window data for {event}")
else:
print(f"Insufficient estimation data for {event}")
return results
def plot_cumulative_abnormal_volatility(self, results):
"""Plot cumulative abnormal volatility across all events"""
if not results:
print("No results to plot")
return None
fig, ax = plt.subplots(figsize=(12, 6))
# Create a common index from -15 to +15 days
common_index = list(range(-15, 16))
# Prepare data for averaging
all_abnormal_vol = []
valid_events = []
for event, data in results.items():
abnormal_vol = data['abnormal_vol']
if len(abnormal_vol) > 0:
# Create a series with the common index, filling missing values with NaN
event_series = pd.Series(index=common_index, dtype=float)
for day in common_index:
if day in abnormal_vol.index:
event_series[day] = abnormal_vol[day]
all_abnormal_vol.append(event_series)
valid_events.append(event)
# Create DataFrame and calculate averages
if all_abnormal_vol:
combined_df = pd.DataFrame(all_abnormal_vol).T
combined_df.columns = valid_events
# Calculate average abnormal volatility (ignoring NaN values)
combined_df['Average_Abnormal_Vol'] = combined_df.mean(axis=1, skipna=True)
combined_df['Cumulative_Avg'] = combined_df['Average_Abnormal_Vol'].cumsum()
# Plot cumulative abnormal volatility
ax.plot(combined_df.index, combined_df['Cumulative_Avg'],
linewidth=3, color='red', marker='o', markersize=4,
label='Cumulative Average Abnormal Volatility')
ax.axvline(x=0, color='black', linestyle='--', linewidth=2, label='Event Date')
ax.axhline(y=0, color='gray', linestyle='-', alpha=0.5)
ax.set_xlabel('Days from Event')
ax.set_ylabel('Cumulative Abnormal Volatility (%)')
ax.set_title('Cumulative Abnormal Volatility Around DNM Shutdowns\n(Across All Events)',
fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3)
ax.legend()
# Add some statistics to the plot
max_abnormal = combined_df['Average_Abnormal_Vol'].max()
min_abnormal = combined_df['Average_Abnormal_Vol'].min()
final_cumulative = combined_df['Cumulative_Avg'].iloc[-1]
ax.text(0.02, 0.98,
f'Max Daily Abnormal: {max_abnormal:.1f}%\nMin Daily Abnormal: {min_abnormal:.1f}%\nFinal Cumulative: {final_cumulative:.1f}%',
transform=ax.transAxes, verticalalignment='top', fontsize=10,
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
plt.tight_layout()
return fig
def print_detailed_analysis(self, results):
"""Print detailed analysis of the results"""
print("\n" + "="*70)
print("DETAILED VOLATILITY ANALYSIS")
print("="*70)
if not results:
print("No results to analyze")
return
for event, data in results.items():
event_vol = data.get('event_volatility')
baseline_vol = data['baseline_vol']
print(f"\n{event}:")
print(f" Event Date: {data['event_date'].strftime('%Y-%m-%d')}")
print(f" Baseline Volatility: {baseline_vol:.1f}%")
if event_vol is not None:
abnormal = event_vol - baseline_vol
print(f" Event Date Volatility: {event_vol:.1f}%")
print(f" Abnormal Volatility: {abnormal:+.1f}%")
if abnormal > 5:
print(" STRONG POSITIVE IMPACT")
elif abnormal > 2:
print(" MODERATE POSITIVE IMPACT")
elif abnormal > 0:
print(" SLIGHT POSITIVE IMPACT")
elif abnormal < -2:
print(" NEGATIVE IMPACT")
else:
print(" MINIMAL IMPACT")
# Show pre/post event averages
abnormal_vol = data['abnormal_vol']
pre_event = abnormal_vol[abnormal_vol.index < 0].mean()
post_event = abnormal_vol[abnormal_vol.index > 0].mean()
print(f" Pre-Event Avg Abnormal: {pre_event:+.1f}%")
print(f" Post-Event Avg Abnormal: {post_event:+.1f}%")
def main():
analyzer = BitcoinVolatilityAnalysis()
# Get Bitcoin data
print("Starting Bitcoin Volatility Analysis...")
btc_data = analyzer.get_bitcoin_data()
if btc_data.empty:
print("Failed to download Bitcoin data")
return
print(f"Downloaded data from {btc_data.index[0].strftime('%Y-%m-%d')} to {btc_data.index[-1].strftime('%Y-%m-%d')}")
# Calculate 30-day historical volatility (proxy for IV)
print("Calculating volatility...")
volatility = analyzer.calculate_historical_volatility(btc_data['Close'], window=30)
volatility = volatility.dropna()
print(f"Volatility calculated for {len(volatility)} trading days")
print(f"Volatility type: {type(volatility)}, shape: {volatility.shape if hasattr(volatility, 'shape') else 'N/A'}")
# Plot 1: Main volatility chart with events
print("\nCreating main volatility plot...")
fig1 = analyzer.plot_volatility_with_events(btc_data, volatility)
plt.show()
# Plot 2: Event study comparison
print("Creating event study plots...")
fig2 = analyzer.plot_event_study_comparison(volatility)
plt.show()
# Calculate and plot abnormal volatility
print("Calculating abnormal volatility...")
results = analyzer.calculate_abnormal_volatility(volatility)
if results:
print(f"Successfully analyzed {len(results)} events")
fig3 = analyzer.plot_cumulative_abnormal_volatility(results)
if fig3:
plt.show()
# Print detailed analysis
analyzer.print_detailed_analysis(results)
# Overall conclusion
print("\n" + "="*70)
print("OVERALL CONCLUSION")
print("="*70)
total_events = len(results)
positive_impact = sum(1 for data in results.values()
if data.get('event_volatility', 0) - data['baseline_vol'] > 0)
print(f"Events with increased volatility: {positive_impact}/{total_events} ({positive_impact/total_events*100:.0f}%)")
if positive_impact / total_events > 0.6:
print("STRONG EVIDENCE: DNM shutdowns generally increase Bitcoin volatility")
elif positive_impact / total_events > 0.4:
print("MODERATE EVIDENCE: Mixed impact on Bitcoin volatility")
else:
print("WEAK EVIDENCE: DNM shutdowns have limited effect on Bitcoin volatility")
else:
print("No valid results to analyze")
if __name__ == "__main__":
main()
Starting Bitcoin Volatility Analysis... Downloading Bitcoin price data... Downloaded data from 2014-09-17 to 2025-11-13 Calculating volatility... Volatility calculated for 4046 trading days Volatility type: <class 'pandas.core.series.Series'>, shape: (4046,) Creating main volatility plot...
Creating event study plots...
Calculating abnormal volatility... Skipping Silk Road 1.0 - event date outside data range Processed Silk Road 2.0 Processed AlphaBay Processed Hansa Processed Wall Street Market Processed Hydra Successfully analyzed 5 events
====================================================================== DETAILED VOLATILITY ANALYSIS ====================================================================== Silk Road 2.0: Event Date: 2014-11-06 Baseline Volatility: 68.5% Event Date Volatility: 54.6% Abnormal Volatility: -14.0% NEGATIVE IMPACT Pre-Event Avg Abnormal: -7.3% Post-Event Avg Abnormal: -0.9% AlphaBay: Event Date: 2017-07-04 Baseline Volatility: 80.5% Event Date Volatility: 77.9% Abnormal Volatility: -2.7% NEGATIVE IMPACT Pre-Event Avg Abnormal: +4.9% Post-Event Avg Abnormal: -9.8% Hansa: Event Date: 2017-07-20 Baseline Volatility: 86.6% Event Date Volatility: 112.5% Abnormal Volatility: +25.9% STRONG POSITIVE IMPACT Pre-Event Avg Abnormal: -15.9% Post-Event Avg Abnormal: +31.2% Wall Street Market: Event Date: 2019-04-01 Baseline Volatility: 45.3% Event Date Volatility: 22.7% Abnormal Volatility: -22.6% NEGATIVE IMPACT Pre-Event Avg Abnormal: -12.2% Post-Event Avg Abnormal: +14.8% Hydra: Event Date: 2022-04-05 Baseline Volatility: 77.4% Event Date Volatility: 53.6% Abnormal Volatility: -23.8% NEGATIVE IMPACT Pre-Event Avg Abnormal: -6.3% Post-Event Avg Abnormal: -27.8% ====================================================================== OVERALL CONCLUSION ====================================================================== Events with increased volatility: 1/5 (20%) WEAK EVIDENCE: DNM shutdowns have limited effect on Bitcoin volatility
The answer is no, there is only weak evidence that market shutdowns are associated with BTC implied volatility.