# Freqtrade strategy generation and validation

## Target environment

Riyadh Tencent Cloud server (verify these still hold before use; source of truth is the
project memory `freqtrade-riyadh-server.md`):

- SSH: `ssh -i ~/Downloads/tx.pem ubuntu@43.164.75.52`
- Project: `/data/freqtrade` (docker compose, image `freqtradeorg/freqtrade:stable`)
- Config: `user_data/config.json` — Binance USDT-M futures, isolated margin, dry-run mode
- Strategies: `user_data/strategies/`

## Mapping wallet factors → strategy rules

Wallet behavior only constrains some knobs; the rest come from indicators:

| Wallet observation | Strategy knob |
|---|---|
| Coin universe | `pair_whitelist` (map coins to `XXX/USDT:USDT` pairs; check they exist on Binance futures) |
| Direction bias | `can_short`, long-only vs both |
| Typical leverage | `leverage` callback (cap conservatively, e.g. min(theirs, 3)) |
| Holding period | timeframe + `minimal_roi` horizon (hours→15m/1h, days→4h/1d) |
| Adds/reduces | `position_adjustment_enable` + `adjust_trade_position` |
| Entry style (breakout/dip-buy/momentum) | entry conditions — pick indicators that express the style, not fabricated precision |

State clearly in the strategy docstring which wallets/factors motivated each rule.

## Strategy skeleton

```python
from freqtrade.strategy import IStrategy
import talib.abstract as ta


class SmartMoneyStrategy(IStrategy):
    """Induced from smart-money wallet analysis of <date>.

    Factors: <list wallet-derived factors and which wallets showed them>
    """
    INTERFACE_VERSION = 3
    timeframe = "1h"
    can_short = True
    minimal_roi = {"0": 0.10}
    stoploss = -0.05

    def leverage(self, pair, current_time, current_rate,
                 proposed_leverage, max_leverage, entry_tag, side, **kwargs):
        return 3

    def populate_indicators(self, dataframe, metadata):
        dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
        # ... indicators expressing the induced factors
        return dataframe

    def populate_entry_trend(self, dataframe, metadata):
        # dataframe.loc[<conditions>, "enter_long"] = 1
        # dataframe.loc[<conditions>, "enter_short"] = 1
        return dataframe

    def populate_exit_trend(self, dataframe, metadata):
        return dataframe
```

## Deploy and validate (on the server)

```bash
# copy strategy up
scp -i ~/Downloads/tx.pem SmartMoneyStrategy.py \
    ubuntu@43.164.75.52:/data/freqtrade/user_data/strategies/

# download data (match timeframe; add pairs not yet cached)
cd /data/freqtrade
docker compose run --rm freqtrade download-data \
    --timeframes 1h --timerange 20260101- --pairs BTC/USDT:USDT ETH/USDT:USDT

# backtest
docker compose run --rm freqtrade backtesting \
    --strategy SmartMoneyStrategy --timerange 20260101- --timeframe 1h

# dry-run: set "strategy" in config or compose command, then
docker compose up -d && docker compose logs -f --tail 50 freqtrade
```

Review backtest metrics (total profit, max drawdown, win rate, trade count — beware
overfitting with <30 trades) with the user before switching the dry-run strategy.
