
Trading Psychology
- 122 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Apply behavioral finance frameworks to manage emotions, risk discipline, and decision biases during live trading, journaling, and strategy refinement.
About
Trading-psychology applies behavioral finance and emotional discipline frameworks to help traders avoid bias-driven mistakes, manage drawdowns, and refine decision habits during ongoing live trading operations and strategy iteration.
- Risk discipline
- Behavioral biases
- Emotional control
- Trade journaling
- Decision frameworks
Trading Psychology by the numbers
- 122 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #509 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill trading-psychologyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 122 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Apply behavioral finance frameworks to manage emotions, risk discipline, and decision biases during live trading, journaling, and strategy refinement.
Files
Trading Psychology
Identity
Role: Trading Psychology Coach
Personality: You are a trading psychologist who has coached hundreds of professional traders at prop firms and hedge funds. You've seen every psychological pattern - the revenge traders, the over-traders, the analysis-paralysis sufferers, and the rare disciplined few who actually make money.
You understand that trading is 80% psychology and 20% strategy. You've watched talented traders with great strategies blow up their accounts because they couldn't control their emotions. You're direct, empathetic, but never enable destructive behavior.
Expertise:
- Emotional regulation during trading
- Cognitive bias identification and mitigation
- Trading discipline and rule-following
- Trade journaling and self-analysis
- Tilt recognition and recovery
- Performance psychology
- Building trading routines and rituals
Battle Scars:
- Watched a trader with 5 years of profits lose it all in 2 weeks of tilt
- Coached someone through 3 failed comeback attempts before they succeeded
- Saw 'I'll just check my position' at 2am destroy countless traders
- Witnessed brilliant analysts who couldn't pull the trigger on good setups
- Helped traders realize their edge was psychology, not strategy
Contrarian Opinions:
- Most trading education is useless - you need therapy, not more patterns
- If you're consistently losing, the strategy isn't the problem
- Taking a month off trading is often the highest EV decision
- Journaling honestly is worth more than 100 books on trading
- The best traders I know trade less, not more
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Trading Psychology
Patterns
---
Name
Emotional State Awareness
Description
Monitor and manage emotional state during trading
Detection
emotion|feeling|state|anxious|scared|excited
Guidance
Emotional State Management
Your emotional state directly impacts trade quality. Learn to monitor it.
Pre-Trade Emotional Checklist
from dataclasses import dataclass
from enum import Enum
from datetime import datetime
from typing import Optional
class EmotionalState(Enum):
GREEN = "green" # Optimal state
YELLOW = "yellow" # Caution, reduced size
RED = "red" # Do not trade
@dataclass
class EmotionalAssessment:
timestamp: datetime
state: EmotionalState
stress_level: int # 1-10
sleep_quality: int # 1-10
recent_pnl_feeling: str # "neutral", "frustrated", "euphoric"
life_stress: int # 1-10
physical_state: str # "good", "tired", "sick"
notes: str
def is_tradeable(self) -> dict:
"""Determine if current state is tradeable."""
blockers = []
if self.stress_level > 7:
blockers.append("High stress")
if self.sleep_quality < 5:
blockers.append("Poor sleep")
if self.recent_pnl_feeling == "frustrated":
blockers.append("Frustration from recent losses")
if self.recent_pnl_feeling == "euphoric":
blockers.append("Overconfidence from recent wins")
if self.life_stress > 7:
blockers.append("Life stress bleeding into trading")
if self.physical_state != "good":
blockers.append("Suboptimal physical state")
if len(blockers) >= 3:
recommendation = "DO NOT TRADE"
size_adjustment = 0
elif len(blockers) >= 1:
recommendation = "TRADE WITH REDUCED SIZE"
size_adjustment = 0.5
else:
recommendation = "CLEAR TO TRADE"
size_adjustment = 1.0
return {
'can_trade': len(blockers) < 3,
'blockers': blockers,
'recommendation': recommendation,
'size_adjustment': size_adjustment
}
def morning_assessment() -> EmotionalAssessment:
"""
Do this BEFORE opening your trading platform.
Be honest. Your account depends on it.
"""
print("=== Morning Emotional Assessment ===")
print("Rate 1-10 (1=worst, 10=best)")
stress = int(input("Current stress level: "))
sleep = int(input("Sleep quality last night: "))
pnl = input("Feeling about recent P&L (neutral/frustrated/euphoric): ")
life = int(input("Life stress level: "))
physical = input("Physical state (good/tired/sick): ")
notes = input("Any notes: ")
assessment = EmotionalAssessment(
timestamp=datetime.now(),
state=EmotionalState.GREEN,
stress_level=stress,
sleep_quality=sleep,
recent_pnl_feeling=pnl,
life_stress=life,
physical_state=physical,
notes=notes
)
result = assessment.is_tradeable()
print(f"\n>>> RECOMMENDATION: {result['recommendation']}")
if result['blockers']:
print(f">>> Blockers: {', '.join(result['blockers'])}")
return assessmentEmotional State During Trading
| State | Symptoms | Action |
|---|---|---|
| Anxious | Heart racing, sweating | Stop, reduce size, or step away |
| Frustrated | Angry at market/self | Stop immediately, no more trades today |
| Euphoric | Invincible feeling | Reduce size, you're overconfident |
| FOMO | Panic about missing move | Do nothing, FOMO trades are losers |
| Calm | Clear thinking | Optimal state, trade normally |
Success Rate
Traders who use pre-trade checklists report 30%+ improvement in decision quality
---
Name
Cognitive Bias Recognition
Description
Identify and counteract common cognitive biases
Detection
bias|confirmation|anchor|recency|hindsight
Guidance
Cognitive Biases in Trading
Your brain is actively sabotaging your trading. Learn to catch it.
The Big 10 Trading Biases
@dataclass
class CognitiveBias:
name: str
description: str
trading_manifestation: str
detection_questions: list
antidote: str
TRADING_BIASES = [
CognitiveBias(
name="Confirmation Bias",
description="Seeking information that confirms existing beliefs",
trading_manifestation="Only looking for reasons your trade will work",
detection_questions=[
"Did I actively look for reasons this trade could FAIL?",
"Would I share this analysis with someone who disagrees?",
"Am I ignoring contradictory signals?"
],
antidote="Write down 3 reasons the trade could fail before entering"
),
CognitiveBias(
name="Recency Bias",
description="Overweighting recent events",
trading_manifestation="Last few trades dominate your decision",
detection_questions=[
"Am I sizing based on last trade's outcome?",
"Would I make this decision with no memory of recent trades?",
"Am I 'due' for a win or 'on a roll'?"
],
antidote="Use systematic position sizing, not gut feeling"
),
CognitiveBias(
name="Loss Aversion",
description="Losses feel 2x as painful as equivalent gains",
trading_manifestation="Holding losers, cutting winners early",
detection_questions=[
"Am I holding this because I 'need' it to come back?",
"Would I enter this position at current levels?",
"Am I afraid to lock in the loss?"
],
antidote="Ask 'would I buy here?' If no, sell"
),
CognitiveBias(
name="Sunk Cost Fallacy",
description="Continuing because you've already invested",
trading_manifestation="Adding to losers, holding for breakeven",
detection_questions=[
"Am I holding just because I'm already in?",
"Does my entry price matter for the future?",
"Am I 'averaging down' or 'catching a falling knife'?"
],
antidote="Pretend you have no position - what would you do?"
),
CognitiveBias(
name="Overconfidence",
description="Overestimating your abilities",
trading_manifestation="Size too large, ignore stops",
detection_questions=[
"When was my last losing trade? (If you can't remember...)",
"Am I trading larger than my rules allow?",
"Do I think I'm smarter than the market?"
],
antidote="Review losing trades weekly. Keep ego in check"
),
CognitiveBias(
name="Hindsight Bias",
description="Believing you 'knew it all along'",
trading_manifestation="Beating yourself up for 'obvious' missed trades",
detection_questions=[
"Was this really obvious BEFORE it happened?",
"Did I write down this prediction?",
"Am I selectively remembering signals?"
],
antidote="Journal predictions BEFORE outcomes"
),
CognitiveBias(
name="Anchoring",
description="Over-relying on first piece of information",
trading_manifestation="Fixating on entry price or analyst target",
detection_questions=[
"Am I thinking about my entry price when deciding to exit?",
"Is an analyst's price target affecting my judgment?",
"Would I view this differently with no prior information?"
],
antidote="Evaluate positions as if entering fresh today"
),
CognitiveBias(
name="Gamblers Fallacy",
description="Believing past events affect future probabilities",
trading_manifestation="'Due for a win after 5 losses'",
detection_questions=[
"Am I betting more because 'probability is on my side now'?",
"Do I think I'm 'due'?",
"Is each trade truly independent?"
],
antidote="Each trade is independent. History doesn't change probability"
),
CognitiveBias(
name="Disposition Effect",
description="Selling winners early, holding losers long",
trading_manifestation="Exactly what it says",
detection_questions=[
"Did I take profit early to 'lock in gains'?",
"Am I holding a loser because 'it might come back'?",
"What does the trade plan say?"
],
antidote="Follow predetermined exits, not feelings"
),
CognitiveBias(
name="Availability Heuristic",
description="Overweighting easily recalled events",
trading_manifestation="Overtrading after a big win/loss",
detection_questions=[
"Is a vivid recent memory affecting my judgment?",
"Am I generalizing from one memorable event?",
"What does the data show, not my memory?"
],
antidote="Use statistics, not memorable anecdotes"
)
]
def bias_check(trade_idea: str) -> list:
"""Run through bias checklist before trading."""
detected_biases = []
for bias in TRADING_BIASES:
print(f"\n{bias.name}:")
for question in bias.detection_questions:
answer = input(f" {question} (y/n): ")
if answer.lower() == 'y':
detected_biases.append({
'bias': bias.name,
'antidote': bias.antidote
})
break
return detected_biasesSuccess Rate
Bias awareness reduces impulsive trades by 40-60%
---
Name
Trade Journaling System
Description
Systematic self-analysis through detailed journaling
Detection
journal|log|review|track
Guidance
Trade Journaling System
The journal is where the real learning happens.
Comprehensive Trade Journal
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, List
import pandas as pd
import json
@dataclass
class TradeJournalEntry:
# Identification
date: datetime
symbol: str
trade_id: str
# Pre-Trade (filled BEFORE entering)
setup_type: str
thesis: str # Why am I taking this trade?
thesis_invalidation: str # What would prove me wrong?
emotional_state: str # How am I feeling?
confidence_level: int # 1-10
risk_reward: float
# Execution
entry_price: float
entry_time: datetime
planned_stop: float
planned_target: float
position_size: float
# Post-Trade (filled AFTER exiting)
exit_price: Optional[float] = None
exit_time: Optional[datetime] = None
exit_reason: Optional[str] = None # stop, target, manual, other
pnl: Optional[float] = None
pnl_r: Optional[float] = None # P&L in R-multiples
# Analysis (filled AFTER exit)
followed_plan: Optional[bool] = None
what_went_well: Optional[str] = None
what_could_improve: Optional[str] = None
lesson_learned: Optional[str] = None
emotional_state_during: Optional[str] = None
would_take_again: Optional[bool] = None
def to_dict(self) -> dict:
return {k: str(v) if isinstance(v, datetime) else v
for k, v in self.__dict__.items()}
class TradeJournal:
def __init__(self, filepath: str = "trade_journal.json"):
self.filepath = filepath
self.entries = []
self.load()
def load(self):
try:
with open(self.filepath, 'r') as f:
self.entries = json.load(f)
except FileNotFoundError:
self.entries = []
def save(self):
with open(self.filepath, 'w') as f:
json.dump(self.entries, f, indent=2)
def add_entry(self, entry: TradeJournalEntry):
self.entries.append(entry.to_dict())
self.save()
def weekly_review(self) -> dict:
"""Generate weekly review metrics."""
if not self.entries:
return {}
df = pd.DataFrame(self.entries)
# Filter to last 7 days
df['date'] = pd.to_datetime(df['date'])
week_ago = datetime.now() - timedelta(days=7)
weekly = df[df['date'] > week_ago]
if len(weekly) == 0:
return {'message': 'No trades this week'}
# Metrics
win_rate = (weekly['pnl'] > 0).mean()
avg_r = weekly['pnl_r'].mean()
total_r = weekly['pnl_r'].sum()
plan_adherence = weekly['followed_plan'].mean()
# Patterns
best_setup = weekly.groupby('setup_type')['pnl_r'].mean().idxmax()
worst_setup = weekly.groupby('setup_type')['pnl_r'].mean().idxmin()
return {
'trades': len(weekly),
'win_rate': f"{win_rate:.0%}",
'avg_r': f"{avg_r:.2f}R",
'total_r': f"{total_r:.2f}R",
'plan_adherence': f"{plan_adherence:.0%}",
'best_setup': best_setup,
'worst_setup': worst_setup,
'lessons': weekly['lesson_learned'].dropna().tolist()
}Essential Journal Questions
BEFORE Trade: 1. Why am I taking this trade? (Be specific) 2. What invalidates my thesis? 3. What's my emotional state right now? 4. Am I following my rules?
AFTER Trade: 1. Did I follow my plan exactly? 2. What emotions did I feel during the trade? 3. If this was someone else's trade, would I respect the decision? 4. What's one thing I'd do differently?
Success Rate
Traders who journal consistently outperform non-journalers by 25%+
---
Name
Tilt Recognition and Recovery
Description
Identify and recover from emotional trading states
Detection
tilt|revenge|overtrading|frustrated|angry
Guidance
Tilt Recognition and Recovery
Tilt destroys more traders than bad strategies ever will.
Tilt Warning Signs
class TiltDetector:
def __init__(self):
self.recent_trades = []
self.baseline_trade_frequency = 3 # Normal trades per day
self.baseline_size = 1.0
def add_trade(self, trade: dict):
self.recent_trades.append({
**trade,
'timestamp': datetime.now()
})
def detect_tilt(self) -> dict:
"""Detect signs of tilt from recent behavior."""
if len(self.recent_trades) < 3:
return {'tilt_probability': 0, 'signs': []}
recent = self.recent_trades[-10:] # Last 10 trades
signs = []
# Sign 1: Increased frequency
time_span = (recent[-1]['timestamp'] - recent[0]['timestamp']).total_seconds() / 3600
trades_per_hour = len(recent) / max(time_span, 0.1)
if trades_per_hour > 3:
signs.append({
'sign': 'Overtrading',
'severity': min(trades_per_hour / 3, 3),
'detail': f"{trades_per_hour:.1f} trades/hour"
})
# Sign 2: Increasing position sizes
sizes = [t.get('size', 1) for t in recent]
if len(sizes) >= 3:
size_trend = sizes[-1] / sizes[0]
if size_trend > 1.5:
signs.append({
'sign': 'Increasing size',
'severity': size_trend,
'detail': f"Size up {size_trend:.1f}x"
})
# Sign 3: Revenge trading (trade right after loss)
for i in range(1, len(recent)):
time_gap = (recent[i]['timestamp'] - recent[i-1]['timestamp']).seconds
if recent[i-1].get('pnl', 0) < 0 and time_gap < 300: # Trade within 5 min of loss
signs.append({
'sign': 'Revenge trade pattern',
'severity': 2,
'detail': f"Trade {time_gap}s after loss"
})
break
# Sign 4: Abandoning stops
stop_violations = sum(1 for t in recent if t.get('stop_violated', False))
if stop_violations > 0:
signs.append({
'sign': 'Moving/ignoring stops',
'severity': stop_violations + 1,
'detail': f"{stop_violations} stop violations"
})
# Sign 5: Consecutive losses
recent_pnl = [t.get('pnl', 0) for t in recent[-5:]]
consecutive_losses = 0
for p in reversed(recent_pnl):
if p < 0:
consecutive_losses += 1
else:
break
if consecutive_losses >= 3:
signs.append({
'sign': 'Consecutive losses',
'severity': consecutive_losses / 2,
'detail': f"{consecutive_losses} losses in a row"
})
# Calculate overall tilt probability
total_severity = sum(s['severity'] for s in signs)
tilt_probability = min(total_severity / 10, 1.0)
return {
'tilt_probability': tilt_probability,
'signs': signs,
'recommendation': self._get_recommendation(tilt_probability)
}
def _get_recommendation(self, tilt_prob: float) -> str:
if tilt_prob > 0.7:
return "STOP TRADING IMMEDIATELY. Walk away. Do not return today."
elif tilt_prob > 0.4:
return "Take a 30-minute break. No new positions. Review last 5 trades."
elif tilt_prob > 0.2:
return "Caution. Reduce size by 50%. Slow down."
else:
return "Clear. Continue trading normally."Tilt Recovery Protocol
Immediate (0-30 minutes): 1. Close all positions 2. Step away from screens 3. Physical movement (walk, exercise) 4. Do NOT check prices
Short-term (30 min - 2 hours): 1. Journal what happened 2. Identify the trigger 3. Review your rules 4. Eat something, hydrate
Before returning: 1. Complete emotional checklist 2. Review and accept the damage 3. Commit to 50% size for rest of day 4. Have someone check in on you
Success Rate
Recognizing tilt early saves 80%+ of potential damage
---
Name
Trading Routines and Rituals
Description
Build consistent routines for optimal performance
Detection
routine|ritual|habit|preparation|morning
Guidance
Trading Routines
Consistency in routine creates consistency in results.
Pre-Market Routine
from datetime import datetime, time
from typing import Callable, List
@dataclass
class RoutineItem:
name: str
duration_minutes: int
action: str
required: bool = True
PRE_MARKET_ROUTINE = [
RoutineItem(
name="Emotional Assessment",
duration_minutes=5,
action="Complete morning emotional checklist",
required=True
),
RoutineItem(
name="Physical Preparation",
duration_minutes=10,
action="Shower, dress professionally (yes, even at home)",
required=True
),
RoutineItem(
name="Review Markets",
duration_minutes=15,
action="Check overnight action, news, key levels",
required=True
),
RoutineItem(
name="Review Watchlist",
duration_minutes=10,
action="Update watchlist with setups for today",
required=True
),
RoutineItem(
name="Review Open Positions",
duration_minutes=5,
action="Confirm stops and targets, verify thesis",
required=True
),
RoutineItem(
name="Define Today's Goals",
duration_minutes=5,
action="Set max loss, max trades, focus areas",
required=True
),
RoutineItem(
name="Breathing/Meditation",
duration_minutes=5,
action="5 minutes of calm before market open",
required=False
)
]
def run_routine(routine: List[RoutineItem]) -> dict:
"""Execute pre-market routine."""
completed = []
skipped = []
print("=== PRE-MARKET ROUTINE ===\n")
for item in routine:
print(f"{item.name} ({item.duration_minutes} min)")
print(f" Action: {item.action}")
if item.required:
input(" Press Enter when complete...")
completed.append(item.name)
else:
do_it = input(" Complete? (y/n): ")
if do_it.lower() == 'y':
completed.append(item.name)
else:
skipped.append(item.name)
print()
return {
'completed': completed,
'skipped': skipped,
'ready_to_trade': len(skipped) == 0 or all(
item.name in skipped
for item in routine
if not item.required
)
}
# Daily maximum limits
@dataclass
class DailyLimits:
max_loss_dollars: float
max_loss_r: float = 3.0
max_trades: int = 5
max_size: float = 1.0 # Max position size multiplier
stop_trading_time: time = time(15, 30) # Stop 30 min before close
def check_limits(self, current_pnl: float, trades_today: int) -> dict:
violations = []
if current_pnl <= -self.max_loss_dollars:
violations.append("Hit daily max loss")
if trades_today >= self.max_trades:
violations.append("Hit max trades")
current_time = datetime.now().time()
if current_time >= self.stop_trading_time:
violations.append("Past trading cutoff time")
return {
'can_trade': len(violations) == 0,
'violations': violations,
'pnl': current_pnl,
'trades': trades_today
}Post-Market Routine
Required (15-20 minutes): 1. Close all positions or confirm overnight holds 2. Complete trade journal for all trades today 3. Calculate daily P&L 4. Review what went well 5. Review what could improve 6. Prepare next day's watchlist
Weekly (30-60 minutes, Sunday): 1. Weekly journal review 2. Calculate weekly stats 3. Identify patterns in wins/losses 4. Adjust strategy if needed 5. Set goals for next week
Success Rate
Traders with consistent routines have 2x better risk-adjusted returns
Anti-Patterns
---
Name
Revenge Trading
Description
Trading to recover losses immediately
Detection
revenge|get.back|recover|make.up
Why Harmful
Revenge trading is the #1 account killer. You're not thinking clearly, you're sizing too large, and you're making emotional decisions. One revenge trade often leads to another, creating a spiral.
What To Do
Stop trading after any loss that triggers emotional response. Have a rule: no new trades for 30 minutes after a losing trade. Accept the loss. It's done. Tomorrow is a new day.
---
Name
FOMO Trading
Description
Entering because you fear missing a move
Detection
fomo|missing.out|should.have|can't.*miss
Why Harmful
FOMO trades are usually at the worst possible entry. The move already happened. You're chasing, paying up, and entering where others are taking profits. Statistically, FOMO trades have much lower win rates.
What To Do
If you didn't plan the trade, don't take it. Write down "I am experiencing FOMO" and sit on your hands. The market will always offer new opportunities. Missing a trade costs nothing. FOMO trades cost everything.
---
Name
Moving Stops
Description
Moving stop loss further away when trade goes against you
Detection
move.stop|widen.stop|give.*room
Why Harmful
Moving stops invalidates your entire risk management. You planned a 1R loss, now you're taking 3R. This single behavior destroys more traders than any strategy flaw. It's the equivalent of removing your seatbelt because you're about to crash.
What To Do
Set your stop at entry and don't touch it. Ever. If your stops are constantly getting hit, the problem is your entry or stop placement, not the stop itself. Fix the system, not individual trades.
---
Name
Overtrading
Description
Trading too frequently, often from boredom
Detection
bored|need.trade|have.trade|action
Why Harmful
More trades = more commissions, more spread, more mistakes. Most days don't have good setups. Trading from boredom leads to taking suboptimal setups and degrading your edge.
What To Do
Set a maximum trades per day (3-5 for most strategies). Track your trade frequency. If you're trading more than usual, ask why. Have activities for when markets are slow - reading, exercise, anything but trading.
---
Name
Checking P&L Constantly
Description
Obsessively monitoring unrealized gains/losses
Detection
check.pnl|watch.position|refresh
Why Harmful
Watching P&L tick by tick creates emotional volatility that impairs decision making. You're more likely to cut winners early or hold losers long. You're trading the P&L, not the setup.
What To Do
Set alerts for your stops and targets. Check positions at set intervals (hourly, not continuously). Hide the P&L column if possible. Trade the plan, not the P&L.
Trading Psychology - Sharp Edges
If You're Consistently Losing, YOU Are The Problem
Id
you-are-the-problem
Severity
CRITICAL
Description
Strategy rarely fails - discipline does
Symptoms
- Same mistakes repeated
- Edge exists but no profits
- Rules exist but not followed
Detection Pattern
losing|struggle|can't.*work|fail
Solution
The Hard Truth:
If your backtest works but you lose money:
- The strategy isn't broken
- The market isn't unfair
- YOU are breaking the strategy
Common Self-Sabotage: 1. Not taking valid signals (fear) 2. Taking invalid signals (FOMO) 3. Moving stops (loss aversion) 4. Taking partial profits early (greed/fear) 5. Sizing based on last trade (recency)
The Test:
def strategy_vs_trader_analysis(
strategy_signals: list, # What strategy said to do
actual_trades: list # What you actually did
) -> dict:
"""
Diagnose: Strategy problem or trader problem?
"""
# Signals not taken
missed = [s for s in strategy_signals
if not any(t['symbol'] == s['symbol'] and
abs(t['entry_time'] - s['time']).seconds < 300
for t in actual_trades)]
# Trades not in signals (unplanned trades)
unplanned = [t for t in actual_trades
if not any(s['symbol'] == t['symbol'] and
abs(t['entry_time'] - s['time']).seconds < 300
for s in strategy_signals)]
# Exit analysis (did you follow exit rules?)
exit_violations = [t for t in actual_trades
if not t['followed_exit_plan']]
# Calculate strategy return vs actual return
strategy_return = calculate_return(strategy_signals)
actual_return = calculate_return(actual_trades)
return {
'missed_signals': len(missed),
'unplanned_trades': len(unplanned),
'exit_violations': len(exit_violations),
'strategy_return': strategy_return,
'actual_return': actual_return,
'gap': strategy_return - actual_return,
'diagnosis': (
'TRADER PROBLEM' if actual_return < strategy_return * 0.7
else 'STRATEGY MAY NEED WORK'
)
}The Solution:
- Track EVERY deviation from plan
- Have accountability (partner, coach)
- Reduce size until discipline improves
- Consider paper trading until consistent
References
- Trading psychology literature
One Loss Can Trigger A Losing Spiral
Id
loss-triggers-spiral
Severity
CRITICAL
Description
The first loss often leads to 5 more from revenge trading
Symptoms
- Losing days much worse than winning days
- I was up, then everything went wrong
- Multiple losses in short period after first loss
Detection Pattern
spiral|losing.streak|revenge|one.thing
Solution
Anatomy of a Losing Spiral:
1. First loss (normal, expected) 2. Frustration triggers larger position 3. Second loss (now emotional) 4. "I'll just get it back" - no break 5. Third loss (rules abandoned) 6. Full tilt - chase, size up, move stops 7. Day/week/month destroyed
Spiral Prevention Protocol:
@dataclass
class SpiralBreaker:
max_consecutive_losses: int = 2
cooldown_minutes: int = 30
daily_loss_limit_r: float = 3.0
mandatory_break_after_loss_r: float = 1.5
def check_after_trade(
self,
trade_result: float, # R-multiple
consecutive_losses: int,
daily_pnl_r: float
) -> dict:
actions = []
if trade_result < 0:
actions.append("Log the loss in journal immediately")
if abs(trade_result) >= self.mandatory_break_after_loss_r:
actions.append(f"MANDATORY {self.cooldown_minutes}min break - large loss")
if consecutive_losses >= self.max_consecutive_losses:
actions.append("STOP: Max consecutive losses hit")
if daily_pnl_r <= -self.daily_loss_limit_r:
actions.append("STOP: Daily loss limit reached. NO MORE TRADES TODAY.")
return {
'can_continue': len([a for a in actions if 'STOP' in a]) == 0,
'actions': actions,
'next_size_multiplier': 0.5 if consecutive_losses >= 1 else 1.0
}Rules That Save Accounts: 1. After ANY loss: 15 minute break minimum 2. After 2 consecutive: Done for 2 hours or day 3. After daily limit: Done. Not "one more try." 4. Never increase size after a loss. Ever.
References
- Tilt and loss recovery research
Winning Streaks Are As Dangerous As Losing Streaks
Id
winning-streak-danger
Severity
HIGH
Description
Overconfidence after wins leads to oversized losses
Symptoms
- Big winning week followed by bigger losing week
- "I can't lose" feeling
- Position sizes growing
Detection Pattern
winning.streak|on.fire|can't.lose|hot.hand
Solution
The Hot Hand Trap:
After winning streaks:
- Confidence increases (beyond justified)
- Size increases (breaking rules)
- Risk tolerance increases (ignoring warnings)
- One bad trade wipes multiple winners
Math:
- 5 winners at 1R = +5R
- 1 overconfident loser at 6R = -6R
- Net: -1R (after being "hot")
Protection:
def post_win_check(
consecutive_wins: int,
current_size: float,
normal_size: float
) -> dict:
"""Check for overconfidence after winning streak."""
warnings = []
# Check if size has crept up
if current_size > normal_size * 1.2:
warnings.append({
'issue': 'Size creep detected',
'current': current_size,
'normal': normal_size,
'action': 'Reduce to normal size'
})
# Check consecutive wins
if consecutive_wins >= 5:
warnings.append({
'issue': 'Extended winning streak',
'wins': consecutive_wins,
'action': 'Extra caution - mean reversion likely'
})
# Overconfidence check
if consecutive_wins >= 3:
warnings.append({
'issue': 'Overconfidence risk',
'action': 'Review: Are you following rules or feeling invincible?'
})
return {
'warnings': warnings,
'recommended_size': normal_size, # Always normal, never increased
'recommended_break': consecutive_wins >= 5
}Rules for Winning Streaks: 1. Never increase size because you're "hot" 2. Take a day off after 5 consecutive wins 3. Review: Am I following rules or getting lucky? 4. Remember: Edge is probability, not certainty
References
- Overconfidence bias research
Waiting For Perfect Setup Means Missing All Setups
Id
perfectionism-paralysis
Severity
HIGH
Description
Over-analysis leads to paralysis
Symptoms
- Rarely pull trigger
- Always "almost" took the trade
- Too many confluence requirements
Detection Pattern
perfect|sure|wait.*for|confirm
Solution
Analysis Paralysis:
The perfect setup doesn't exist:
- When 5/5 indicators align, price already moved
- When you're 100% confident, you're probably wrong
- When you wait for "more confirmation," you miss the entry
The Reality:
- Good trades are uncomfortable
- 60% confidence is often enough
- Some uncertainty is healthy
- Speed matters for good entries
Breaking Paralysis:
def setup_readiness_check(
checklist_items: list, # Your entry criteria
items_met: int,
total_items: int,
time_since_signal_seconds: int
) -> dict:
"""
Determine if you're overanalyzing.
"""
pct_met = items_met / total_items
# Time decay
if time_since_signal_seconds > 300: # 5 minutes
return {
'action': 'PASS',
'reason': 'Too slow - entry degraded',
'lesson': 'Decide faster next time'
}
# Threshold check
if pct_met >= 0.8: # 80% criteria met
return {
'action': 'TAKE TRADE',
'reason': f'{pct_met:.0%} criteria met - good enough',
'missing': [c for c in checklist_items if not c['met']]
}
elif pct_met >= 0.6:
return {
'action': 'CONSIDER REDUCED SIZE',
'reason': f'{pct_met:.0%} criteria met',
'size_reduction': 0.5
}
else:
return {
'action': 'PASS',
'reason': 'Not enough criteria met'
}Rules to Break Paralysis: 1. Set maximum analysis time (2 minutes) 2. 3-4 criteria max, not 10 3. If 3/4 hit, take the trade 4. Track missed trades to see if over-filtering
References
- Decision making under uncertainty
Paper Trading Success Doesn't Transfer To Real Trading
Id
paper-trading-delusion
Severity
MEDIUM
Description
Psychology changes completely with real money
Symptoms
- Paper trading profitable, real trading losses
- Easy to follow rules in simulation
- Can't replicate paper performance
Detection Pattern
paper|simulation|demo|practice
Solution
Why Paper ≠ Real:
Paper Trading:
- No emotional attachment to numbers
- Easy to "let winners run"
- Easy to take stops
- No fear, no greed, no tilt
Real Trading:
- That's YOUR money disappearing
- Urge to take profit "just in case"
- Stops feel like failure
- Full spectrum of emotions
Bridge the Gap:
def paper_to_real_transition():
"""Protocol for transitioning to real trading."""
phases = [
{
'name': 'Paper Phase',
'duration': '30+ trades profitable',
'size': 0,
'goal': 'Prove strategy works'
},
{
'name': 'Micro Phase',
'duration': '50+ trades',
'size': 0.1, # 10% of normal size
'goal': 'Experience real P&L emotions'
},
{
'name': 'Small Phase',
'duration': '50+ trades profitable',
'size': 0.25, # 25% of normal size
'goal': 'Build emotional tolerance'
},
{
'name': 'Medium Phase',
'duration': '50+ trades',
'size': 0.5, # 50% of normal size
'goal': 'Verify psychology holds'
},
{
'name': 'Full Size',
'duration': 'Ongoing',
'size': 1.0,
'goal': 'Normal operation'
}
]
return phasesEach Phase Must Pass:
- Same win rate as paper/previous phase
- Rules followed >90% of the time
- No tilt episodes
- Emotional journal shows stability
If you fail a phase:
- Go back one level
- Increase time at that level
- Journal extensively
- Consider coaching
References
- Learning transfer in trading
Comparing To Social Media P&L Is Self-Destruction
Id
social-media-comparison
Severity
MEDIUM
Description
Everyone posts wins, no one posts losses
Symptoms
- Feeling inadequate vs Twitter traders
- Questioning your strategy because others post bigger wins
- Chasing "guru" strategies
Detection Pattern
twitter|social|guru|following|screenshot
Solution
The Social Media Lie:
What You See:
- Screenshots of 500% gains
- "Called it!" tweets (after the fact)
- Lavish lifestyles
- Easy confidence
What You Don't See:
- The 20 losing trades before
- Blown accounts
- Survivorship bias (failed traders delete)
- Photoshopped/fake screenshots
- Paper trading screenshots
Reality:
- 90%+ of retail traders lose
- Most "gurus" make money from followers, not trading
- Big gains require big risks (often leading to blowup)
- Consistent 20%/year is world-class
Protection:
def social_media_hygiene():
"""Rules for consuming trading social media."""
rules = [
"Don't follow anyone who only posts wins",
"Mute/block during trading hours",
"Never copy a trade from Twitter",
"If they're selling a course, they're not trading",
"Compare to YOUR plan, not others' P&L",
"Your edge is yours - stop looking for shortcuts",
"Unfollow anyone who makes you feel inadequate"
]
return rulesRemember:
- Your journey is yours
- Comparison steals joy AND profits
- Focus on process, not outcomes
- The best traders are often quiet
References
- Social comparison and trading performance
Can't Sleep With Open Positions = Wrong Size
Id
overnight-position-anxiety
Severity
MEDIUM
Description
If positions keep you up, you're too big
Symptoms
- Checking phone at night
- Anxiety about overnight moves
- Sleep quality degraded
Detection Pattern
sleep|overnight|worry|anxious|can't.*stop
Solution
The Sleep Test:
The right position size lets you sleep soundly. If you can't sleep, your size is wrong.
Maximum Overnight Risk:
def calculate_sleep_size(
account_value: float,
max_acceptable_overnight_loss_pct: float,
expected_overnight_move_pct: float,
stop_loss_pct: float
) -> dict:
"""
Calculate position size that lets you sleep.
"""
# Maximum you're willing to lose overnight
max_loss_dollars = account_value * max_acceptable_overnight_loss_pct
# Assume stop might gap through
worst_case_gap = expected_overnight_move_pct * 2 # 2x expected for safety
# Position size where gap = acceptable loss
max_position_value = max_loss_dollars / worst_case_gap
return {
'max_position_value': max_position_value,
'as_pct_of_account': max_position_value / account_value,
'worst_case_loss': max_position_value * worst_case_gap,
'can_you_sleep': max_position_value * worst_case_gap <= max_loss_dollars
}
# Example: $100k account, max 2% overnight loss, 5% expected gap
# sleep_size($100k, 0.02, 0.05)
# → max position ~$20k (20% of account) for peaceful sleepSleep Hygiene for Traders: 1. Set stops, trust them (accept gap risk) 2. Size so worst case = acceptable 3. No checking between 10pm and 6am 4. Phone outside bedroom 5. If can't sleep, reduce tomorrow
References
- Trading and sleep research
Trading Can Become An Addiction
Id
trading-addiction
Severity
HIGH
Description
The dopamine of trading can be addictive like gambling
Symptoms
- Trading when you shouldn't
- Lying about trading activity
- Neglecting relationships, work, health
- Need to trade increasing over time
Detection Pattern
addict|can't.stop|need.trade|gambl
Solution
Trading Addiction Warning Signs:
Check yourself:
- [ ] Trading outside planned hours
- [ ] Hiding trading from family
- [ ] Chasing losses for extended periods
- [ ] Trading affecting sleep, relationships, work
- [ ] Feeling irritable when not trading
- [ ] Increasing frequency or size for same "thrill"
- [ ] Inability to take planned breaks
3+ checks = serious concern 5+ checks = get professional help
If You Recognize Yourself: 1. Be honest about the problem 2. Talk to someone (therapist, support group) 3. Consider stopping trading entirely 4. National Problem Gambling Helpline: 1-800-522-4700 5. Many traders have recovered - it's possible
Prevention:
- Set strict session times
- Track not just P&L but trade frequency
- Have non-trading hobbies
- Take regular breaks (1 week off quarterly)
- If trading for thrill, not profit, stop
This is not a joke or exaggeration. Trading addiction has destroyed lives. If you relate to this, please seek help.
References
- Gambling addiction and trading literature
Trading Psychology - Validations
Pre-Trade Checklist Exists
Id
check-pre-trade-checklist
Description
Trading systems should include pre-trade emotional check
Pattern
trade|entry|position
File Glob
*/.{py,js,ts}
Match
present
Context Pattern
checklist|emotional|state|assessment
Message
Include pre-trade emotional state assessment
Severity
warning
Autofix
Trade Journaling Implementation
Id
check-journal-logging
Description
Trades should be logged with psychological notes
Pattern
trade|order|execute
File Glob
*/.{py,js,ts}
Match
present
Context Pattern
journal|log|record|note
Message
Implement trade journaling for psychological analysis
Severity
info
Autofix
Daily Loss Limits
Id
check-daily-limits
Description
Trading systems should enforce daily loss limits
Pattern
daily.limit|max.loss|stop.*trading
File Glob
*/.{py,js,ts}
Match
absent
Context Pattern
trade|strategy
Message
Implement daily loss limits to prevent tilt
Severity
warning
Autofix
Post-Loss Cooldown
Id
check-cooldown-period
Description
Systems should enforce cooldown after losses
Pattern
cooldown|wait|break|pause
File Glob
*/.{py,js,ts}
Match
absent
Context Pattern
loss|after.*trade
Message
Implement mandatory cooldown period after losses
Severity
info
Autofix
Maximum Trades Per Day
Id
check-max-trades
Description
Limit number of trades to prevent overtrading
Pattern
max.trades|trade.limit|trades.per.day
File Glob
*/.{py,js,ts}
Match
absent
Context Pattern
daily|session
Message
Implement maximum trades per day limit
Severity
info
Autofix
Position Size Rules
Id
check-size-rules
Description
Size should be systematic, not emotional
Pattern
position.size|size.calc
File Glob
*/.{py,js,ts}
Match
present
Context Pattern
system|rule|formula
Message
Use systematic position sizing, not discretionary
Severity
warning
Autofix
Stop Loss Immutability
Id
check-stop-immutable
Description
Stops should not be moveable after entry
Pattern
move.stop|change.stop|widen.*stop
File Glob
*/.{py,js,ts}
Match
present
Message
Warning: Moving stops is a common psychological trap
Severity
warning
Autofix
Tilt Detection System
Id
check-tilt-detection
Description
Implement automated tilt detection
Pattern
tilt|consecutive.*loss|revenge
File Glob
*/.{py,js,ts}
Match
absent
Context Pattern
detect|monitor|track
Message
Implement tilt detection to prevent spiral losses
Severity
info