مدارهای حفاظتی برای رباتهای معاملاتی چیست؟
مدارهای حفاظتی پیش از تشدید زیان، ربات معاملاتی را متوقف میکنند. با حد زیان روزانه و مقیاسبندی نوسان، اندازه موقعیت و دفعات فعالشدن این کنترل را بشناسید.
مدارهای حفاظتی معاملات رباتها، قواعدی هستند که پس از رسیدن به یک حد مشخص، مانع ارسال سفارش توسط یک استراتژی خودکار میشوند. این قواعد در لایه ریسک، میان استراتژی و کارگزار قرار میگیرند و برای همه سفارشها اجرا میشوند؛ چه استراتژی با آنها موافق باشد و چه نباشد. استراتژی تعیین میکند چه چیزی معامله شود. لایه ریسک تعیین میکند که آیا اساساً معاملهای انجام شود یا نه.
همین تفکیک، مبنای کل طراحی است. استراتژیای که خودش بر عملکرد خود نظارت میکند، در لحظهای که فرضهایش از اعتبار میافتند هیچ کنترل مستقلی ندارد؛ و دقیقاً در همان لحظه است که وجود چنین کنترلی اهمیت پیدا میکند.
مدارشکن در یک ربات معاملاتی چه میکند
لایه ریسک چهار بخش دارد و هر بخش برای جلوگیری از یک خطای مشخص و معمولی طراحی شده است.
- سقفهای سختگیرانه برای اندازه موقعیت، ارزش اسمی معاملات هر نماد و نرخ ارسال سفارش. این سقفها دامنه زیان ناشی از خطایی را محدود میکنند که در غیر این صورت میتوانست نامحدود باشد.
- مدارشکن افت سرمایه که پس از کاهش موجودی حساب به میزان مشخصی در طول جلسه، یا پس از افت آن به میزان مشخصی از اوج ارزش حقوق صاحبان سهام، ارسال سفارشهای جدید را متوقف میکند.
- اندازهگذاری مقیاسپذیر سفارش که بر اساس نوسان اخیر یا کسری از شرط Kelly تعیین میشود، نه تعداد ثابتی از سهم. این روش کمک میکند ریسک هر معامله تقریباً ثابت بماند، حتی وقتی دامنه نوسان بازار تغییر میکند.
- گزارش حسابرسی فقطالحاقی از همه تصمیمها، از جمله سفارشهایی که لایه ریسک رد کرده است. این تنها سندی است که نشان میدهد «استراتژی اشتباه بود» یا «کنترل اصلاً اجرا نشد».
تمام مطالب زیر، تشریح عملی یکی از همین چهار بخش است.
حد معقول زیان روزانه برای یک ربات معاملاتی چیست؟
حد زیان روزانه پس از آنکه زیان جلسه از یک آستانه عبور کند، ارسال سفارشهای جدید را متوقف میکند. انتخاب این عدد به کالیبراسیون نیاز دارد، نه سلیقه. اگر حد را در محدوده نوسان عادی بازار تعیین کنید، ربات بیشتر هفتهها متوقف میماند. اگر آن را بسیار دورتر قرار دهید، هرگز فعال نمیشود. نقطه شروع، بررسی تعداد دفعاتی است که خود بازار در یک روز با افتی در اندازه مشخص مواجه میشود.
کد دقیق SQL پشت هر عدد
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2017-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
with_prev AS (
SELECT d,
close_px,
any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT toYear(d) AS year,
countIf(close_px / prev_close - 1 <= -0.01) AS down_1pct_days,
countIf(close_px / prev_close - 1 <= -0.02) AS down_2pct_days,
countIf(close_px / prev_close - 1 <= -0.03) AS down_3pct_days
FROM with_prev
WHERE prev_close > 0
AND d >= toDate('2018-01-01')
GROUP BY year
ORDER BY yearتعداد جلساتی که در آن بازار با افت یکدرصدی یا بیشتر بسته شد، در 2019 و 2020 بهترتیب 15 و 45 مورد بود؛ این ارقام از حدود 250 روز معاملاتی در سال به دست آمدهاند. شمارش روزهای با افت سهدرصدی یا بیشتر متفاوت است: 0 مورد در 2019، در برابر 16 مورد در 2020. ردیف آخر 9 فقط جلسات معاملاتی تا 31 ژوئیه 2026 را پوشش میدهد.
این روند یکنواخت نیست و بهصورت خوشهای رخ میدهد؛ همین نکته مبنای طراحی حد زیان است. روزهای دشوار در قالب خوشه ظاهر میشوند. رباتی که در نخستین روز یک خوشه متوقف شود و در روز دوم دوباره فعالیت کند، عملاً توقف مؤثری نداشته است.
دو آستانه، دو وظیفه متفاوت دارند. حد زیان روزانه که معمولاً معادل 2٪ از حقوق صاحبان حساب است، جلسه معاملاتی را پایان میدهد. حد افت سرمایه شناور که از بالاترین سطح حقوق صاحبان حساب اندازهگیری میشود و معمولاً حدود 10٪ است، استراتژی را تا زمان بررسی انسانی متوقف میکند. اولی اقدامی معمول است و دومی باید بهندرت فعال شود. رباتی که فقط حد نخست را داشته باشد، میتواند حساب را هر بار 2٪ کوچکتر کند، بیآنکه هیچگاه سازوکار حفاظتی دیگری فعال شود.
How does volatility scaling change position size?
Volatility targeting sizes a position inversely to recent realized volatility: when the daily range doubles, the position roughly halves, holding the dollar risk per trade near constant. Realized volatility here is the annualized standard deviation of daily returns, and it travels further than most people expect.
کد دقیق SQL پشت هر عدد
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2023-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
rets AS (
SELECT d,
close_px / any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) - 1 AS ret
FROM daily
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(stddevSamp(ret) * sqrt(252) * 100, 1) AS realized_vol_pct,
round(least(100.0, 1200.0 / (stddevSamp(ret) * sqrt(252) * 100)), 1) AS vol_target_size_pct
FROM rets
WHERE d >= toDate('2024-01-01')
AND isFinite(ret)
GROUP BY toStartOfMonth(d)
HAVING count() >= 15
ORDER BY toStartOfMonth(d)Realized volatility measured 11.1% annualized in 2024-01 and 12% in 2026-07, across 31 months. The second column turns each reading into the position a 12% volatility target would carry, capped at the full line: 100% in 2024-01 against 99.7% in 2026-07. Same strategy, same conviction, a very different share count.
The Kelly criterion approaches the same problem from the other end, sizing from estimated edge and variance rather than from volatility alone. Most systematic operators run a fraction of it, half or quarter Kelly, given that both inputs are estimates off a finite sample. Kelly criterion position sizing works through that arithmetic.
چرا یک ربات معاملاتی پس از فعالشدن حد ضرر دوباره وارد معامله میشود؟
حد ضرر فعال میشود. موقعیت بسته میشود. نود ثانیه بعد، شرط ورود دوباره برقرار است، ربات مجدداً وارد معامله میشود، همان زیان را متحمل میشود و این روند تکرار میشود. هیچیک از اجزای سیستم خراب نیستند. استراتژی همان کاری را انجام داده که برای آن نوشته شده است، حد ضرر نیز وظیفه خود را انجام داده است و حساب معاملاتی همچنان در هر رفتوبرگشت زیان میکند.
تعداد دفعات این اتفاق مستقیماً از مسیر قیمت ناشی میشود. این نمودار در هر جلسه معاملاتی میشمارد که SPY چند بار از بیش از 0.1 درصد بالاتر از قیمت آغازین خود به بیش از 0.1 درصد پایینتر از آن رفته، یا برعکس، از پایین به بالا بازگشته است.
کد دقیق SQL پشت هر عدد
WITH mins AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
window_start AS ts,
toFloat64(close) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2025-08-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
),
opens AS (
SELECT d, argMin(px, ts) AS open_px
FROM mins
GROUP BY d
),
zoned AS (
SELECT m.d AS d,
m.ts AS ts,
multiIf(m.px >= o.open_px * 1.001, 1,
m.px <= o.open_px * 0.999, -1,
0) AS zone
FROM mins AS m
INNER JOIN opens AS o ON m.d = o.d
),
flips AS (
SELECT d,
zone,
any(zone) OVER (PARTITION BY d ORDER BY ts ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_zone
FROM zoned
WHERE zone != 0
),
per_day AS (
SELECT d, countIf(prev_zone != 0 AND zone != prev_zone) AS crossings
FROM flips
GROUP BY d
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(avg(crossings), 1) AS avg_crossings_per_session,
max(crossings) AS max_crossings_in_a_session
FROM per_day
GROUP BY toStartOfMonth(d)
ORDER BY toStartOfMonth(d)SPY در 2025-08 بهطور میانگین 0.7 بار در هر جلسه از این دامنه عبور کرد و در 2026-07 این رقم به 1.5 بار رسید؛ همچنین در یک جلسه در 2026-07، 5 عبور ثبت شد. هر قاعدهای که در یک سوی سطح وارد معامله شود و در سوی دیگر حد ضرر بگذارد، در یک روز فرصت دارد به همین تعداد فعال شود.
چهار سازوکار این چرخه را محدود میکنند.
- دوره توقف پس از هر حد ضرر، برحسب دقیقه یا کندل، که طی آن هیچ سفارش جدیدی برای آن نماد از لایه مدیریت ریسک عبور نمیکند.
- سقف روزانه تعداد معاملات برای هر نماد که یک چرخه نامحدود را به چرخهای محدود تبدیل میکند.
- پرچم توقفی که در وضعیت فعال باقی میماند. پس از فعالشدن حد زیان روزانه، این پرچم تا زمانی که فردی آن را پاک نکند، فعال میماند.
- ذخیرهسازی این پرچم خارج از حافظه فرایند. سرپرستی که ربات ازکارافتاده را راهاندازی مجدد میکند، وضعیت پاکی به آن میدهد؛ در حالی که جلوگیری از همین وضعیت، دلیل وجود پرچم است.
مورد آخر، افرادی را گرفتار میکند که همه اقدامات دیگر را درست انجام دادهاند. رباتهای معاملهگری شبکهای ذاتاً نردبانهایی از سفارشها ایجاد میکنند؛ بنابراین سقف تعداد معاملات، جزئی حیاتی است و نه قابلیتی تزئینی.
وقتی یک ربات بر اساس خوراک قیمتی منسوخ معامله میکند چه رخ میدهد؟
قیمتی که دیگر بهروزرسانی نمیشود، همچنان یک عدد به نظر میرسد. ربات آن را میخواند، سفارش را بر مبنای همان قیمتگذاری میکند و سفارش را وارد بازاری میکند که حرکت کرده است. این خطا بیصدا رخ میدهد: هیچ خطایی ایجاد نمیشود، گزارشی ثبت نمیشود و نامتعارفبودن معاملات تنها بعداً، هنگام مشاهده معاملات اجراشده، مشخص میشود.
نسخهای که بهروشنی قابلاندازهگیری است، شکاف شبانه است؛ زمانی که یک قیمت شناختهشده ساعتها بدون تغییر باقی میماند، در حالی که قیمت قابلمعامله حرکت میکند.
کد دقیق SQL پشت هر عدد
WITH daily AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMin(toFloat64(open), window_start) AS open_px,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'KO', 'MSFT', 'AAPL', 'NVDA', 'TSLA')
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2024-01-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, d
),
gaps AS (
SELECT ticker,
d,
open_px,
any(close_px) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT ticker,
round(quantileDeterministic(0.5)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS median_gap_pct,
round(quantileDeterministic(0.95)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS p95_gap_pct,
round(max(abs(open_px / prev_close - 1) * 100), 2) AS max_gap_pct
FROM gaps
WHERE prev_close > 0
GROUP BY ticker
ORDER BY p95_gap_pct DESCنمادی که در صدک 95 شکاف، بیشترین فاصله را داشت TSLA بود؛ این رقم برای آن 4.41% و برای KO، 1% بود. در شبهای معمول، بازار بسیار آرامتر بود: میانه شکافها بهترتیب 1.01% و 0.24% بود. لبههای توزیع همان جایی است که لایه مدیریت ریسک برای آن طراحی میشود و بزرگترین شکاف منفرد در TSLA طی دوره بررسی، 14.57% اندازهگیری شد. اینها همان فاصلههایی هستند که ربات هنگام اتکا به قیمتی که مدتی پیش خوانده است، با آنها مواجه میشود. چرا سهام در طول شب با شکاف قیمتی باز میشوند سازوکار این پدیده را توضیح میدهد.
راهکارهای دفاعی کمهزینهاند. برای هر مظنهای که لایه ریسک بر اساس آن قیمتگذاری میکند، حداکثر عمر تعیین کنید؛ این مدت برای یک استراتژی درونروزی معمولاً چند ثانیه است. سیگنال heartbeat خوراک را جدا از داده دریافت کنید تا سوکت خاموش از بازار کمتحرک قابلتشخیص باشد. داده مفقود را بهجای وضعیت ثابت، توقف معاملات تلقی کنید؛ زیرا رباتی که هیچ قیمتی در اختیار ندارد، نمیتواند نقاط خروج خود را نیز ارزیابی کند.
کدام سقفهای سخت باید در لایه ریسک قرار گیرند؟
- حداکثر ارزش اسمی هر نماد بهعنوان سهمی از حقوق صاحبان سهام حساب. سقف 10درصدی مانع میشود یک نماد زیانده کل حساب را تحتتأثیر قرار دهد.
- حداکثر ارزش اسمی ناخالص همه موقعیتهای باز. تعیین این سقف در سطح 100درصد حقوق صاحبان سهام به معنای استفادهنکردن از اهرم است؛ تصمیمی که باید صراحتاً گرفته شود، نه اینکه از تنظیمات پیشفرض کارگزار به ارث برسد.
- حداکثر تعداد سفارشها در دقیقه و در روز. برای بیشتر استراتژیهای معاملهگری سرمایهگذاران خرد، 10 سفارش در دقیقه رقم بالایی است و در عین حال، یک حلقه خارج از کنترل را در بازه یک دقیقه محدود میکند.
- حداکثر اندازه سفارش بهعنوان سهمی از میانگین حجم روزانه نماد. سقف 1درصدی مانع میشود ربات قیمت داراییای را که قصد معامله آن را دارد جابهجا کند و میانگین حجم روزانه مخرج این محاسبه است.
همه این موارد باید در لایه ریسک قرار گیرند، نه در استراتژی؛ همچنین همه آنها باید در آزمون پسنگر، معاملات آزمایشی و معاملات واقعی از یک مسیر کدنویسی یکسان عبور کنند. محدودیتی که فقط در معاملات واقعی وجود داشته باشد، محدودیتی است که هیچکس آن را آزمایش نکرده است.
گزارش ممیزی ربات معاملاتی به چه چیزهایی نیاز دارد؟
گزارش فقطافزودنی برای هر تصمیم یک رکورد ثبت میکند و هرگز رکوردی را ویرایش یا حذف نمیکند. هر رکورد باید زمان ثبت، مظنه استفادهشده و عمر آن، نتیجه همه بررسیهای حدودی اجراشده، سفارش ارسالشده و پاسخ کارگزار را دربر داشته باشد. سفارشهای ردشده باید با همان اهمیت سفارشهای تکمیلشده ثبت شوند.
هدف، بازسازی رویدادهاست. شش هفته پس از یک جلسه معاملاتی ناموفق، پرسش اصلی هرگز این نیست که P&L چه میزان بوده است. پرسش این است که کدام بررسی، بر مبنای چه دادهای، موفق شده است. بدون ثبت داده ورودی، ناچار میشوید وضعیت ربات را از روی وضعیت بازار دوباره استخراج کنید؛ این همان خطایی است که در سوگیری نگاه به آینده در پسآزمایی رخ میدهد: استفاده از اطلاعاتی که سیستم در لحظه تصمیمگیری در اختیار نداشته است.
پروژه riskguard یکی از پیادهسازیهای متنباز این تفکیک است. در این پروژه، بررسیهای حدودی در مؤلفهای قرار دارند که استراتژی آن را فراخوانی میکند، نه اینکه منطق بررسیها در سراسر خود استراتژی پراکنده باشد. این فقط یکی از چندین الگوست و بهتر است پیش از پذیرش، آن را مطالعه کنید. هر مؤلفهای که به آن وابسته هستید، یک نسخه برچسبگذاریشده را ثابت کنید، نه شاخه پیشفرض را. شاخه ممکن است بین دو اجرای یک پسآزمایی تغییر کند و لایه مدیریت ریسکی که بیسروصدا تغییر کرده است، از نبودن چنین لایهای بدتر است.
چرا نخستین اجرا با یک کارگزار آزمایشی انجام میشود
آداپتور کارگزار بهطور پیشفرض روی حساب آزمایشی تنظیم است و انجام معاملات واقعی بهصورت عمدی به فعالسازی یک گزینه صریح نیاز دارد. این کار از خطایی ساده اما پرهزینه جلوگیری میکند: فایل پیکربندی کپیشده یا متغیر محیطیای که هرگز تغییر نکرده است، سفارشهای واقعی را با پول واقعی ارسال کند.
اجرای آزمایشی همچنین خروجی مهمی ایجاد میکند: گزارش تصمیمگیری از همان لایه مدیریت ریسک، بر مبنای قیمتهای واقعی بازار، که نشان میدهد کدام محدودیتها فعال شدند و کدامیک فعال نشدند. این گزارش درباره عملکرد لایه ریسک شواهد ارائه میکند؛ موضوعی جدا از این پرسش که آیا راهبرد سودآور است یا نه. معامله آزمایشی پیش از استفاده از پول واقعی توضیح میدهد که یک سابقه معاملاتی آزمایشی چه چیزهایی را ثابت میکند و چه چیزهایی را ثابت نمیکند. سامانههای معاملاتی هوش مصنوعی چندعاملی نیز نشان میدهد چرا وقتی چند عامل میتوانند سفارش ارسال کنند، اختیار توقف باید خارج از اختیار همه آنها قرار داشته باشد.
پرسشهای متداول درباره قطعکننده اضطراری ربات معاملاتی
قطعکننده اضطراری در ربات معاملاتی چیست؟
قاعدهای در لایه مدیریت ریسک است که پس از رسیدن زیان یا ریسک به حد تعیینشده، ارسال سفارشهای جدید توسط ربات را متوقف میکند. این حد معمولاً آستانه زیان روزانه یا میزان افت سرمایه از اوج ارزش حساب است. این سازوکار مستقل از استراتژی و برای هر سفارش اجرا میشود و تا زمانی که عامل مشخصی آن را رفع نکند، فعال باقی میماند.
بازار هر چند وقت یکبار یک روز با افت 2 درصدی را تجربه میکند؟
SPY در 2019 جلسه، در 5 یا بیشتر افت کرد و در 2020 نیز 25 جلسه از این نوع ثبت شد؛ هر سال تقریباً 250 روز معاملاتی دارد. همین فاصله میان یک سال آرام و یک سال پرتنش نشان میدهد که حد زیان باید بر اساس سابقه بازار تنظیم شود، نه بر مبنای حدس و شهود.
چگونه مانع ورود دوباره ربات پس از توقف میشوید؟
تعیین یک دوره توقف پس از هر بار فعالشدن حد زیان و تعیین سقف روزانه معاملات برای هر نماد، یک حلقه نامحدود را به فرآیندی محدود تبدیل میکند. پرچم توقف نیز باید خارج از حافظه فرایند ثبت و حفظ شود؛ زیرا در غیر این صورت، ناظر با راهاندازی مجدد رباتی که از کار افتاده است، وضعیت تازهای را در اختیار آن میگذارد که در آن توقف فعال نیست.
ربات چگونه متوجه میشود که دادههای قیمت قدیمی شدهاند؟
ربات باید پیش از قیمتگذاری سفارش بر اساس هر مظنه، عمر آن را بررسی کند و ضربان قلب دریافتی از منبع داده را نیز جداگانه زیر نظر بگیرد. شکافهای شبانه، ابعاد چیزی را که قیمت قدیمی پنهان میکند نشان میدهند: صدک 95 حرکت شبانه از ژانویه 2024 تا ژوئیه 2026 در TSLA به 4.41% رسید.
آیا یک ربات معاملاتی کوچک واقعاً به گزارش ثبت رویداد نیاز دارد؟
گزارش معاملات اجراشده نشان میدهد چه اتفاقی افتاده است. گزارش تصمیمها نشان میدهد ربات تصور میکرد مجاز به انجام چه کاری است؛ و این تنها راه تشخیص تفاوت میان یک استراتژی نادرست و کنترل ریسکی است که هرگز اجرا نشده است. نسخه حداقلی و مفید این گزارش باید فقط امکان الحاق داشته باشد و رد سفارشها را نیز ثبت کند.
تمام ارقام بالا از یک کوئری ذخیرهشده روی دادههای میلهای دقیقهای به دست آمدهاند و هر پنل به SQL مربوط به خود باز میشود. همین کوئریها را روی فهرست نمادهای خود در پایانه Strasmore اجرا کنید.