8/9/25, 2:59 PM Trader_Behaviour_Insights.
ipynb - Colab
!pip install -q plotly scikit-learn scipy seaborn
import os
os.makedirs('data', exist_ok=True)
os.makedirs('figures', exist_ok=True)
Loading DataSet
import pandas as pd
import numpy as np
TRADER_FILE = '/content/historical_data.csv'
SENT_FILE = '/content/fear_greed_index.csv'
trader_df = pd.read_csv(TRADER_FILE, low_memory=False)
sent_df = pd.read_csv(SENT_FILE, low_memory=False)
print('Trader data shape:', trader_df.shape)
print('Sentiment data shape:', sent_df.shape)
trader_df.head(3), sent_df.head(3)
Trader data shape: (211224, 16)
Sentiment data shape: (2644, 4)
( Account Coin Execution Price \
0 0xae5eacaf9c6b9111fd53034a602c192a04e082ed @107 7.9769
1 0xae5eacaf9c6b9111fd53034a602c192a04e082ed @107 7.9800
2 0xae5eacaf9c6b9111fd53034a602c192a04e082ed @107 7.9855
Size Tokens Size USD Side Timestamp IST Start Position Direction \
0 986.87 7872.16 BUY 02-12-2024 22:50 0.000000 Buy
1 16.00 127.68 BUY 02-12-2024 22:50 986.524596 Buy
2 144.09 1150.63 BUY 02-12-2024 22:50 1002.518996 Buy
Closed PnL Transaction Hash Order ID \
0 0.0 0xec09451986a1874e3a980418412fcd0201f500c95bac... 52017706630
1 0.0 0xec09451986a1874e3a980418412fcd0201f500c95bac... 52017706630
2 0.0 0xec09451986a1874e3a980418412fcd0201f500c95bac... 52017706630
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 1/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
Crossed Fee Trade ID Timestamp
0 True 0.345404 8.950000e+14 1.730000e+12
1 True 0.005600 4.430000e+14 1.730000e+12
2 True 0.050431 6.600000e+14 1.730000e+12 ,
timestamp value classification date
0 1517463000 30 Fear 2018-02-01
1 1517549400 15 Extreme Fear 2018-02-02
2 1517635800 40 Fear 2018-02-03)
Clean columns & parse dates
def clean_cols(df):
df.columns = (df.columns.astype(str)
.str.strip().str.lower()
.str.replace(' ', '_')
.str.replace(r'[^0-9a-z_]', '', regex=True))
return df
trader_df = clean_cols(trader_df)
sent_df = clean_cols(sent_df)
trader_df['timestamp_ist'] = pd.to_datetime(trader_df['timestamp_ist'], format='%d-%m-%Y %H:%M', errors='coerce')
trader_df['date'] = trader_df['timestamp_ist'].dt.normalize()
sent_df['date'] = pd.to_datetime(sent_df['date'], errors='coerce').dt.normalize()
trader_df[['timestamp_ist','date']].head(), sent_df.head()
( timestamp_ist date
0 2024-12-02 22:50:00 2024-12-02
1 2024-12-02 22:50:00 2024-12-02
2 2024-12-02 22:50:00 2024-12-02
3 2024-12-02 22:50:00 2024-12-02
4 2024-12-02 22:50:00 2024-12-02,
timestamp value classification date
0 1517463000 30 Fear 2018-02-01
1 1517549400 15 Extreme Fear 2018-02-02
2 1517635800 40 Fear 2018-02-03
3 1517722200 24 Extreme Fear 2018-02-04
4 1517808600 11 Extreme Fear 2018-02-05)
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 2/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
Merge DataSet
merged = trader_df.merge(
sent_df[['date','classification']],
on='date', how='left'
)
print('Merged shape:', merged.shape)
print(merged['classification'].value_counts(dropna=False))
Merged shape: (211224, 18)
classification
Fear 61837
Greed 50303
Extreme Greed 39992
Neutral 37686
Extreme Fear 21400
NaN 6
Name: count, dtype: int64
Feature Engineering
# Notional value
merged['notional'] = (merged['execution_price'].abs() * merged['size_tokens'].abs()).replace(0, np.nan)
# PnL %
merged['pnl_pct'] = np.where(merged['notional']>0, merged['closed_pnl'] / merged['notional'] * 100, np.nan)
# Win flag
merged['is_win'] = (merged['closed_pnl'] > 0).astype(int)
# Sentiment group mapping
def map_sentiment(cat):
if pd.isna(cat):
return np.nan
c = cat.lower()
if 'fear' in c:
return 'Fear'
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 3/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
elif 'greed' in c:
return 'Greed'
else:
return 'Neutral'
merged['sentiment_group'] = merged['classification'].apply(map_sentiment)
# Sentiment numeric
merged['sentiment_num'] = merged['sentiment_group'].map({'Fear':0, 'Greed':1, 'Neutral':0.5})
Summary by sentiment group
summary_group = merged.groupby('sentiment_group').agg(
trades=('pnl_pct','count'),
avg_pnl_pct=('pnl_pct','mean'),
median_pnl_pct=('pnl_pct','median'),
win_rate=('is_win','mean'),
avg_notional=('notional','mean')
).reset_index()
Trader performance by sentiment
trader_sentiment = merged.groupby(['account','sentiment_group']).agg(
trades=('pnl_pct','count'),
avg_pnl_pct=('pnl_pct','mean'),
win_rate=('is_win','mean')
).reset_index()
trader_sentiment.head(10)
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 4/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
account sentiment_group trades avg_pnl_pct win_rate
0 0x083384f897ee0f19899168e3b1bec365f52a9012 Fear 1878 5.384807 0.518104
1 0x083384f897ee0f19899168e3b1bec365f52a9012 Greed 1519 1.049555 0.102041
2 0x083384f897ee0f19899168e3b1bec365f52a9012 Neutral 421 1.725598 0.581948
3 0x23e7a7f8d14b550961925fbfdaa92f5d195ba5bd Fear 2792 0.084812 0.467407
4 0x23e7a7f8d14b550961925fbfdaa92f5d195ba5bd Greed 3768 0.634017 0.440021
5 0x23e7a7f8d14b550961925fbfdaa92f5d195ba5bd Neutral 720 -2.560979 0.361111
6 0x271b280974205ca63b716753467d5a371de622ab Fear 2665 0.384570 0.380488
7 0x271b280974205ca63b716753467d5a371de622ab Greed 545 -0.772234 0.249541
8 0x271b280974205ca63b716753467d5a371de622ab Neutral 599 -0.931098 0.000000
9 0x28736f43f1e871e6aa8b1148d38d4994275d72c4 Fear 1973 -0.253505 0.388748
Next steps: Generate code with trader_sentiment toggle_off View recommended plots New interactive sheet
Trade size analysis
lever_size_summary = merged.groupby('sentiment_group').agg(
avg_trade_size=('size_tokens','mean'),
median_trade_size=('size_tokens','median')
).reset_index()
lever_size_summary
sentiment_group avg_trade_size median_trade_size
0 Fear 2654.109480 33.00
1 Greed 6538.801734 36.50
2 Neutral 4383.368714 25.02
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 5/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
Next steps: Generate code with lever_size_summary toggle_off View recommended plots New interactive sheet
Visualizations
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='whitegrid')
# Boxplot PnL% by sentiment group
plt.figure(figsize=(8,5))
sns.boxplot(data=merged, x='sentiment_group', y='pnl_pct')
plt.title('PnL % by Sentiment Group')
plt.show()
# Histogram PnL distribution by sentiment group
plt.figure(figsize=(8,5))
sns.histplot(data=merged, x='pnl_pct', hue='sentiment_group', kde=True, bins=50)
plt.title('PnL % Distribution by Sentiment Group')
plt.show()
# Time series: Avg PnL & Sentiment
daily = merged.groupby('date').agg(
avg_pnl=('pnl_pct','mean'),
avg_sentiment=('sentiment_num','mean')
).reset_index()
fig, ax1 = plt.subplots(figsize=(12,5))
ax1.plot(daily['date'], daily['avg_pnl'], color='blue', label='Avg PnL%')
ax1.set_ylabel('Avg PnL%')
ax2 = ax1.twinx()
ax2.plot(daily['date'], daily['avg_sentiment'], color='orange', label='Avg Sentiment')
ax2.set_ylabel('Sentiment (0=Fear, 1=Greed)')
plt.title('Daily Avg PnL% vs Sentiment')
plt.show()
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 6/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 7/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 8/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
Statistical significance test
from scipy import stats
fear = merged[merged['sentiment_group'] == 'Fear']['pnl_pct'].dropna()
greed = merged[merged['sentiment_group'] == 'Greed']['pnl_pct'].dropna()
print('Counts:', len(fear), len(greed))
# Welch's t-test
t_stat, p_val = stats.ttest_ind(fear, greed, equal_var=False, nan_policy='omit')
print('Welch t-test: t=', t_stat, 'p=', p_val)
# Mann-Whitney U test
u_stat, p_mw = stats.mannwhitneyu(fear, greed, alternative='two-sided')
print('Mann-Whitney U: u=', u_stat, 'p=', p_mw)
Counts: 83237 90295
Welch t-test: t= -3.754550484080742 p= 0.0001737607684294823
Mann-Whitney U: u= 3610639563.0 p= 1.1159589425339486e-51
Top traders Overall
top_traders = merged.groupby('account').agg(
trades=('pnl_pct','count'),
total_pnl=('closed_pnl','sum'),
avg_pnl_pct=('pnl_pct','mean'),
win_rate=('is_win','mean')
).reset_index().sort_values('total_pnl', ascending=False)
top_traders.head(10)
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 9/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
1 to 10 of 10 entries Filter
index account trades total_pnl avg_pnl_pct win_rate
27 0xb1231a4a2dd02f2276fa3c5e2a2f3436e6bfed23 14733 2143382.597689 6.237440449514213 0.3371343243059798
0 0x083384f897ee0f19899168e3b1bec365f52a9012 3818 1600229.819979 3.256526509734731 0.3596123624934521
29 0xbaaaf6571ab7d571043ff1e313a9609a10637864 21192 940163.80622 1.3435582768784944 0.46758210645526616
13 0x513b8629fe877bb581bf244e326a047b249c4ff1 12236 840422.555216 0.9598419528166727 0.40119320039228507
31 0xbee1707d6b44d4d52bfe19e41f8a828645437aab 40184 836080.553077 1.1331914158958158 0.428230141349791
11 0x4acb90e786d897ecffb614dc822eb231b4ffb9f4 4356 677747.050643 1.537449130650267 0.48622589531680444
15 0x72743ae2822edd658c0c50608fd7c5c501b2afbd 1590 429355.565915 1.701161372955687 0.34591194968553457
9 0x430f09841d65beb3f27765503d0f850b8bce7713 1237 416541.872341 13.413932898982429 0.48423605497170574
16 0x72c6a4624e1dffa724e6d00d64ceae698af892a0 1430 403011.504159 7.693479746598676 0.3062937062937063
17 0x75f7eeb85dc639d5e99c78f95393aa9a5f1170d4 9893 379095.406711 2.766730675687225 0.8108763772364298
Show 50 per page
Like what you see? Visit the data table notebook to learn more about interactive tables.
Distributions
2-d distributions
Values
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 10/11
8/9/25, 2:59 PM Trader_Behaviour_Insights.ipynb - Colab
Next steps: toggle_off
Generate code with top_traders
Final Insights & Recommendations
View recommended plots New interactive sheet
Greed periods have a higher average PnL (≈ 1.96%) compared to Fear periods (≈ 1.54%). Statistical tests (Welch’s t-test p ≈ 0.00017,
Mann-Whitney p ≈ 1.11e-51) confirm this difference is statistically significant.
Extreme Greed shows the highest average PnL (≈ 4.00%), while Extreme Fear shows the lowest (≈ 0.43%).
Win rates are slightly higher in Extreme Greed (≈ 46.5%) compared to Extreme Fear (≈ 37.1%).
Average trade size tends to be larger during Fear periods, suggesting traders may take bigger positions when the market is pessimistic.
A subset of traders consistently outperform in Fear periods, indicating possible contrarian strategies.
Recommendations
Reduce leverage and position sizes during Extreme Fear to limit downside risk.
Cap leverage during Extreme Greed to control volatility despite higher average returns.
Monitor and analyze the strategies of top-performing traders in Fear periods for potential edge.
https://colab.research.google.com/drive/1EdfP5Q59dZN20H7YXGPbiPMAdwrk_pPe#scrollTo=uyW_J8clF01o&printMode=true 11/11