استراتژیها و سرآیند
سرآیند کامل استراتژی: حجم، کارمزد، اسپرد، لغزش قیمت، سواپ، تأخیر و مارجین، نحوهٔ پر شدن سفارشها، ارقام حساب که میتوانید بخوانید و نتیجهها.
استراتژی اسکریپتی است که سرآیندش یک خط strategy است و سفارشهایش را با تابعهای orders.* میگذارد. نمودار سفارشها را روی کندلهایی که دارد بازپخش میکند و معاملهها را نشان میدهد. هیچ سفارشی به بروکر نمیفرستد. درس 14: اولین استراتژی شما مقدمهٔ کوتاه است، درس 15: آزمایش در Strategy Lab آزمایشهای طولانیتر Strategy Lab را نشان میدهد و این صفحه مرجع است.
واژههای این صفحه#
لات (lot) اندازهٔ استاندارد معامله در یک ابزار است. تیک (tick) کوچکترین گام قیمت است. اسپرد فاصلهٔ قیمت خرید و قیمت فروش است، و لغزش قیمت (slippage) حرکت قیمت بین ثبت سفارش و پر شدن آن. سواپ هزینه (یا اعتبار) نگه داشتن پوزیشن در طول شب است. ضریب سود (profit factor) پولِ بُرده تقسیم بر پولِ باخته است، و افت سرمایه (drawdown) پایین آمدن حساب از اوج آن.
سرآیند#
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_random | true: هر پر شدن به اندازهٔ بخشی تصادفی از slippage میلغزد، نه همهٔ آن |
swap | off: هیچ هزینهٔ شبانهای نیست |
swap_long, swap_short | هزینهٔ شبانهٔ پوزیشن خرید یا فروش برای یک لات و یک شب (عدد منفی هزینه است و عدد مثبت اعتبار)، با واحد swap_mode |
swap_mode | percent، money یا points |
latency | فاصلهٔ زمانی بین سفارش و پر شدنش (300 ms، یا مدتی مثل 1s). قیمت در این فاصله حرکت میکند، پس تأخیر طولانی قیمت پر شدن را عوض میکند؛ تأخیری کوتاهتر از یک کندل اغلب چیزی را روی نمودار عوض نمیکند |
fills | وقتی یک کندل هم به حد ضرر میرسد و هم به هدف، کدام اول پر شود: path (پیشفرض)، worst، best، stop_first، target_first (پایینتر را ببینید) |
costs | none کمیسیون و سواپ خود ابزار را کنار میگذارد، و سواپی را هم که خودتان اعلام کردهاید؛ fees بلوک setup: در هر حال کسر میشود |
lots | round هر حجم را به گام لات ابزار گرد میکند؛ سفارشی که به کمتر از کوچکترین لات گرد شود رد میشود (اجرا میگوید چند سفارش) |
fill_on_close | true سفارش را در قیمت بستهشدن همان کندلی که ثبتش کرده پر میکند، نه در قیمت بازشدن کندل بعد |
کلمههای ticks و ms بعد از یک عدد فقط در یک تنظیم execution: پذیرفته میشوند. جای دیگر رد میشوند:
indicator "A unit outside the header"
edition = 1
plot(25 ticks)تنظیمی که یک بلوک ندارد خطاست، همراه با فهرست تنظیمهایی که دارد:
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 همهٔ پارامترها را فهرست میکند.
کلیدها سختگیرانهاند. اگر ورودی را با کلیدی ببندید که فقط در بزرگی و کوچکی حرفها، فاصله، _ یا - با یکی از کلیدهای بهکاررفته فرق دارد، به احتمال زیاد غلط تایپ کردهاید، و موتور با یک پیشنهاد متوقف میشود:
strategy "A mistyped id"
edition = 1
display = price
if bar.index == 10
orders.enter("Long", side.long)
if bar.index == 20
orders.close("long")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 آن را نشان میدهند، و این همان چیزی است که سقف ضرر روزانه لازم دارد:
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 کندل منصرف میشود:
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، نتیجههایی که زیادی خوب به نظر میرسند، روز معاملاتی و سشنها.