چگونه یک استراتژی ساده را به کمک پایتون بکتست‌گیری کنیم؟ آموزش جامع بک تست گرفتن با پایتون

آموزش قدم‌به‌قدم پیاده‌سازی، تست و ارتقای یک استراتژی معاملاتی تکنیکال از مرحله نخست تا اجرای کامل. از نصب ابزارها تا خروجی گزارش‌های حرفه‌ای. آموزش جامع بک تست گرفتن با پایتون .

بک تست گرفتن با پایتون

تصور کنید ایده‌ای برای معامله‌گری دارید: “وقتی میانگین متحرک 20 روزه از میانگین 50 روزه عبور کرد، بخر و وقتی شرایط برعکس شد، بفروش.” ساده به نظر می‌رسد، اما آیا واقعاً در گذشته جواب داده است؟ آیا با درنظرگرفتن کارمزدها هم سودده است؟ پاسخ این سوالات را نه با حدس و گمان، بلکه با بکتست‌گیری علمی (Backtesting) می‌توان یافت. همان طور که در مقالات “بک تستینگ: بک تست چیست ؟ سنگ محک استراتژی‌های معاملاتی شما” و “بک تست گیری در برنامه متاتریدر و ترید برد: یک مقایسه جامع” اشاره کردیم، بکتست گیری یکی از مهمترین ابزار برای هر معامله گر است. اما در بیشتر اوقات، بکتست گرفتن از یک استراتژی ساده در چند بازار یا نماد مختلف به قدری وقت گیر است که باعث میشود انجام آن برای همه امکان پذیر نباشد. در این مقاله، شما را گام‌به‌گام از پیاده سازی یک ایده ساده به کم کد پایتون، به یک استراتژی تست‌شده خواهیم رساند. شما پس از مطالعه این مقاله قادر بود تقریبا هر نوع استراتژی اندیکاتوری را در قالب کُد پایتونی تعریف کنید و در عرض چند دقیقه و کمتر، آن را در هر بازار و نماد دلخواه بکتست گیری کنید. با یادگیری این مهارت، شما از این پس قادر خواهید بود تعداد بسیار زیادی استراتژی مختلف را در مدت کوتاهی بکتست گیری کنید. شما همچنین میتوانید استراتژیهای خودتان را برای نماد یا بازار خاصی بهینه سازی کنید. برای آشنایی با نحوه بهینه سازی یک استراتژی، به مقاله بعدی ما با عنوان “چگونه یک استراتژی معاملاتی را به کمک کد پایتونی بهینه سازی کنیم” رجوع کنید. به عنوان پیش نیاز این مهارت، شما میبایست آشنایی مقدماتی با زبان برنامه نویسی پایتون داشته باشید.

هدف نهایی این مقاله چیست؟

ما در این مسیر چهار مرحله اصلی را طی می‌کنیم:

  • آماده‌سازی میز کار: نصب کتابخانه‌های ضروری پایتون.
  • گردآوری داده‌ها: دانلود داده‌های تاریخی قیمت با کیفیت.
  • پیاده‌سازی اولیه: کدنویسی استراتژی SMA Crossover ساده و اجرای اولین بکتست.
  • ارتقا و بهبود: افزودن حد سود و ضرر (SL/TP) و ترکیب با اندیکاتور RSI برای ساخت استراتژی قدرتمندتر.

در پایان، شما یک فایل پایتون عملیاتی خواهید داشت که می‌تواند استراتژی نهایی شما را روی هر سهمی تست کند و گزارش جامعی ارائه دهد.

گام اول آموزش بک تست گرفتن با پایتون : آماده‌سازی محیط پایتون

قبل از هر چیز، باید ابزارهایمان را آماده کنیم. پایتون به دلیل کتابخانه‌های غنی و جامعه فعال، بهترین انتخاب برای این کار است.

نصب کتابخانه‌های تخصصی بکتست‌گیری

پایتون به تنهایی کافی نیست. نیاز به کتابخانه‌هایی داریم که عملیات سنگین مالی و تحلیلی را برای ما ساده کنند.

لیست کتابخانه‌های ضروری و وظیفه هرکدام

کتابخانه
وظیفه
دستور نصب
backtesting.py
هسته اصلی فرآیند بکتست. ساخت استراتژی، شبیه‌سازی معاملات و تولید گزارش را انجام می‌دهد.
pip install backtesting
pandas & numpy
پردازش و تحلیل داده‌های جدولی و انجام محاسبات عددی سریع.
pip install pandas numpy
pandas-ta
اندیکاتورهای تکنیکال.
pip install pandas pandas-ta
yfinance
دریافت رایگان و آسان داده‌های تاریخی بازار سهام از Yahoo Finance.
pip install yfinance
matplotlib
رسم نمودارهای قیمت، اندیکاتورها و نتایج معاملات.
pip install matplotlib

تأیید صحت نصب

بیایید مطمئن شویم همه چیز درست نصب شده است. کد زیر را در یک فایل پایتون (مثلا test_install.py) ذخیره و اجرا کنید.

				
					import backtesting
import pandas as pd
import numpy as np
import yfinance as yf
import matplotlib

print("✅ تمام کتابخانه‌ها با موفقیت import شدند!")
print("ورژن backtesting.py:", backtesting.__version__)
print("ورژن pandas:", pd.__version__)
                    
				
			

نکته مهم:گاهی اوقات استفاده از کتابخانه yfinance برای ایرانیان با محدودیت مواجه میشود و دانلود داده ها از این روش امکان پذیر نیست. شما میتوانید برای دریافت داده های تاریخی به کانالهای تلگرام و یا ایتای ما مراجعه کنید. نمونه هایی از داده های تاریخی در فرمت فایل های CSV برای استفاده شما در این کانال‌ها قرار داده شده است. بنابراین، درصورتی که فایلها را از کانال دریافت کرده اید میتوانید از این بخش عبور کنید.

گام دوم آموزش بک تست گرفتن با پایتون : گردآوری و آماده‌سازی داده‌های تاریخی

داده تاریخی، سوخت موتور بکتست ماست. بدون داده دقیق و کامل، هر نتیجه‌ای بی‌معنا خواهد بود.

کد دانلود داده با yfinance

کتابخانه yfinance دسترسی ساده‌ای به داده‌های ده‌ها سال گذشته هزاران سهم و ETF فراهم می‌کند.

				
					
# فایل: download_data.py
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt

# 1. تنظیم پارامترهای دانلود
SYMBOL = "BTC-USD"        # جفت ارز بیتکوین به دلار (می‌توانید به جفت ارزهای دیگر و نمادهای بازار سهام امریکا TSLA, GOOGL و... تغییر دهید)
START_DATE = "2020-01-01"
END_DATE = "2025-12-01"
INTERVAL = "1d"         # داده روزانه. گزینه‌های دیگر: '1h', '1wk', '1mo'

print(f"در حال دانلود داده‌های {SYMBOL} از {START_DATE} تا {END_DATE}...")

# 2. دانلود داده
df = yf.download(
    tickers=SYMBOL,
    start=START_DATE,
    end=END_DATE,
    interval=INTERVAL,
    progress=False  # نوار پیشرفت را نشان نده
)

# 3. بررسی و نمایش اطلاعات اولیه داده
print(f"\n✅ دانلود تکمیل شد. {len(df)} ردیف داده دریافت شد.")
print("📅 بازه زمانی:", df.index[0].strftime('%Y-%m-%d'), "تا", df.index[-1].strftime('%Y-%m-%d'))
print("\nستون‌های موجود:")
for col in df.columns:
    print(f"  - {col}")

print("\nنمونه‌ای از داده‌ها (5 ردیف اول):")
print(df.head())

# 4. ذخیره داده در فایل CSV برای استفاده‌های بعدی
csv_filename = f"{SYMBOL}_historical.csv"
df.to_csv(csv_filename)
print(f"\n💾 داده‌ها در فایل '{csv_filename}' ذخیره شدند.")

# 5. رسم نمودار سریع قیمت بسته‌شدن
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['Close'], label='Close Price', color='navy', linewidth=1.5)
plt.title(f'Price history {SYMBOL}', fontsize=14, fontweight='bold')
plt.xlabel('Date')
plt.ylabel('Price (USD)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.savefig(f'{SYMBOL}_price_chart.png', dpi=150)
print(f"📈 نمودار قیمت در فایل '{SYMBOL}_price_chart.png' ذخیره شد.")
plt.show()
                    
				
			

📖 توضیح ساختار داده دریافتی

داده‌های دانلود شده یک DataFrame پانداس با ستون‌های زیر است:

  • Open: اولین قیمت معامله شده در آن روز.
  • High: بالاترین قیمت در طول روز.
  • Low: پایین‌ترین قیمت در طول روز.
  • Close: آخرین قیمت معامله شده در آن روز (مهمترین قیمت برای بسیاری از تحلیل‌ها).
  • Adj Close: قیمت بسته‌شدن تعدیل‌شده. این قیمت، اثر تقسیم سود نقدی، افزایش سرمایه و تجزیه سهام را تصحیح می‌کند و برای تحلیل‌های بلندمدت حیاتی است.
  • Volume: تعداد سهام معامله شده در آن روز.

برای بکتست معمولاً از Adj Close استفاده می‌کنیم تا تحلیل واقع‌بینانه‌تری داشته باشیم.

گام سوم آموزش بک تست گرفتن با پایتون : پیاده‌سازی اولین استراتژی (SMA Crossover)

حالا نوبت زنده کردن ایده معاملاتی ماست. ما از کتابخانه backtesting.py استفاده می‌کنیم که ساختار منظم و کارآمدی برای این کار ارائه می‌دهد.

کتابخانه های جایگزین دیگری نیز مانند backtrader با امکانات مشابه وجود دارند. شما می توانید به داکیومنت این کتابخانه ها مراجعه کنید تا بیشتر با جزییاتشان آشنا شوید.

آشنایی با ساختار یک استراتژی در backtesting.py

هر استراتژی یک کلاس پایتون است که از کلاس پایه Strategy ارث‌بری می‌کند. دو تابع کلیدی دارد:

    • init(): محل تعریف اندیکاتورها و محاسبات یکباره. این تابع فقط یک بار فراخوانی می‌شود.
    • next() مغز استراتژی! این تابع برای هر کندل (مثلاً هر روز) اجرا می‌شود و در آن منطق خرید و فروش را می‌نویسیم. ما در این تابع مشخص میکنیم، در کندل فعلی، با بررسی شرایط گذشته تا کنون، شرایط ورود یا خروج از معامله را بسنجد و در صورت برآورده شدن هر یک از این شروط، وارد معامله مربوطه بشود.

فرض کنید میخواهیم یک استراتژی ساده تعریف کنیم که طی آن: اگر میانگین متحرک با طول 20، میانگین متحرک با طول 50 را به سمت بالا قطع کرد، وارد یک معامله خرید بشویم و در صورتی که عکس این اتفاق افتاد، ایک معامله فروش انجام دهیم. کدهای مربوط به تعریف این استراتژی را در ادامه میبینید:

کد کامل استراتژی SMA Crossover ساده

				
					
# فایل: simple_sma_crossover.py
import pandas as pd
import yfinance as yf
from backtesting import Backtest, Strategy
from backtesting.lib import crossover

class SimpleSMACrossover(Strategy):
    """
    استراتژی قطع شدن میانگین متحرک ساده (SMA Crossover).
    پارامترها:
        n1: دوره میانگین متحرک کوتاه‌مدت (پیش‌فرض 20)
        n2: دوره میانگین متحرک بلندمدت (پیش‌فرض 50)
    """
    # پارامترهای قابل تنظیم استراتژی
    n1 = 20
    n2 = 50

    def init(self):
        # محاسبه اندیکاتورها در اینجا انجام می‌شود.
        # self.I() تابعی است که اندیکاتور را به داده‌های استراتژی اضافه می‌کند.
        close_prices = self.data.Close
        self.sma_short = self.I(lambda x: pd.Series(x).rolling(self.n1).mean(),
                                close_prices, name=f'SMA{self.n1}')
        self.sma_long = self.I(lambda x: pd.Series(x).rolling(self.n2).mean(),
                               close_prices, name=f'SMA{self.n2}')

    def next(self):
        # این تابع برای هر روز (کندل) اجرا می‌شود.
        # self.position نشان‌دهنده موقعیت فعلی ما است. اگر خالی باشد، یعنی موقعیتی نداریم.

        # شرط خرید: اگر موقعیتی نداریم و SMA کوتاه از SMA بلند بالاتر رفته باشد (قطع به سمت بالا)
        if not self.position and crossover(self.sma_short, self.sma_long):
            # دستور خرید. size=1 یعنی تمام سرمایه موجود را وارد معامله کن.
            self.buy()

        # شرط فروش: اگر موقعیت خرید داریم و SMA بلند از SMA کوتاه بالاتر رفته باشد (قطع به سمت پایین)
        elif self.position and crossover(self.sma_long, self.sma_short):
            # بستن موقعیت خرید (فروش)
            self.position.close()

if __name__ == "__main__":
    # --- بخش اجرا و گزارش‌گیری ---
    print("🚀 شروع بکتست استراتژی SMA Crossover ساده")
    print("="*50)

    # 1. دانلود داده (می‌توانید از فایل CSV ذخیره شده هم بخوانید)
    print("در حال دریافت داده‌های BTC...")
    data = yf.download("BTC-USD", start="2020-01-01", end="2025-12-01")

    # اصلاح ستون‌ها: حذف MultiIndex و تبدیل به ستون‌های ساده (در صورتی که از روشی غیر از کتابخانه yfindnce داده ها را دریافت کرده اید، نیازی به انجام این اصلاح نخواهید داشت)
    if isinstance(data.columns, pd.MultiIndex):
        # اگر MultiIndex است، آن را ساده کنیم
        data.columns = [col[0] for col in data.columns]
    
    # اطمینان حاصل کنیم که ستون‌های مورد نیاز وجود دارند
    required_cols = ['Open', 'High', 'Low', 'Close', 'Volume']
    for col in required_cols:
        if col not in data.columns:
            print(f"⚠️  ستون {col} در داده‌ها یافت نشد!")
    
    print(f"\nداده‌های دریافت شده: {len(data)} کندل")
    print(f"ستون‌ها: {list(data.columns)}")
    
    # 2. ایجاد موتور بکتست
    # cash: سرمایه اولیه به دلار
    # commission: کارمزد معاملات (مثلاً 0.1%)
    # exclusive_orders=True: فقط یک موقعیت باز در هر زمان داشته باش.
    bt = Backtest(data, SimpleSMACrossover,
                  cash=1000000,
                  commission=.001,
                  exclusive_orders=True)

    # 3. اجرای استراتژی روی داده‌ها
    print("\nدر حال اجرای شبیه‌سازی معاملات...")
    output = bt.run()

    # 4. نمایش خلاصه نتایج کلیدی
    print("\n" + "="*50)
    print("📊 خلاصه نتایج بکتست")
    print("="*50)
    print(f"📈 بازده نهایی استراتژی: {output['Return [%]']:.2f}%")
    print(f"🏦 سرمایه نهایی: ${output['Equity Final [$]']:.2f}")
    print(f"😨 حداکثر افت سرمایه (Max Drawdown): {output['Max. Drawdown [%]']:.2f}%")
    print(f"🔢 تعداد معاملات: {output['# Trades']}")
    print(f"✅ درصد معاملات سودده (Win Rate): {output['Win Rate [%]']:.2f}%")
    print(f"⚖️  نسبت سود به ضرر (Profit Factor): {output['Profit Factor']:.2f}")

    # 5. رسم نمودار تعاملی کامل (قیمت، اندیکاتورها، معاملات، سرمایه)
    print("\nدر حال تولید نمودارها... (پنجره نمودار باز می‌شود)")
    bt.plot()
             
				
			

خروجی اجرای کد:

با اجرای کد بالا، خروجی زیر در ترمینال نمایش داده میشود:

نمودارهای دارایی اسراتژی و تاریخچه قیمت و معاملات:

نهایتا با اتمام بکتست گیری، نمودارهای زیر در یک صفحه وب به شما نمایش داده میشوند. منحنی اول در این شکل، ارزش دارایی شما را در طول زمان نشان میدهد و مشخص میکند دارایی شما در صورت به کار گیری این استراتژی چگونه در طول زمان تغییر میکرده است. در این منحنی همچنین مقدار بیشینه افت دارایی هم مشخص است. نمودار دوم، میزان سود و زیان معاملات را نشان میدهد: علائم سبز به معنای معامله سودده و علائم قرمز به معنای معامله زیان ده هستند. نمودار آخر، قیمت تاریخی را بصورت نمودار کندلی نمایش میدهد. در این شکل همچنین نقاط ورود و خروج از معاملات و سود و زیان آنها نیز مشخص شده اند. این نمودارها حالت تعاملی دارند و با اسکرول کردن نشانگر موس میتوانید بزرگنمایی یا کوچک نمایی انجام دهید تا جزییات بیشتری را بتوانید در نمودار مشاهده کنید.

نکات طلایی اجرای اولین بکتست

  • خروجی ترمینال را ببینید: تاریخ سیگنال‌های خرید و فروش در کنسول چاپ می‌شوند. این برای دیباگ و درک رفتار استراتژی عالی است.
  • نمودار تعاملی را کشف کنید: بعد از اجرا، نموداری با چندین تب باز می‌شود. در تب اول، خطوط SMA و فلش‌های خرید/فروش را روی نمودار قیمت ببینید. در تب‌های بعدی، نمودار سرمایه و drawdown را بررسی کنید.
  • به Max Drawdown دقت کنید: این عدد نشان می‌دهد اگر در بدترین زمان وارد معامله می‌شدید، چه درصدی از سرمایه شما از بین می‌رفت. عددی بالای ۲۰-۲۵٪ معمولاً خطرناک است.
  • نکته مهم بکتست گیری در بازار ارز دیجیتال:همانطور که در مثال بالا دیدید، میزان اعتبار قرار داده شده برای بکتست گیری عدد بسیار بزرگی بود (10 میلیون دلار!). دلیل این کار این است که کتابخانه مورد استفاده در هر معامله تنها به میزان عدد صحیح از سهام موردنظر خریداری میکند. اما همانطور که میدانید، در بازار ارزهای دیجیتال شما میتوانید مقدار اعشاری از یک ارز را خریداری کنید. برای بکتست گیری اختصاصی در بازار ارزهای دیجیتال میتوانید از کلاس FractionalBacktest استفاده کنید. در مثال بعدی از این کلاس استفاده خواهیم کرد.

نکته مهم:گاهی اوقات استفاده از کتابخانه yfinance برای ایرانیان با محدودیت مواجه میشود و دانلود داده ها از این روش امکان پذیر نیست. شما میتوانید برای دریافت داده های تاریخی به کانالهای تلگرام و یا ایتای ما مراجعه کنید. نمونه هایی از داده های تاریخی در فرمت فایل های CSV برای استفاده شما در این کانال‌ها قرار داده شده است. بنابراین، درصورتی که فایلها را از کانال دریافت کرده اید میتوانید از این بخش عبور کنید. کدهای فراخوانی داده ها از یک فایل در بخش “سوالات متداول و عیب‌یابی” توضیح داده شده اند

یک روش ساده تر برای تست این کتابخانه بدون دانلود داده های تاریخی، استفاده از داده های تست موجود در همین کتابخانه است. برای این کار شما میتوانید از دستور زیر برای استخراج داده های بیتکوین و یا جفت ارز یورو به دلار استفاده کنید:

 
				
					from backtesting.test import EURUSD, BTCUSD
				
			

شما در ادامه میبایست از دستور زیر برای بکتست گیری از این داده ها استفاده کنید (دیگر نیازی به مرتب سازی داده ها ندارید):

				
					
bt = Backtest(EURUSD, SimpleSMACrossover,
    cash=1000,
    commission=.001,
    exclusive_orders=True)
				
			

استفاده از اندیکاتورهای آماده از کتابخانه pandas-ta: در کد استراتژی بالایی، ما اندیکاتورهای میانگین متحرک ساده را بصورت دستی تعریف کردیم. شما به همین نحو میتوانید تقریبا هر اندیکاتور تکنیکال شخصی خودتان را تعریف کنید. با این حال بسیاری از اندیکاتورهای تکنیکل را میتوان از کتابخانه pandas-ta استخراج کرد. برای این کار کافی است پس از لود کردن این کتابخانه بصورت زیر:

 
				
					import pandas-ta as ta
				
			

خطوط زیر در کد تعریف استراتژی را:

				
					
self.sma_short = self.I(lambda x: pd.Series(x).rolling(self.n1).mean(),
                        close_prices, name=f'SMA{self.n1}')
self.sma_long = self.I(lambda x: pd.Series(x).rolling(self.n2).mean(),
                    close_prices, name=f'SMA{self.n2}')
                    
				
			

با این کد جایگزین کنیم:

				
					
self.sma_short = self.I(ta.sma, close_prices, name=f'SMA{self.n1}')
self.sma_long = self.I(ta.sma, close_prices, name=f'SMA{self.n2}')
				
			

گام چهارم آموزش بک تست گرفتن با پایتون : ارتقای استراتژی با حد سود و حد ضرر (SL/TP)

استراتژی ساده ما فقط با سیگنال‌های SMA کار می‌کند. اما یک تریدر حرفه‌ای همیشه مدیریت ریسک می‌کند. بیایید دو قانون کلیدی را اضافه کنیم:

  • حد ضرر (Stop Loss): اگر قیمت به اندازه مشخصی علیه ما حرکت کرد، فوراً با ضرر کم از معامله خارج شو تا از ضرر بزرگتر جلوگیری کنیم.
  • حد سود (Take Profit): وقتی قیمت به اندازه مشخصی به نفع ما حرکت کرد، معامله را با سود ببندیم و طمع نکنیم.

کد استراتژی SMA Crossover با SL و TP

				
					
# فایل: sma_crossover_with_sltp.py
import pandas as pd
from backtesting import Strategy
from backtesting.lib import crossover, FractionalBacktest

class SMACrossWithSLTP(Strategy):
    """
    استراتژی SMA Crossover همراه با مدیریت ریسک (حد سود و حد ضرر).
    """
    n1 = 20
    n2 = 50
    stop_loss_pct = 0.08   # حد ضرر 8% پایین‌تر از قیمت ورود
    take_profit_pct = 3.5 # حد سود 350% بالاتر از قیمت ورود

    def init(self):
        close = self.data.Close
        self.sma_short = self.I(lambda x: pd.Series(x).rolling(self.n1).mean(), close)
        self.sma_long = self.I(lambda x: pd.Series(x).rolling(self.n2).mean(), close)

    def next(self):
        current_price = self.data.Close[-1]

        if not self.position:
            if crossover(self.sma_short, self.sma_long):
                # محاسبه قیمت‌های حد سود و ضرر نسبت به قیمت فعلی
                stop_price = current_price * (1 - self.stop_loss_pct)
                take_profit_price = current_price * (1 + self.take_profit_pct)

                # خرید با تعیین SL و TP
                self.buy(sl=stop_price, tp=take_profit_price)

        # نکته: دیگر شرط فروش با crossover را اینجا نداریم، چون موقعیت یا با SL/TP بسته می‌شود، یا باید یک شرط فروش جداگانه اضافه کنیم.
        # در این نسخه، فقط با SL/TP از معامله خارج می‌شویم.
        # می‌توانیم شرط فروش با crossover را هم حفظ کنیم:
        elif self.position and crossover(self.sma_long, self.sma_short):
            self.position.close()

        # اجرا و مقایسه با استراتژی قبلی
        if __name__ == "__main__":
            import yfinance as yf
            data = yf.download("BTC-USD", "2020-01-01", "2025-12-01")

            # اصلاح ستون‌ها: حذف MultiIndex و تبدیل به ستون‌های ساده
            if isinstance(data.columns, pd.MultiIndex):
                # اگر MultiIndex است، آن را ساده کنیم
                data.columns = [col[0] for col in data.columns]
            
            # اطمینان حاصل کنیم که ستون‌های مورد نیاز وجود دارند
            required_cols = ['Open', 'High', 'Low', 'Close', 'Volume']
            for col in required_cols:
                if col not in data.columns:
                    print(f"⚠️  ستون {col} در داده‌ها یافت نشد!")

    bt_simple = FractionalBacktest(data, SimpleSMACrossover, fractional_unit=1e-06, cash=1000, commission=.001)
    bt_sltp = FractionalBacktest(data, SMACrossWithSLTP, fractional_unit=1e-06, cash=1000, commission=.001)

    res_simple = bt_simple.run()
    res_sltp = bt_sltp.run()

    print("\n" + "="*60)
    print("🆚 Performance comparison: Simple against strategy with SL/TP")
    print("="*60)
    print(f"{'reference':<25} {'simple':<15} {'with SL/TP':<15}")
    print("-"*60)
    print(f"{'Total return %':<25} {res_simple['Return [%]']:<15.2f} {res_sltp['Return [%]']:<15.2f}")
    print(f"{'Max Drawdown %':<25} {res_simple['Max. Drawdown [%]']:<15.2f} {res_sltp['Max. Drawdown [%]']:<15.2f}")
    print(f"{'Win Rate %':<25} {res_simple['Win Rate [%]']:<15.2f} {res_sltp['Win Rate [%]']:<15.2f}")
    print(f"{'Number of trades':<25} {res_simple['# Trades']:<15} {res_sltp['# Trades']:<15}")
    print(f"{'Avg. return/trade':<25} {res_simple['Avg. Trade [%]']:<15.2f} {res_sltp['Avg. Trade [%]']:<15.2f}")
				
			

تحلیل نتایج مقایسه

پس از اجرای کد بالا، مقایسه جالبی خواهید دید که در تصویر زیر نمایش داده شده است. این مقایسه نشان میدهد:

  • حداکثر افت سرمایه (Max Drawdown) کاهش یافته: چون ضررها سریعتر قطع می‌شوند.
  • درصد معاملات سودده (Win Rate) تغییری نیافته: معمولا قرار دادن حد سود و زیان مناسب میبایست به بهبود وضعیت Win Rate منجر شود چرا که معاملات با سود کم و سریع بسته می‌شوند.
  • بازده نهایی 30% افزایش یافته است: برای این مقایسه، با ثابت ماندن تعداد معاملات، بازده نهایی افزایش قابل توجهی داشته. در شرایط کلی ممکن است بازده نهایی پس از قرار دادن حد سود و زیان کاهش پیدا کند. چون برخی معاملات که ممکن بود به سودهای بزرگتر تبدیل شوند، زود بسته شده‌اند. این بهای مدیریت ریسک است.

هدف، پیدا کردن توازن بین سود و ریسک است.

گام پنجم بک تست گرفتن با پایتون : ساخت استراتژی ترکیبی پیشرفته (SMA + RSI)

حالا بیایید استراتژی را هوشمندتر کنیم. اندیکاتور RSI (شاخص قدرت نسبی) می‌تواند به ما بگوید بازار در شرایط “اشباع خرید” (Overbought) یا “اشباع فروش” (Oversold) قرار دارد. می‌توانیم از این اطلاعات برای فیلتر کردن سیگنال‌های SMA استفاده کنیم.

منطق جدید: فقط زمانی بخریم که دو شرط با هم برقرار باشند: ۱) سیگنال خرید SMA ۲) RSI زیر سطح ۳۰ (اشباع فروش) باشد. این یعنی بازار در حال اصلاح است و احتمال بازگشت روند بیشتر است.

کد محاسبه RSI در چارچوب backtesting.py

				
					
# فایل: advanced_strategy.py
import pandas as pd
import numpy as np
from backtesting import Backtest, Strategy
from backtesting.lib import crossover

def calculate_rsi(series: pd.Series, period: int = 14) -> pd.Series:
    """
    تابع محاسبه RSI.
    فرمول RSI: 100 - (100 / (1 + (میانگین سود / میانگین ضرر)))
    """
    delta = series.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    rsi = 100 - (100 / (1 + rs))
    return rsi

class AdvancedSMARSIStrategy(Strategy):
    """
    استراتژی ترکیبی پیشرفته: فیلتر کردن سیگنال‌های SMA با اندیکاتور RSI.
    """
    # پارامترهای SMA
    sma_short = 20
    sma_long = 50
    # پارامترهای RSI
    rsi_period = 14
    rsi_oversold = 30  # زیر این عدد، اشباع فروش محسوب می‌شود
    rsi_overbought = 70 # بالای این عدد، اشباع خرید محسوب می‌شود
    # پارامترهای مدیریت ریسک
    stop_loss = 0.06
    take_profit = 0.12

    def init(self):
        close = self.data.Close
        # محاسبه اندیکاتور SMA
        self.sma_fast = self.I(lambda x: pd.Series(x).rolling(self.sma_short).mean(), close)
        self.sma_slow = self.I(lambda x: pd.Series(x).rolling(self.sma_long).mean(), close)

        # محاسبه اندیکاتور RSI با استفاده از تابع کمکی
        # توجه: باید محاسبات را در قالب یک تابع lambda به self.I() بسپاریم.
        self.rsi = self.I(lambda x: calculate_rsi(pd.Series(x), self.rsi_period), close)

    def next(self):
        current_price = self.data.Close[-1]
        current_rsi = self.rsi[-1] if not np.isnan(self.rsi[-1]) else 50

        # --- شرایط ورود به معامله خرید (Long) ---
        # 1. سیگنال خرید از SMA (قطع به سمت بالا)
        # 2. RSI در ناحیه اشباع فروش باشد (تاییدیه از مومنتوم)
        if not self.position:
            if (crossover(self.sma_fast, self.sma_slow) and current_rsi < self.rsi_oversold):
                sl_price = current_price * (1 - self.stop_loss)
                tp_price = current_price * (1 + self.take_profit)
                self.buy(sl=sl_price, tp=tp_price)

        # --- شرایط خروج از معامله خرید ---
        # 1. سیگنال فروش از SMA (قطع به سمت پایین) - خروج اصلی
        # 2. RSI به ناحیه اشباع خرید برسد (خروج زودتر با سود) - خروج ثانویه
        elif self.position:
            if crossover(self.sma_slow, self.sma_fast):
                self.position.close()
            elif current_rsi > self.rsi_overbought:
                self.position.close()
                    
				
			

پروژه عملی: بکتست نهایی و ارائه گزارش جامع با پایتون

حالا همه قطعات پازل را داریم. بیایید استراتژی نهایی (ترکیبی پیشرفته) را روی داده‌های یک سهم یا ارز اجرا کنیم و یک گزارش حرفه‌ای تولید کنیم.

کد نهایی پروژه (همه چیز در یک فایل)

				
					
# فایل: final_backtest_project.py
import pandas as pd
import numpy as np
import yfinance as yf
from datetime import datetime
from backtesting import Strategy, Backtest # برای بکتست گیری در بازارهایی غیر از ارز دیجیتال
from backtesting.lib import crossover, FractionalBacktest # برای بکتست گیری در بازار ارز دیجیتال

# ---- تعریف توابع کمکی ----
def calculate_rsi(series, period=14):
    delta = series.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))

# ---- استراتژی نهایی ترکیبی ----
class FinalCombinedStrategy(Strategy):
    sma_short = 20
    sma_long = 60
    rsi_period = 14
    rsi_oversold = 35
    rsi_overbought = 75
    stop_loss = 0.05
    take_profit = 0.15

    def init(self):
        close = self.data.Close
        self.sma_fast = self.I(lambda x: pd.Series(x).rolling(self.sma_short).mean(), close)
        self.sma_slow = self.I(lambda x: pd.Series(x).rolling(self.sma_long).mean(), close)
        self.rsi = self.I(lambda x: calculate_rsi(pd.Series(x), self.rsi_period), close)

    def next(self):
        price = self.data.Close[-1]
        rsi_val = self.rsi[-1]

        if not self.position:
            if (crossover(self.sma_fast, self.sma_slow) and rsi_val < self.rsi_oversold):
                self.buy(sl=price*(1-self.stop_loss), tp=price*(1+self.take_profit))
        elif self.position:
            if crossover(self.sma_slow, self.sma_fast) or rsi_val > self.rsi_overbought:
                self.position.close()

# ---- اجرای اصلی پروژه ----
if __name__ == "__main__":
    print("🎯 پروژه عملی: بکتست استراتژی ترکیبی پیشرفته (SMA + RSI + SL/TP)")
    print("="*70)

    # 1. انتخاب نماد و دانلود داده
    TICKER = "BTC-USD"  # بیتکوین
    YEARS = 5
    end_date = datetime.now().strftime("%Y-%m-%d")
    start_date = (datetime.now() - pd.DateOffset(years=YEARS)).strftime("%Y-%m-%d")

    print(f"نماد: {TICKER}")
    print(f"بازه زمانی: {start_date} تا {end_date} ({YEARS} سال)")
    print("در حال دانلود داده...")

    data = yf.download(TICKER, start=start_date, end=end_date, progress=False)

    # 2. اجرای بکتست با استراتژی نهایی
    bt = FractionalBacktest(data, FinalCombinedStrategy, fractional_unit=1e-06و
                  cash=1000,        # سرمایه اولیه 1000 دلار
                  commission=.002,      # کارمزد 0.2%
                  margin=1,            # اهرم 1:1 (بدون اهرم)
                  exclusive_orders=True)

    print("در حال اجرای بکتست (این ممکن است چند ثانیه طول بکشد)...")
    results = bt.run()

    # 3. نمایش گزارش جامع
    print("\n" + "#"*70)
    print("گزارش نهایی بکتست")
    print("#"*70)

    # بخش 1: عملکرد کلی
    print("\n1. 📊 عملکرد کلی")
    print("-"*40)
    print(f"   بازده کل: {results['Return [%]']:+.2f}%")
    print(f"   سرمایه اولیه: ${results['Start Equity']:.2f}")
    print(f"   سرمایه نهایی: ${results['Equity Final [$]']:.2f}")
    annual_return = ((1 + results['Return [%]']/100) ** (1/YEARS) - 1) * 100
    print(f"   بازده سالانه: {annual_return:.2f}%")

    # بخش 2: ریسک
    print("\n2. 🛡️  معیارهای ریسک")
    print("-"*40)
    print(f"   حداکثر افت سرمایه: {results['Max. Drawdown [%]']:.2f}%")
    print(f"   نسبت شارپ: {results.get('Sharpe Ratio', 'N/A'):.2f}")
    print(f"   نسبت سورتینو: {results.get('Sortino Ratio', 'N/A'):.2f}")

    # بخش 3: آمار معاملات
    print("\n3. 🔄 آمار معاملات")
    print("-"*40)
    print(f"   تعداد کل معاملات: {results['# Trades']}")
    if results['# Trades'] > 0:
        print(f"   درصد معاملات سودده: {results['Win Rate [%]']:.1f}%")
        print(f"   میانگین سود به ازای هر معامله: {results['Avg. Trade [%]']:.2f}%")
        print(f"   بیشترین سود یک معامله: {results['Best Trade [%]']:.2f}%")
        print(f"   بیشترین ضرر یک معامله: {results['Worst Trade [%]']:.2f}%")
        print(f"   نسبت سود به ضرر (Profit Factor): {results['Profit Factor']:.2f}")
        print(f"   میانگین مدت نگهداری معامله: {results['Avg. Holding Time']}")

    # بخش 4: نتیجه‌گیری
    print("\n4. 📝 نتیجه‌گیری و وضعیت استراتژی")
    print("-"*40)
    if results['Return [%]'] > 0 and results['Max. Drawdown [%]'] < 20 and results.get('Sharpe Ratio', 0) > 1:
        status = "✅ قوی"
        recommendation = "استراتژی از نظر سودآوری و کنترل ریسک عملکرد قابل قبولی دارد. می‌توان با سرمایه کم آن را در بازار واقعی تست کرد."
    elif results['Return [%]'] > 0:
        status = "⚠️ متوسط"
        recommendation = "استراتژی سودده بوده اما قبل از استفاده واقعی، روی بازه‌های زمانی دیگر تست شود."
    else:
        status = "❌ ضعیف"
        recommendation = "استراتژی در این بازه زمانی سودده نبوده است. نیاز به بازنگری در پارامترها یا منطق پایه دارد."

    print(f"   وضعیت: {status}")
    print(f"   توصیه: {recommendation}")

    # 5. رسم نمودارهای تعاملی
    print("\nدر حال تولید نمودارهای تعاملی...")
    bt.plot()
    print("\n✨ پروژه عملی به پایان رسید!")
                    
				
			

با اجرای کد بالا شما میبایست خروجی زیر را در ترمینال (یا محیط Jupyter notebook، Google Colab و … مشاهده کنید:)

چه چیزی یاد گرفتیم؟

در این پروژه عملی، شما موفق شدید:

  1. یک محیط برنامه‌نویسی حرفه‌ای برای تحلیل بازار راه‌اندازی کنید.
  2. داده‌های واقعی بازار را به صورت خودکار دریافت و پردازش کنید.
  3. یک استراتژی معاملاتی ساده اما کامل بر اساس میانگین‌های متحرک پیاده‌سازی کنید.
  4. مدیریت ریسک را با افزودن حد سود و حد ضرر به استراتژی وارد کنید.
  5. با ترکیب چند اندیکاتور (SMA و RSI)، استراتژی را به سطح بالاتری ببرید تا سیگنال‌های بهتری تولید کند.
  6. کل این فرآیند را روی داده‌های یک سهم جدید اجرا کرده و یک گزارش تحلیلی جامع تولید کنید.

این چارچوب، پایه‌ای قوی برای تست هر ایده معاملاتی دیگر است. کافی است کلاس استراتژی را تغییر دهید.

سوالات متداول و عیب‌یابی

❓ خطای "yfinance not found" می‌دهد.

مطمئن شوید کتابخانه yfinance را با دستور pip install yfinance نصب کرده‌اید. اگر در محیط مجازی کار می‌کنید، فعال بودن آن را بررسی کنید.

❓ نمودارها نمایش داده نمی‌شوند.

اگر از سرور یا محیطی بدون رابط گرافیکی استفاده می‌کنید (مثل برخی IDEهای آنلاین)، دستور bt.plot() ممکن است کار نکند. به جای آن از bt.plot(resample=False, open_browser=False) استفاده کنید و نمودار را در فایل ذخیره کنید.

❓ داده‌های دانلود شده قدیمی هستند.

تاریخ پایان (end_date) را چک کنید. برای دریافت داده تا امروز، می‌توانید از end_date = datetime.now().strftime("%Y-%m-%d") استفاده کنید.

❓ استراتژی من هیچ معامله‌ای انجام نمی‌دهد.

پارامترهای استراتژی (مثل دوره‌های SMA) ممکن است برای بازار انتخابی شما مناسب نباشد. ابتدا سیگنال‌های اندیکاتورها را روی نمودار قیمت به صورت دستی بررسی کنید. همچنین می‌توانید در تابع next() با دستور print، مقادیر اندیکاتورها را چاپ کنید تا ببینید شرایط منطقی شما کی True می‌شود.

❓ برای دانلود داده ها به کمک کتابخانه yfinance مشکل دارم و این کتابخانه نصب نمیشود.

در صورتی که نتوانستید با کتابخانه yfinance کار کنید میتوانید با جایگزینهای دیگری مانند کتابخانه ccxt برای ارزهای دیجیتال کار کنید. برای دانلود داده های قیمت مربوط به یک سال اخیر بیتکوین به کمک این کتابخانه دستورات زیر را اجرا کنید:

ابتدا نصب کتابخانه با اجرای دستور: pip install ccxt

سپس دانلود داده ها:

				
					
import ccxt

# ---- مشخص کردن صرافی و دانلود داده ها ----
exchange = ccxt.kucoin()
timeframe = '4h'
start_date = datetime(year=2025, month=1, day=1)
since = int(start_date.timestamp()*1000)  # تبدیل میکرو به میلی ثانیه
ohlcv = exchange.fetch_ohlcv(symbol='BTC/USDT', timeframe=timeframe, since=since)
data = pd.DataFrame(data = ohlcv, columns = ['timestamp', 'open', 'high', 'low', 'close', 'volume'])
data.rename(columns={
    'open': 'Open',
    'high': 'High',
    'low': 'Low',
    'close': 'Close',
    'volume': 'Volume'
}, inplace=True)
				
			

پلتفرم تریدبرد با درک چالش‌های پیش روی معامله گران علاقه مند به بکتست گیری اتوماتیک، و با هدف ساده و قابل دسترس کردن فرآیند بک تست و استراتژی سازی طراحی شده است. این پلتفرم یک راهکار تحت وب ارائه می‌دهد که بسیاری از موانع موجود در پلتفرم های سنتی را از بین می‌برد. اگر شما یک معامله گر نا آشنا با کُدنویسی حرفه ای و معاملات الگوریتمی هستید، تریدبرد این امکان را برایتان فراهم کرده تا استراتژی اندیکاتوری خود را به کمک یک رابط کاربری ساده و زیبا طراحی کنید و سپس در بازارهای مختلف، ارزهای مختلف و تایم فریمهای مختلف از آن بکتست گیری کنید. این فرایند کوتاهتر از یک دقیقه خواهد بود و شما را از سختی کار با پلتفرم های دستی بکتست گیری رها خواهد کرد.

اما اگر شما با کُدنویسی پایتونی آشنا هستید، یا استراتژی شما پیچیده تر از آن است که با اندیکاتورهای متنوع تریدبرد تعریف شود، میتوانید استراتژی خود را بصورت کُدی در این پلتفرم تعریف کنید و سپس به سادگی در بازارها و ارزهای مختلف از آن بکتست گیری کنید. شما میتوانید با تغییر پارامترهای استراتژی خود و بکتست گیری مداوم، استراتژی پیچیده خود را در مدت زمان کوتاهی بهینه سازی کنید. کاری که شاید در بکتست گیری دستی هرگز امکان پذیر نباشد. همچنین شما میتوانید استراتژی های الگوریتمی خود را در تریدبرد ثبت کرده و برایشان روباتهای سیگنال ساز بسازید تا در صورت برآورده شدن شرایط ورود و خروج از معاملات، این روباتها سیگنالهای خرید و فروش را به شما در شبکه های اجتماعی اطلاع رسانی کنند.

پیشنهاد می کنیم برای آشنایی بیشتر با ربات های سیگنال دهی مقاله ی ربات‌های سیگنال‌دهی چیستند و چگونه کار می‌کنند؟ از اسطوره تا واقعیت را مطالعه کنید.

مراحل گام به گام اجرای یک بک تست در تریدبرد

گام اول: ثبت نام و ورود به پلتفرم

کافیست مرورگر وب خود را باز کرده و به آدرس پلتفرم تریدبرد مراجعه کنید. شما برای استفاده از امکانات پلتفرم نیازی به حساب کارگزار ندارید و تنها یک ثبت نام ساده در خود پلتفرم کافیست.

صفحه اصلی و لاگین پلتفرم تریدبرد

صفحه اصلی و لاگین پلتفرم تریدبرد

گام دوم: تعریف استراتژی (Strategy Builder)

تریدبرد دو راه قدرتمند و انعطاف پذیر برای تعریف استراتژی در اختیار شما می‌گذارد:

📊

تعریف استراتژی بر اساس اندیکاتورها (بدون کدنویسی)

  • از منوی جانبی به بخش استراتژی ها مراجعه کنید.
  • روی دکمه ساخت استراتژی اندیکاتوری یا ساخت استراتژی کُدی کلیک کنید.
  • شما می‌توانید از کتابخانه گسترده ای از اندیکاتورهای تکنیکال (مانند Moving Average, RSI, MACD و …) استفاده کنید.
  • پارامترهای هر اندیکاتور (مثل دوره زمانی) به طور کامل قابل تنظیم است.
  • شما می‌توانید با انتخاب از بین شرایط مختلف (قطع رو به بالا/پایین، بزرگتر/کوچکتر/مساوی) شرایط پیچیده ای برای ورود و خروج از معاملات ایجاد کنید. مثلاً: “هرگاه EMA دوره ۲۰ از بالای EMA دوره ۵۰ عبور کند و در همان زمان RSI زیر سطح ۷۰ باشد، یک پوزیشن خرید باز کن”.
🐍

تعریف استراتژی با کدنویسی در پایتون

  • برای کاربران حرفه ای تر، تریدبرد این امکان را فراهم کرده که استراتژی خود را به زبان پایتون کدنویسی کنند.
  • شما به کتابخانه های محبوب و شناخته شده‌ای مانند pandas-ta برای محاسبه اندیکاتورهای تکنیکال دسترسی دارید.
  • همچنین، این قابلیت منحصر به فرد وجود دارد که بتوانید اندیکاتورهای اختصاصی خود را تعریف و در استراتژی به کار ببرید. این امکان، افق بینهایتی را برای آزمون ایده های خلاقانه در اختیار شما قرار می‌دهد.
صفحه Strategy Builder در تریدبرد (هم حالت اندیکاتوری و هم محیط کدنویسی پایتون)

صفحه Strategy Builder در تریدبرد (هم حالت اندیکاتوری و هم محیط کدنویسی پایتون)

گام سوم: اجرای بک تست

پس از ذخیره استراتژی، از منوی جانبی به بخش بک تست ها مراجعه کنید و روی دکمه “افزودن بکتست” (برای بک تست گیری از استراتژی‌های اندیکاتوری) و یا “افزودن بکتست از استراتژی کدی” (برای بکتست گیری از استراتژی‌های کدی) کلیک کنید.

1

انتخاب استراتژی

استراتژی ای که قبلاً تعریف کرده اید (چه اندیکاتوری و چه کدپایتون) را از لیست انتخاب کنید.

2

انتخاب بازار و نماد

بازار مورد نظر خود را (فارکس، ارز دیجیتال، بورس ایران، طلا و نقره) و سپس نماد خاص را انتخاب نمایید. داده های ارزهای دیجیتال مستقیماً از صرافی معتبر بایننس تامین می‌شود که از صحت و کیفیت آن اطمینان دارید.

3

انتخاب تایم فریم

تایم فریم مورد نظر برای تست را از ۱ دقیقه تا ۱ روز انتخاب کنید.

4

تعیین بازه تاریخی

تاریخ شروع و پایان دقیق دوره بک تست را با استفاده از تقویم مشخص کنید.

5

اجرای تست

با کلیک بر روی دکمه ساخت بکتست، یک کارت بکتست با تنظیمات مشخص شده توسط شما در صفحه ساخته می‌شود که در وضعیت “درانتظار اجرا” قرار دارد. با کلیک بر روی دکمه “اجرای بکتست” مربوط به این کارت، بک تست اجرا می‌شود و پس از خاتمه یافتن فرایند بکتست گیری (در کمتر از یک دقیقه)، وضعیت کارت بروز شده و به حالت “انجام شده” تغییر می‌کند.

پنل بکتست گیری در تریدبرد

پنل بکتست گیری در تریدبرد

تحلیل و گزارش‌های پیشرفته در تریدبرد

پس از اتمام تست، تریدبرد یک پکیج کامل و جامع از گزارش‌ها و نمودارها را در اختیار شما قرار می‌دهد که نه تنها از نظر کمی، بلکه از نظر کیفی نیز بسیار غنی هستند.

الف) معیارهای عملکرد جامع

تریدبرد طیف وسیعی از معیارهای عملکردی که در کد شما ذکر شده بود را محاسبه و نمایش می‌دهد. این معیارها شامل موارد کلیدی زیر هستند:

شارپ
Sharpe Ratio
سورتینو
Sortino Ratio
افت سرمایه
Drawdown
نرخ برد
Win Rate
  • ضریب شارپ (Sharpe Ratio) و ضریب سورتینو (Sortino Ratio): برای تحلیل بازدهی با ریسک تنظیم شده.
  • حداکثر و میانگین افت سرمایه (Max & Avg Drawdown): برای درک عمق و میانگین ضررهای موقت.
  • مدت زمان افت سرمایه (Max & Avg DD Duration): برای فهمیدن چه مدت زمانی طول می‌کشد تا استراتژی از یک ضرر بازیابی شود.
  • نرخ برد (Win Rate) و تعداد معاملات (Num Trades): برای ارزیابی کارایی و فعالیت استراتژی.
  • سود کل (Total Return) و سود سالیانه (Annual Return): برای اندازه گیری بازدهی.
  • سود Buy & Hold: برای مقایسه عملکرد استراتژی شما با ساده ترین استراتژی ممکن (خرید و نگهداری).
  • فاکتور سود (Profit Factor) و امید ریاضی (Expectancy): برای قضاوت در مورد سودآوری ذاتی سیستم.
  • نوسانات سالیانه (Annual Volatility): برای اندازه گیری ریسک.
  • بهترین و بدترین معامله (Best & Worst Trade): برای تحلیل دامنه نتایج ممکن، و بسیاری فاکتور عملکردی دیگر که در تصویر مشاهده می‌کنید.
صفحه نتایج بک تست با لیست کامل معیارها در تریدبرد

صفحه نتایج بک تست با لیست کامل معیارها در تریدبرد

ب) نمودارهای پیشرفته

📈
نمودار قیمت با نقطه گذاری ورود و خروج

نمودار اصلی قیمت به همراه مارکرهای واضحی که نشان دهنده نقطه ورود (با فلش سبز) و خروج (با فلش قرمز) هر معامله هستند. این نمودار درک بصری عالی از رفتار استراتژی به شما می‌دهد.

📊
نمودار مقایسه ای Equity Curve

دو منحنی روی یک نمودار:

  • منحنی سرمایه (Equity Curve): نشان می‌دهد سرمایه حساب شما در طول زمان چگونه تغییر کرده است.
  • منحنی Buy & Hold: نشان می‌دهد اگر شما همان دارایی را فقط می‌خریدید و تا انتها نگه می‌داشتید، سرمایه شما چقدر می‌شد.
این دو نمودار بر محور زمان همگام (Sync) هستند و مقایسه آنها بسیار ساده است.

 

📉
نمودار میله ای سود و زیان معاملات (PnL Bar Chart)

یک نمودار میله ای که سود یا زیان هر معامله را به ترتیب زمانی نشان می‌دهد. این نمودار به شما کمک می‌کند توالی معاملات برنده و بازنده را به راحتی شناسایی کنید.

مجموعه نمودارها در تریدبرد

مجموعه نمودارها (قیمت، دارایی، دارایی خرید و نگهداری، مارکرهای ورود و خروج از معاملات ) در تریدبرد

ج) قابلیت ذخیره سازی و بازیابی نتایج

یکی از ویژگی‌های منحصر به فرد تریدبرد، امکان ذخیره نتایج هر بک تست است. شما می‌توانید نتایج تست‌های مختلف خود را ذخیره کنید و در هر زمان دیگری به آنها مراجعه کرده، مجدداً تحلیل کنید یا با نتایج جدید مقایسه نمایید. این ویژگی برای ردیابی پیشرفت و توسعه استراتژی شما در طول زمان حیاتی است.

د) خروجی CSV

برای تحلیل‌های دقیق تر، شما می‌توانید گزارش کامل تمام معاملات را در قالب یک فایل CSV دانلود کرده و در نرم افزارهایی مانند Excel یا Google Sheets باز کرده و تحلیل‌های آماری پیشرفته تری روی آنها انجام دهید. همچنین می‌توانید نتایج بکتست های مربوط به بازه های زمانی متوالی مخصوصا مربوط با تایم فریم های کوچک (که محدودیت بازه زمانی انتخابی برای آنها صدق می‌کند) را در یک فایل CSV جمع آوری کرده و تحلیل جامع تری از استراتژی خود در این تایم فریم ها داشته باشید.

نمودار ستونی بازدهی معاملات در تریدبرد

نمودار ستونی بازدهی معاملات (قابل ذخیره سازی به فرمتهای گوناگون از جمله png و csv)

جمع‌بندی و گام بعدی

تبریک! شما اکنون توانایی بکتست‌گیری یک استراتژی معاملاتی از صفر تا صد را دارید. شما نه تنها یک استراتژی ساده را تست کردید، بلکه آن را با افزودن قوانین مدیریت ریسک و فیلترهای دیگر، به یک سیستم معاملاتی قوی‌تر ارتقا دادید.

  • گام بعدی چیست؟ در مقاله بعدی، به سراغ مرحله حرفه‌تری می‌رویم: «بهینه‌سازی خودکار استراتژی». خواهیم آموخت که چگونه با استفاده از کد پایتون، بهترین پارامترها برای استراتژی خود را به صورت خودکار و علمی پیدا کنیم، بدون آنکه در دام «اورفیتینگ» (تنظیم بیش از حد روی داده‌های گذشته) بیفتیم. با استفاده از Heatmap و تکنیک‌های اعتبارسنجی، یاد می‌گیریم چگونه استراتژی‌ای بسازیم که نه تنها در گذشته، بلکه با احتمال بیشتری در آینده نیز عملکرد خوبی داشته باشد.

⚠️ هشدار مهم پایانی

نتایج بکتست‌گیری ضمانتی برای سودآوری آینده نیستند. بازارها پویا هستند و شرایط تغییر می‌کند. همیشه:

  • با سرمایه‌ای که توان از دست دادنش را دارید شروع کنید.
  • استراتژی خود را به طور مداوم در بازار واقعی با حجم بسیار کم (Forward Test) بررسی کنید.
  • به مدیریت ریسک و Diversification (تنوع بخشی) پایبند باشید.

هدف بکتست‌گیری، افزایش احتمال موفقیت و کاهش ریسک‌های غیرضروری است، نه تضمین سود قطعی. 

برای آشنایی بیشتر با مفهوم و کارایی بک تستینگ مقاله ی بک تستینگ: بک تست چیست ؟ سنگ محک استراتژی‌های معاملاتی شما را مطالعه بکنید .

امیدواریم این آموزش گام‌به‌گام برای شما مفید بوده باشد. برای هر سوال یا ابهامی، می‌توانید کدهای کامل ارائه شده را اجرا و پارامترها را تغییر دهید. موفق و پرسود باشید!

کلمات کلیدی مرتبط

آموزش بکتست پایتون
backtesting.py
استراتژی SMA Crossover
حد سود و حد ضرر
پیاده‌سازی RSI پایتون
دانلود داده یاهو فایننس
yfinance
شبیه‌سازی معاملات
پروژه عملی الگوریتم تریدینگ
تحلیل ریسک بازده
پایتون برای معاملات