millionchart
English

استراتژی‌ها و سرآیند

سرآیند کامل استراتژی: حجم، کارمزد، اسپرد، لغزش قیمت، سواپ، تأخیر و مارجین، نحوهٔ پر شدن سفارش‌ها، ارقام حساب که می‌توانید بخوانید و نتیجه‌ها.

استراتژی اسکریپتی است که سرآیندش یک خط strategy است و سفارش‌هایش را با تابع‌های orders.* می‌گذارد. نمودار سفارش‌ها را روی کندل‌هایی که دارد بازپخش می‌کند و معامله‌ها را نشان می‌دهد. هیچ سفارشی به بروکر نمی‌فرستد. درس 14: اولین استراتژی شما مقدمهٔ کوتاه است، درس 15: آزمایش در Strategy Lab آزمایش‌های طولانی‌تر Strategy Lab را نشان می‌دهد و این صفحه مرجع است.

واژه‌های این صفحه#

لات (lot) اندازهٔ استاندارد معامله در یک ابزار است. تیک (tick) کوچک‌ترین گام قیمت است. اسپرد فاصلهٔ قیمت خرید و قیمت فروش است، و لغزش قیمت (slippage) حرکت قیمت بین ثبت سفارش و پر شدن آن. سواپ هزینه (یا اعتبار) نگه داشتن پوزیشن در طول شب است. ضریب سود (profit factor) پولِ بُرده تقسیم بر پولِ باخته است، و افت سرمایه (drawdown) پایین آمدن حساب از اوج آن.

سرآیند#

Cuprel
strategy "Crossover with costs"
    edition = 1
    display = price

setup:
    capital = 10000
    size = sizing.lots(0.1)
    fees = fee.per_lot(3.5)

execution:
    spread = 25 ticks
    slippage = 2 ticks
    swap_long = -3.2
    swap_short = 1.1
    latency = 300 ms
    fills = worst

margin:
    long = 5
    short = 5

let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
if tech.crosses_above(fast, slow)
    orders.enter("Long", side.long)
if tech.crosses_below(fast, slow)
    orders.close("Long")
plot(fast, name = "Fast")
plot(slow, name = "Slow")

سرآیند استراتژی زیر خط‌های سرآیند تا سه بلوک دارد: setup: (پول، حجم و کارمزدها)، execution: (سفارش‌ها چطور پر شوند) و margin: (چه مقدار از پوزیشن نگه داشته شود). هر بلوک از لبهٔ چپ شروع می‌شود و تنظیم‌هایش زیر آن تورفته نوشته می‌شوند. هر تنظیم زنده است: می‌تواند یک ورودی را بخواند، و عوض کردن ورودی اجرای بعدی را عوض می‌کند. مثلاً size = sizing.lots(lots) همراه با input lots: float = 0.1 همان حجمی را معامله می‌کند که آن ورودی می‌گوید.

setup:#

تنظیممعنا
capitalپولی که حساب روی نمودار با آن شروع می‌شود
sizeهر سفارش چقدر معامله کند: یکی از چهار شکل زیر. بدون size، هر سفارش 1 واحد معامله می‌کند
feesهزینهٔ هر معامله: یکی از چهار شکل زیر، که در هر پر شدن (ورود و خروج) کسر می‌شود
pyramidingچند ورود می‌تواند همزمان در یک جهت باز باشد (1 وقتی چیزی نگویید؛ با 3، سه فراخوانی پشت‌سرهم orders.enter روی هم جمع می‌شوند)
حجمحجم معامله
size = sizing.lots(0.1)0.1 لات از ابزار
size = sizing.fixed(2)2 واحد از ابزار
size = sizing.equity(10)تعداد واحدی که ارزشش 10 درصد حساب است
size = sizing.cash(5000)تعداد واحدی که ارزشش 5,000 پول حساب است
کارمزددر هر پر شدن کسر می‌شود
fees = fee.per_lot(3.5)3.5 از پول حساب به ازای هر لات
fees = fee.per_unit(0.5)0.5 به ازای هر واحد
fees = fee.per_order(5)5 برای هر پر شدن، هر حجمی که داشته باشد
fees = fee.rate(0.05)0.05 درصد از ارزش معامله‌شده

هر سفارش می‌تواند qty خودش را هم داشته باشد، بر حسب واحد: orders.enter("Long", side.long, qty = 3) هر چه size بگوید، 3 واحد معامله می‌کند. qty برابر na خطاست (E-QTY-NA) و هرگز بی‌صدا به یک مقدار پیش‌فرض تبدیل نمی‌شود.

execution:#

تنظیممعنا
spreadبه تیکِ نماد (25 ticks). خریدها روی ask پر می‌شوند و فروش‌ها روی bid، پس اسپرد هر معامله را با زیان شروع می‌کند. auto اسپرد زندهٔ ابزار را می‌خواهد؛ اجرای روی نمودار برای آن 0 می‌خواند، چون عکس لحظه‌ای یک قیمت زنده قابل تکرار نیست
slippageبه تیک: سفارش‌های بازار و استاپ به همین اندازه تیک بدتر از قیمتشان پر می‌شوند
slippage_randomtrue: هر پر شدن به اندازهٔ بخشی تصادفی از slippage می‌لغزد، نه همهٔ آن
swapoff: هیچ هزینهٔ شبانه‌ای نیست
swap_long, swap_shortهزینهٔ شبانهٔ پوزیشن خرید یا فروش برای یک لات و یک شب (عدد منفی هزینه است و عدد مثبت اعتبار)، با واحد swap_mode
swap_modepercent، money یا points
latencyفاصلهٔ زمانی بین سفارش و پر شدنش (300 ms، یا مدتی مثل 1s). قیمت در این فاصله حرکت می‌کند، پس تأخیر طولانی قیمت پر شدن را عوض می‌کند؛ تأخیری کوتاه‌تر از یک کندل اغلب چیزی را روی نمودار عوض نمی‌کند
fillsوقتی یک کندل هم به حد ضرر می‌رسد و هم به هدف، کدام اول پر شود: path (پیش‌فرض)، worst، best، stop_first، target_first (پایین‌تر را ببینید)
costsnone کمیسیون و سواپ خود ابزار را کنار می‌گذارد، و سواپی را هم که خودتان اعلام کرده‌اید؛ fees بلوک setup: در هر حال کسر می‌شود
lotsround هر حجم را به گام لات ابزار گرد می‌کند؛ سفارشی که به کمتر از کوچک‌ترین لات گرد شود رد می‌شود (اجرا می‌گوید چند سفارش)
fill_on_closetrue سفارش را در قیمت بسته‌شدن همان کندلی که ثبتش کرده پر می‌کند، نه در قیمت بازشدن کندل بعد

کلمه‌های ticks و ms بعد از یک عدد فقط در یک تنظیم execution: پذیرفته می‌شوند. جای دیگر رد می‌شوند:

Cuprel · خطا E3270
indicator "A unit outside the header"
    edition = 1

plot(25 ticks)

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

Cuprel · خطا E3130
strategy "A setting that does not exist"
    edition = 1
    display = price

execution:
    speed = 25

if bar.index == 10
    orders.enter("Long", side.long)

margin:#

long = 5 و short = 5 درصدی از ارزش پوزیشن است که به‌عنوان مارجین نگه داشته می‌شود. سفارشی که بیش از مارجین آزاد لازم داشته باشد رد می‌شود و اجرا می‌گوید چند سفارش به این دلیل رد شد. 0 بررسی مارجین را خاموش می‌کند. بدون بلوک margin: هم یک مارجین پیش‌فرض اعمال می‌شود، پس پوزیشنی خیلی بزرگ‌تر از حساب باز هم رد می‌شود.

سفارش‌ها#

فراخوانیکار
orders.enter(key, side, ...)پوزیشن باز می‌کند یا به آن اضافه می‌کند؛ با limit یا stop منتظر آن قیمت می‌ماند، و با expires = n بعد از n کندل لغو می‌شود
orders.exit(key, entry, ...)خروج معامله‌ای که ورودی به نام entry باز کرده: قیمت stop و limit، یا loss_ticks و profit_ticks از قیمت ورود؛ حد ضرر متحرک هم دارد (trail_ticks، trail_offset_ticks)
orders.close(key)معامله‌هایی را می‌بندد که آن ورود باز کرده
orders.close_all()همه‌چیز را می‌بندد
orders.cancel(key)، orders.cancel_all()سفارش‌هایی را که هنوز در انتظارند پس می‌گیرند

سفارشی که وقت بسته شدن یک کندل می‌گذارید از قیمت بعدی فعال است: سفارش بازار در قیمت بازشدن کندل بعد پر می‌شود (مگر با fill_on_close = true). orders.exit به معامله‌ای تعلق دارد که برایش گذاشته شده و با آن تمام می‌شود. نمی‌تواند به‌طور اتفاقی معاملهٔ بعدی را بگیرد. مرجع orders همهٔ پارامترها را فهرست می‌کند.

کلیدها سخت‌گیرانه‌اند. اگر ورودی را با کلیدی ببندید که فقط در بزرگی و کوچکی حرف‌ها، فاصله، _ یا - با یکی از کلیدهای به‌کاررفته فرق دارد، به احتمال زیاد غلط تایپ کرده‌اید، و موتور با یک پیشنهاد متوقف می‌شود:

Cuprel · خطا E-ORDER-ID
strategy "A mistyped id"
    edition = 1
    display = price

if bar.index == 10
    orders.enter("Long", side.long)
if bar.index == 20
    orders.close("long")
Cuprel · خطا E-QTY-NA
strategy "A size that is na"
    edition = 1
    display = price

if close > open
    orders.enter("Long", side.long, qty = na)

خواندن حساب#

این‌ها سری‌هایی مثل بقیه‌اند و در شرط‌ها به کار می‌روند:

ناممعنا
position.sizeحجم باز؛ برای خرید مثبت و برای فروش منفی
position.avg_priceمیانگین قیمت پوزیشن باز
stats.equityارزش حساب، همراه با سود باز
stats.net_profitسود معامله‌های بسته‌شده
trades.closed_countتعداد معامله‌های بسته‌شده
stats.equity_lowپایین‌ترین اکوییتی داخل کندلی که همین حالا بسته شده
stats.day_low_equityپایین‌ترین اکوییتی داخل روز معاملاتی تا اینجا
stats.day_start_equityاکوییتی‌ای که روز معاملاتی با آن شروع شد

قیمت بسته‌شدن یک کندل پنهان می‌کند که حساب داخل آن چقدر پایین رفته. stats.equity_low و stats.day_low_equity آن را نشان می‌دهند، و این همان چیزی است که سقف ضرر روزانه لازم دارد:

Cuprel
strategy "Daily loss guard"
    edition = 1
    display = price

setup:
    capital = 10000
    size = sizing.lots(0.1)

input max_loss_pct: float = 1.0, name = "Stop trading today after losing %", min = 0.1, step = 0.1
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
let day_loss = (stats.day_start_equity - stats.day_low_equity) / stats.day_start_equity * 100
let blocked = day_loss >= max_loss_pct
if tech.crosses_above(fast, slow) and not blocked
    orders.enter("Long", side.long)
if tech.crosses_below(fast, slow)
    orders.close("Long")
plot(day_loss, name = "Loss today, %")

سفارش‌های در انتظار هم مثل سفارش‌های بازار کار می‌کنند؛ ورود استاپ منتظر یک قیمت می‌ماند و بعد از expires کندل منصرف می‌شود:

Cuprel
strategy "Pending breakout entry"
    edition = 1
    display = price

let high20 = tech.highest(high, 20)
if bar.index % 50 == 0
    orders.enter("Breakout", side.long, stop = high20, expires = 5)
plot(high20, name = "20-bar high")

تابع‌های risk.* وقتی به یک سقف برسید ورودهای تازه را متوقف می‌کنند، مثل دو ورود در روز یا سه روز زیان‌ده پشت‌سرهم؛ مرجع risk آن‌ها را فهرست می‌کند و نمونه استراتژی‌ها از دوتای آن‌ها استفاده می‌کنند.

وقتی یک کندل به دو قیمت می‌رسد#

نمودار از هر کندل فقط open، high، low و close را دارد. وقتی کندلی هم به حد ضرر شما می‌رسد و هم به هدف، کدام اول بوده است؟ تنظیم fills تصمیم می‌گیرد:

  • path (پیش‌فرض) شکل کندل را دنبال می‌کند: فرض می‌شود کندل صعودی اول پایین می‌رود و کندل نزولی اول بالا.
  • worst ترتیبی را می‌گیرد که حساب را پایین‌تر می‌گذارد، و best ترتیبی را که حساب را بالاتر می‌گذارد.
  • stop_first و target_first همیشه همان ترتیب را می‌گیرند.

worst انتخاب محتاطانه است: ترتیب نامطلوب‌تر را فرض می‌کند، پس نتیجه‌ای که با آن به دست می‌آید با شانس زیباتر نمی‌شود. Strategy Lab می‌تواند دقیقه‌های درون هر کندل را هم بازپخش کند، که بیشتر این موارد را به جای حدس زدن روشن می‌کند.

نتیجه‌ها#

روی نمودار، استراتژی در هر ورود یک مثلث نشان می‌دهد (با کلید همان ورود)، در هر خروج یک ضربدر (سبز برای سود، قرمز برای ضرر)، یک خط‌چین از ورود تا خروج، و یک جدول با سود خالص و درصد آن، معامله‌های بسته‌شده، سهم معامله‌هایی که پول ساخته‌اند، ضریب سود، بزرگ‌ترین افت سرمایه و معامله‌های باز. وقتی کمیسیون یا سواپ پرداخت شده باشد ردیفی به نام Costs پیدا می‌شود، و وقتی ترتیب دو رویداد داخل یک کندل حدسی بوده و حساب را عوض کرده، ردیفی به نام Guessed exits. دو ورودی خود استراتژی، Show the trades on the chart و *Show the results table*، آن‌ها را خاموش می‌کنند. علامت‌ها و خط‌ها فقط برای آخرین 500 معامله نگه داشته می‌شوند، پس در یک تاریخچهٔ بلند ممکن است جدول معامله‌های بیشتری از آنچه نمودار رسم می‌کند بشمارد.

رد شدن سفارش توسط مدل بروکر (سفارشی زیر کوچک‌ترین لات، سفارشی بیش از مارجین آزاد) یک اخطار برای آن اجراست که یک بار، همراه با تعدادش، گفته می‌شود.

مدل‌سازی نشده و هنوز در دسترس نیست#

  • گزینه‌ای از سرآیند که این بازپخش مدل نمی‌کند با E3130 رد می‌شود، و پیام تنظیم‌هایی را که سرآیند می‌گیرد فهرست می‌کند.
  • funding و hedge در سرآیند، و دستور سفارش bracket، هنوز در دسترس نیستند؛ bracket به‌عنوان متعلق به یک نسخهٔ زبان (edition) بعدی رد می‌شود (E9002).
  • استراتژی نمی‌تواند آینده را بخواند (future = true همان E3132 است)، و فقط یک نماد را معامله می‌کند: نمادِ نمودار.
  • هیچ‌کدام از این‌ها سفارش واقعی نیست. نمودار و Strategy Lab معامله‌ها را روی کندل‌های گذشته شبیه‌سازی می‌کنند؛ MillionChart هیچ سفارش واقعی‌ای اجرا نمی‌کند.

نگاه کنید به: درس 14: اولین استراتژی شما، درس 15: آزمایش در Strategy Lab، نتیجه‌هایی که زیادی خوب به نظر می‌رسند، روز معاملاتی و سشن‌ها.