استفاده صحیح از کندلهای Heikin-Ashi در Pine Script
کندلهای Heikin-Ashi یکی از روشهای محبوب برای نمایش قیمت در تریدینگویو هستند که با هدف کاهش نویز و سادهتر کردن تشخیص روند مورد استفاده قرار میگیرند. ظاهر این کندلها به کندلهای معمولی شباهت دارد، اما یک تفاوت بسیار مهم وجود دارد:
قیمتهای Open، High، Low و Close در کندلهای هیکینآشی الزاماً قیمتهای واقعی بازار نیستند.
این تفاوت در هنگام نوشتن اندیکاتورها و بهخصوص استراتژیهای معاملاتی و بکتست اهمیت بسیار زیادی پیدا میکند. اگر برنامهنویس بدون توجه به این موضوع از مقادیر هیکینآشی در کد خود استفاده کند، ممکن است اندیکاتور یا استراتژی رفتاری متفاوت از چیزی که انتظار دارد داشته باشد.
در این آموزش ابتدا نحوه محاسبه کندلهای هیکینآشی را بررسی میکنیم، سپس نحوه دریافت این دادهها در پایناسکریپت را توضیح میدهیم و در نهایت به یکی از مهمترین نکات یعنی استفاده از Heikin-Ashi در استراتژیها و بکتست میپردازیم.
کندل معمولی در مقابل Heikin-Ashi
در یک نمودار کندلی استاندارد، هر کندل دارای چهار مقدار اصلی است:
- Open: قیمت باز شدن
- High: بالاترین قیمت
- Low: پایینترین قیمت
- Close: قیمت بسته شدن
این مقادیر مستقیماً از دادههای بازار به دست میآیند. بنابراین اگر مثلاً Open یک کندل برابر با 3145 دلار باشد، این مقدار نشاندهنده قیمت واقعی بازار در زمان باز شدن آن کندل است.
اما در هیکینآشی شرایط متفاوت است.
هیکینآشی یک نوع نمایش غیر استاندارد قیمت است که OHLC آن بر اساس فرمولهای مشخصی از دادههای واقعی بازار و مقادیر هیکینآشی کندلهای قبلی محاسبه میشود. بنابراین این مقادیر قیمتهای قراردادی هستند، نه قیمتهایی که الزاماً در بازار معامله شدهاند. (TradingView)
به همین دلیل ممکن است وقتی یک کندل را در نمودار استاندارد و نمودار هیکینآشی بررسی میکنیم، مقادیر Open، High، Low و Close متفاوت باشند.
فرمول محاسبه Heikin-Ashi
برای درک صحیح رفتار هیکینآشی در Pine Script بهتر است ابتدا نحوه محاسبه آن را بشناسیم.
اگر مقادیر Heikin-Ashi را با HA مشخص کنیم، فرمولها به شکل زیر هستند.
Close
قیمت بسته شدن Heikin-Ashi از میانگین چهار مقدار واقعی همان کندل محاسبه میشود:
HA Close = (Open + High + Low + Close) / 4
بنابراین برای محاسبه HA Close نیازی به اطلاعات Heikin-Ashi کندل قبلی نداریم.
Open
فرمول Open متفاوت است:
HA Open = (HA Open[1] + HA Close[1]) / 2
یعنی Open کندل Heikin-Ashi فعلی از میانگین Open و Close کندل هیکینآشی قبلی به دست میآید.
در نتیجه، برای محاسبه Open هر کندل به اطلاعات کندل قبلی نیاز داریم.
این وابستگی زنجیرهای یکی از نکات مهم هنگام پیادهسازی Heikin-Ashi در Pine Script است.
High
مقدار High نیز به صورت زیر محاسبه میشود:
HA High = max(High, HA Open, HA Close)
یعنی بیشترین مقدار بین:
- High واقعی کندل
- Open هیکین آشی
- Close هیکین آشی
به عنوان High کندل Heikin-Ashi انتخاب میشود.
Low
به همین شکل:
HA Low = min(Low, HA Open, HA Close)
یعنی کمترین مقدار بین Low واقعی، Open هیکین آشی و Close هیکین آشی انتخاب میشود.
بنابراین خلاصه فرمولها چنین است:
HA Open = (HA Open[1] + HA Close[1]) / 2
HA High = max(High, HA Open, HA Close)
HA Low = min(Low, HA Open, HA Close)
HA Close = (Open + High + Low + Close) / 4
البته در اولین کندل، چون کندل قبلی وجود ندارد، باید مقدار اولیه HA Open را به شکل مناسبی مقداردهی کنیم.
مشکل کندل اول در محاسبه Heikin-Ashi
همانطور که گفتیم، HA Open به HA Open[1] و HA Close[1] وابسته است.
اما در اولین کندل، اطلاعات کندل قبلی وجود ندارد.
بنابراین باید یک مقدار اولیه تعریف کنیم. این مقدار اولیه میتواند به روشهای مختلف تعیین شود؛ نکته مهم این است که بعد از شروع محاسبات، مقدار HA Open در کندلهای بعدی به صورت زنجیرهای محاسبه خواهد شد.
در Pine Script میتوان از barstate.isfirst برای شناسایی اولین کندل استفاده کرد یا با استفاده از متغیرهای var مقدار اولیه را فقط یک بار تعیین کرد.
برای مثال، مفهوم کلی میتواند به صورت زیر باشد:
haOpen = barstate.isfirst ? (open + close) / 2 : (haOpen[1] + haClose[1]) / 2
در اینجا برای اولین کندل از میانگین Open و Close واقعی همان کندل استفاده شده و از کندل دوم به بعد، فرمول اصلی Heikin-Ashi اجرا میشود.
نکته مهم این است که مقدار اولیه در ادامه سری تأثیر بسیار محدودی خواهد داشت؛ زیرا مقدار HA Open به صورت متوالی بر اساس کندلهای بعدی محاسبه میشود.
پیادهسازی Heikin-Ashi در Pine Script
پس از تعریف چهار مقدار OHLC میتوانیم کندلهای محاسبهشده را با plotcandle روی نمودار نمایش دهیم.
ساختار کلی چنین کدی به این صورت است:
//@version=6
indicator("Custom Heikin-Ashi", overlay = true)
haClose = (open + high + low + close) / 4
var float haOpen = na
haOpen := barstate.isfirst ? (open + close) / 2 :
(haOpen[1] + haClose[1]) / 2
haHigh = math.max(high, math.max(haOpen, haClose))
haLow = math.min(low, math.min(haOpen, haClose))
haColor = haClose >= haOpen ? color.green : color.red
plotcandle(haOpen, haHigh, haLow, haClose, color = haColor)
با این روش، بدون اینکه نوع نمودار تریدینگویورا به Heikin-Ashi تغییر دهیم، میتوانیم کندلهای هیکینآشی را خودمان در Pine Script محاسبه و روی نمودار استاندارد نمایش دهیم.
این موضوع یک مزیت مهم دارد: نوع نمودار اصلی همچنان Standard Candles باقی میماند، اما محاسبات ما میتوانند بر اساس Heikin-Ashi انجام شوند.
استفاده از قابلیت داخلی TradingView
البته لازم نیست همیشه فرمولهای Heikin-Ashi را خودمان در Pine Script پیادهسازی کنیم.
TradingView برای دسترسی به دادههای Heikin-Ashi یک قابلیت داخلی در اختیار برنامهنویس قرار داده است:
ticker.heikinashi
این تابع یک شناسه مخصوص برای دادههای هیکینآشی ایجاد میکند و سپس میتوان آن را به request.security داد تا مقادیر هیکینآشی را دریافت کنیم. (TradingView)
برای مثال:
haTicker = ticker.heikinashi(syminfo.tickerid)
haClose = request.security(haTicker, timeframe.period, close)
در اینجا:
ticker.heikinashiشناسه Heikin-Ashi نماد فعلی را ایجاد میکند.request.securityداده مربوط به آن را دریافت میکند.closeمقدار Close کندل Heikin-Ashi خواهد بود.
به همین شکل میتوان Open، High و Low را نیز دریافت کرد.
مثلاً:
haOpen = request.security(haTicker, timeframe.period, open)
haHigh = request.security(haTicker, timeframe.period, high)
haLow = request.security(haTicker, timeframe.period, low)
haClose = request.security(haTicker, timeframe.period, close)
تریدینگویو همچنین امکان دریافت چهار مقدار OHLC را در یک request.security با استفاده از tuple فراهم کرده است. (TradingView)
چرا همیشه استفاده از request.security بهترین انتخاب نیست؟
استفاده از request.security بسیار کاربردی است، اما در اسکریپتهای پیچیده باید به تعداد درخواستهای request نیز توجه داشته باشیم.
فرض کنید علاوه بر Heikin-Ashi، قصد دارید داده چند نماد و چند تایمفریم مختلف را نیز دریافت کنید. اگر برای هر محاسبه چند درخواست جداگانه ایجاد کنیم، تعداد درخواستهای مورد نیاز به سرعت افزایش پیدا میکند.
برای مثال اگر برای دریافت OHLC هیکین آشی چهار درخواست جداگانه داشته باشیم و همین کار را برای چند نماد یا تایمفریم تکرار کنیم، تعداد درخواستها به شکل قابل توجهی افزایش خواهد یافت.
به همین دلیل، اگر هدف فقط محاسبه هیکینآشی بر اساس اطلاعات همان نمودار و همان تایمفریم باشد، گاهی اوقات پیادهسازی مستقیم فرمولها در ابتدای کد انتخاب مناسبتری است.
از طرف دیگر، زمانی که واقعاً به داده هیکینآشی یک نماد یا تایمفریم دیگر نیاز داریم، ticker.heikinashi به همراه request.security ابزار مناسبی است. request.security اساساً برای دریافت داده در contextهای مختلف نماد و تایمفریم طراحی شده است. (TradingView)
نکته مهم درباره اندیکاتورها
یکی از نکات مهمی که هنگام استفاده از هیکینآشی باید به آن توجه کرد، تأثیر آن بر اندیکاتورهاست.
فرض کنید یک Moving Average با دوره 9 روی close محاسبه کردهایم:
ma = ta.sma(close, 9)
اگر نمودار روی کندلهای استاندارد باشد، close همان Close واقعی بازار است.
اما اگر نمودار روی هیکینآشی قرار گرفته باشد، close مربوط به Close مصنوعی هیکینآشی خواهد بود.
در نتیجه: SMA روی کندل استاندارد ≠ SMA روی Heikin-Ashi
حتی اگر هر دو اندیکاتور دقیقاً از یک فرمول و یک Period استفاده کنند.
این موضوع فقط مختص Moving Average نیست. هر اندیکاتوری که از OHLC استفاده کند، ممکن است با تغییر نوع نمودار از Standard Candles به Heikin-Ashi خروجی متفاوتی داشته باشد.
راهکار بهتر: تحلیل با Heikin-Ashi، اجرای واقعی با قیمت بازار
در بسیاری از پروژهها ممکن است بخواهیم سیگنالها بر اساس هیکینآشی تولید شوند، اما قیمت ورود و خروج همچنان قیمت واقعی بازار باشد.
در چنین شرایطی بهتر است نمودار را روی کندلهای استاندارد نگه داریم و دادههای Heikin-Ashi را در داخل کد دریافت یا محاسبه کنیم.
برای مثال میتوانیم:
نمودار اصلی → کندل استاندارد
↓
قیمت واقعی بازار
+
دادههای Heikin-Ashi
↓
محاسبه اندیکاتور
↓
تولید سیگنال
↓
ورود/خروج با قیمت واقعی
این ساختار بهخصوص برای استراتژیها اهمیت زیادی دارد.
تریدینگویو نیز در مستندات خود توصیه میکند که بکتست روی نمودارهای غیر استاندارد مانند هیکینآشی با احتیاط انجام شود، زیرا قیمتهای این کندلها قیمتهای واقعی بازار نیستند و سفارشهای معاملاتی در بازار واقعی با قیمتهای واقعی اجرا میشوند. (TradingView)
چرا بکتست مستقیم روی Heikin-Ashi مشکلساز است؟
فرض کنید استراتژی ما زمانی که دو Moving Average یکدیگر را به سمت بالا قطع میکنند، وارد معامله خرید شود.
اگر استراتژی را روی نمودار استاندارد اجرا کنیم، سفارش بر اساس قیمت واقعی بازار شبیهسازی میشود.
اما اگر نمودار را به Heikin-Ashi تغییر دهیم، Open، High، Low و Close کندلها دیگر الزاماً قیمت واقعی بازار نیستند.
در نتیجه ممکن است استراتژی تصور کند معامله در قیمتی انجام شده که در واقعیت هیچگاه در بازار معامله نشده است.
این مسئله میتواند روی موارد زیر تأثیر بگذارد:
- قیمت ورود
- قیمت خروج
- حد ضرر
- حد سود
- میزان سود و زیان
- تعداد معاملات
- نسبت سود به زیان
- نتایج کلی بکتست
بنابراین ممکن است یک استراتژی روی نمودار هیکینآشی عملکرد بسیار جذابی نشان دهد، اما هنگام اجرای واقعی روی قیمت بازار چنین عملکردی نداشته باشد.
تریدینگویو نیز صراحتاً توضیح میدهد که OHLC هیکین آشی Synthetic است و برای بکتست یا معاملات خودکار مناسب نیست، چون سفارشها با قیمتهای واقعی بازار اجرا میشوند، نه قیمتهای هیکینآشی. (TradingView)
روش پیشنهادی برای استراتژیهای Heikin-Ashi
اگر استراتژی شما بر اساس هیکینآشی طراحی شده است، یک روش مناسب این است که:
1. نمودار را روی Standard Candles قرار دهید.
2. مقادیر هیکینآشی را در خود پایناسکریپت محاسبه کنید یا از ticker.heikinashi دریافت کنید.
3. اندیکاتورها و منطق ورود و خروج را بر اساس دادههای هیکینآشی محاسبه کنید.
4. سفارشها را در محیط استاندارد و بر اساس قیمت واقعی بازار شبیهسازی کنید.
برای مثال اگر قرار است دو EMA بر اساس Close هیکین آشی محاسبه شوند، به جای تغییر نوع نمودار میتوانیم ابتدا Close هیکین آشی را در کد داشته باشیم:
haClose = ...
و سپس:
ema1 = ta.ema(haClose, 9)
ema2 = ta.ema(haClose, 50)
در این حالت منطق تحلیل بر اساس هیکینآشی خواهد بود، اما نمودار اصلی همچنان استاندارد باقی میماند.
جمعبندی
Heikin-Ashi صرفاً یک ظاهر متفاوت برای کندلهای معمولی نیست؛ بلکه مجموعهای از مقادیر OHLC است که با فرمولهای مشخص و بر اساس دادههای واقعی و تاریخی محاسبه میشود. بنابراین قیمتهایی که در یک کندل هیکینآشی مشاهده میکنیم لزوماً قیمتهای واقعی بازار نیستند.
این تفاوت برای برنامهنویسی پایناسکریپت اهمیت زیادی دارد.
اگر هدف ما صرفاً نمایش بهتر روند و کاهش نویز بازار باشد، استفاده از نمودار هیکینآشی میتواند مفید باشد. اما اگر قصد داریم بر اساس هیکینآشی یک اندیکاتور یا بهخصوص یک استراتژی معاملاتی طراحی کنیم، باید بین داده مورد استفاده برای تحلیل و قیمت واقعی مورد استفاده برای معاملات تفاوت قائل شویم.
در پایناسکریپت دو روش اصلی برای کار با هیکینآشی وجود دارد:
روش اول: محاسبه مستقیم
فرمولهای Open، High، Low و Close را خودمان در Pine Script پیادهسازی کنیم.
مزیت این روش این است که کنترل کاملی روی دادهها داریم و در مواردی که فقط به هیکینآشی همان نماد و تایمفریم نیاز داریم، میتوانیم بدون ایجاد درخواستهای متعدد request.security کار کنیم.
روش دوم: استفاده از قابلیت داخلی TradingView
با استفاده از:
ticker.heikinashi
و:
request.security
میتوانیم دادههای هیکینآشی را مستقیماً از تریدینگویو دریافت کنیم. این روش بهخصوص زمانی مفید است که بخواهیم دادههای هیکینآشی یک نماد یا تایمفریم دیگر را دریافت کنیم. (TradingView)
اما مهمترین نکته این است:
اگر تحلیل شما بر اساس هیکینآشی است، لزوماً لازم نیست خود نمودار را روی Heikin-Ashi قرار دهید.
در بسیاری از استراتژیها بهتر است نمودار روی Standard Candles باقی بماند، دادههای هیکینآشی در داخل کد محاسبه شوند و منطق تحلیل بر اساس همان دادهها اجرا شود. به این ترتیب، سیگنالها میتوانند بر اساس هیکینآشی باشند، در حالی که قیمتهای ورود و خروج همچنان به قیمت واقعی بازار مرتبط هستند.
این تفکیک میان داده تحلیلی و قیمت معاملاتی واقعی یکی از نکات کلیدی در طراحی صحیح استراتژیهای پایناسکریپت و جلوگیری از نتایج گمراهکننده در بکتست است.