DEV Community

shakti tiwari
shakti tiwari

Posted on

7 Deadly Sins of Retail Algo Trading in India (And How to Avoid Them)

I committed all 7. Lost ₹2 lakh. Here’s the autopsy.

Algorithmic trading sounds simple: write code, connect broker API, let it run. If it were that simple, everyone would be rich.

I ran an algo bot for 18 months. Made every mistake possible. Lost ₹2 lakh, blew up 3 accounts, and got my IP blocked by Dhan twice.

Here are the 7 deadly sins — and the exact fixes that saved my system.

Sin 1: No static IP

The sin: Assuming “any internet connection” works for API trading.

The consequence: Dhan blocked my account for 7 days after IP rotation. Missed expiry week, biggest profit window of the month.

The fix:

# Mac/Linux/Termux — check your IP
curl https://api.ipify.org

# If dynamic, call ISP or set up tunnel
cloudflared tunnel create your-bot
Enter fullscreen mode Exit fullscreen mode

See my Static IP Fix Guide for the complete setup.

Sin 2: Overfitting on backtest

The sin: 95% win rate on historical data, 42% in live market.

The cause: My XGBoost model memorized noise. 300 rows isn’t enough for deep learning.

The fix:

  • Use XGBoost, not LSTM (better with small data)
  • Limit features to 40 (from 150)
  • Walk-forward validation, not train/test split
  • Paper trade for 4 weeks before going live

Mac / Linux / Termux — walk-forward validation:

from sklearn.model_selection import TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(X):
    model.fit(X.iloc[train_idx], y.iloc[train_idx])
    score = model.score(X.iloc[test_idx], y.iloc[test_idx])
    print(f"Fold score: {score:.3f}")
Enter fullscreen mode Exit fullscreen mode

Windows CMD (PowerShell):

# Requires PowerShell 7+ and scikit-learn.NET or invoke Python script
python -c "from sklearn.model_selection import TimeSeriesSplit; print('Use Python script instead')"
Enter fullscreen mode Exit fullscreen mode

Sin 3: Ignoring transaction costs

The sin: Backtest shows ₹50,000 profit. Live shows ₹12,000.

The cause: I forgot Dhan charges ₹20/trade + GST + STT. 127 trades = ₹5,000+ in costs. Plus slippage on NIFTY options: ₹5-10 per lot.

The fix:

# Include ALL costs in backtest
def calculate_net_profit(gross_profit, num_trades):
    brokerage_per_trade = 20  # Dhan charges
    stt_percent = 0.0625  # On sell side
    gst_percent = 0.18

    total_brokerage = num_trades * brokerage_per_trade
    stt = gross_profit * stt_percent / 100
    gst = total_brokerage * gst_percent / 100

    return gross_profit - total_brokerage - stt - gst
Enter fullscreen mode Exit fullscreen mode

Sin 4: No kill switch

The sin: Bot placed 15 losing trades in a row. I was sleeping.

The consequence: ₹45,000 loss in 2 hours. Account dropped 30%.

The fix:

# Max daily loss circuit breaker
MAX_DAILY_LOSS = 50000  # ₹50,000

def check_kill_switch(daily_pnl):
    if daily_pnl <= -MAX_DAILY_LOSS:
        send_telegram_alert("KILL SWITCH ACTIVATED: Daily loss limit hit")
        dhan.cancel_all_orders()
        dhan.disable_auto_trading()
        exit(1)
Enter fullscreen mode Exit fullscreen mode

Telegram alert setup:

# Mac/Linux/Termux
curl -X POST https://api.telegram.org/botYOUR_BOT_TOKEN/sendMessage \
  -d chat_id=YOUR_CHAT_ID \
  -d text="KILL SWITCH: Daily loss limit hit"
Enter fullscreen mode Exit fullscreen mode

Sin 5: Single point of failure

The sin: Everything ran on my Mac. Mac slept. Bot died. Missed 3 signals.

The fix:

  • Primary: Mac + launchd
  • Backup: Android phone + Termux + Ollama
  • Monitor: Cloudflare Tunnel health check

See my Android Trading Guide.

Sin 6: No paper trading phase

The sin: Went live after 1 week of backtesting.

The consequence: Slippage killed me. My “2% stop” became 4% because NIFTY options gap at open.

The fix:

# 4-week paper trading mandatory
PAPER_TRADING_DAYS = 20
live_trades = 0

while live_trades < PAPER_TRADING_DAYS:
    signal = model.predict(latest_data)
    execute_paper_trade(signal)
    live_trades += 1
    time.sleep(60)  # 1-minute bars
Enter fullscreen mode Exit fullscreen mode

Sin 7: Emotional override

The sin: Bot said “CALL.” I thought “PUT” because I was bearish. I overrode. Lost ₹8,000.

The fix:

  • No manual overrides allowed
  • Bot runs, I observe
  • Post-market review only

Python enforcement:

# No override allowed in production
if os.getenv('ENV') == 'production':
    if manual_override_requested:
        send_alert("OVERRIDE BLOCKED: Trading in production mode")
        return jsonify({"error": "Manual override not allowed"}), 403
Enter fullscreen mode Exit fullscreen mode

The recovery

After committing all 7 sins, here’s what saved me:

Fix Time to Implement Cost
Static IP / Tunnel 2 hours Free
XGBoost instead of LSTM 1 day Free
Cost-aware backtest 3 hours Free
Kill switch 1 hour Free
Android backup 4 hours Free
4-week paper phase 1 month Opportunity cost
No-override policy 0 hours Free

Total time: 6 weeks. Total cost: ₹0.

TL;DR

Sin Symptom Fix
No static IP Order rejections Cloudflare Tunnel + auto-update
Overfitting Live ≪ backtest XGBoost, fewer features
Ignoring costs Net profit much lower Include all fees in backtest
No kill switch Catastrophic losses Daily loss circuit breaker
Single failure point Downtime Android backup
No paper phase Slippage surprise 4-week mandatory paper
Emotional override Second-guessing bot Code-level block

Don’t repeat my mistakes. Build once, test thoroughly, deploy with redundancy.


Shakti Tiwari is a trader and developer building optiontradingwithai.in. He co-directs CodeVisser and authored books on trading psychology. Find him on Dev.to as @shaktitiwari715-ai.

Top comments (0)