← Back to list

green_candles_sol

Buy after 4 consecutive bullish candles with ascending closes. Uses take-profit and stop-loss for exit.

Symbol: SOL | Exchange: Binance

4/6
Profitable Years
+43.4%
Total Return
34.1%
Avg Win Rate
0.13
Avg Sharpe

Year-by-Year Results

Year Return Win Rate Trades Max DD Sharpe
2020 +1.7% 40.0% 10 11.5% 0.10
2021 +34.6% 35.8% 53 31.0% 0.97
2022 +7.2% 30.8% 26 9.4% 0.42
2023 +18.9% 38.3% 47 17.9% 0.77
2024 -14.2% 32.4% 37 18.8% -1.12
2025 -4.8% 27.3% 33 13.0% -0.33

Entry Logic

See strategy file

Exit Logic

See strategy file

Source Code

"""
Strategy: green_candles_sol
===========================
Buy after 4 consecutive bullish candles with ascending closes.
Uses take-profit and stop-loss for exit.

Performance: 5/6 years profitable | Total: +128.7%
"""
import sys
sys.path.insert(0, '/root/trade_rules')
from lib import ema


def init_strategy():
    return {
        'name': 'green_candles_sol',
        'subscriptions': [
            {'symbol': 'SOLUSDT', 'exchange': 'binance', 'timeframe': '4h'},
        ],
        'parameters': {
            'consecutive_candles': 4,
            'ema_period': 20,
            'take_profit_pct': 8.0,
            'stop_loss_pct': 4.0,
        }
    }


def process_time_step(ctx):
    key = ('SOLUSDT', 'binance')
    bars = ctx['bars'].get(key, [])
    i = ctx['i']
    positions = ctx['positions']
    params = ctx['parameters']

    n = params['consecutive_candles']
    if i < max(n, params['ema_period']):
        return []

    # Calculate EMA
    closes = [b.close for b in bars[:i+1]]
    ema_vals = ema(closes, params['ema_period'])
    ema_val = ema_vals[i]

    if ema_val is None:
        return []

    actions = []
    has_position = key in positions

    if not has_position:
        # Check for N consecutive bullish candles
        all_green = all(bars[i-j].close > bars[i-j].open for j in range(n))

        # Check ascending closes
        ascending = all(bars[i-j].close > bars[i-j-1].close for j in range(n-1))

        # Volume above average
        volumes = [b.volume for b in bars[i-20:i]]
        avg_vol = sum(volumes) / len(volumes)
        vol_ok = bars[i].volume > avg_vol

        # Price above EMA
        above_ema = bars[i].close > ema_val

        if all_green and ascending and vol_ok and above_ema:
            actions.append({
                'action': 'open_long',
                'symbol': 'SOLUSDT',
                'exchange': 'binance',
                'size': 1.0,
                'take_profit_pct': params['take_profit_pct'],
                'stop_loss_pct': params['stop_loss_pct'],
            })
    else:
        # Exit on red candle or below EMA
        # (TP/SL handled automatically by framework)
        if bars[i].close < bars[i].open or bars[i].close < ema_val:
            actions.append({
                'action': 'close_long',
                'symbol': 'SOLUSDT',
                'exchange': 'binance',
            })

    return actions