Complete x-121.x-rply tool ...
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>X121 XReplay - سند پروژه</title>
|
||||
<style>
|
||||
@page { size: A4; margin: 2cm; }
|
||||
@media print {
|
||||
.page-break { page-break-before: always; }
|
||||
body { font-size: 11px; }
|
||||
}
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
line-height: 1.9; color: #1a1a2e; background: #fff;
|
||||
padding: 40px; max-width: 850px; margin: 0 auto;
|
||||
}
|
||||
h1 { font-size: 1.7em; color: #0f3460; border-bottom: 3px solid #e94560; padding-bottom: 12px; margin-bottom: 20px; }
|
||||
h2 { font-size: 1.35em; color: #16213e; margin-top: 28px; margin-bottom: 12px; padding-right: 12px; border-right: 4px solid #e94560; }
|
||||
h3 { font-size: 1.1em; color: #0f3460; margin-top: 18px; margin-bottom: 8px; }
|
||||
p { margin-bottom: 10px; text-align: justify; }
|
||||
.cover { text-align: center; padding: 70px 0; }
|
||||
.cover h1 { font-size: 2.4em; border: none; color: #e94560; margin-bottom: 10px; }
|
||||
.cover .subtitle { font-size: 1.2em; color: #555; margin-top: 12px; }
|
||||
.cover .meta { margin-top: 50px; color: #777; line-height: 2.2; }
|
||||
table { width: 100%; border-collapse: collapse; margin: 12px 0 20px; font-size: 0.9em; }
|
||||
th, td { border: 1px solid #ccc; padding: 9px 11px; text-align: right; }
|
||||
th { background: #0f3460; color: #fff; font-weight: 600; }
|
||||
tr:nth-child(even) { background: #f4f6f9; }
|
||||
code { background: #f0f0f0; padding: 2px 5px; border-radius: 3px; font-family: 'Courier New', monospace; font-size: 0.87em; color: #c7254e; }
|
||||
pre {
|
||||
background: #1e1e2e; color: #cdd6f4; padding: 16px; border-radius: 6px;
|
||||
overflow-x: auto; margin: 12px 0 20px; font-size: 0.82em;
|
||||
line-height: 1.6; direction: ltr; text-align: left;
|
||||
}
|
||||
.note { background: #fff3cd; border-right: 4px solid #ffc107; padding: 12px 16px; margin: 12px 0; border-radius: 0 5px 5px 0; }
|
||||
.tip { background: #d1ecf1; border-right: 4px solid #17a2b8; padding: 12px 16px; margin: 12px 0; border-radius: 0 5px 5px 0; }
|
||||
.success { background: #d4edda; border-right: 4px solid #28a745; padding: 12px 16px; margin: 12px 0; border-radius: 0 5px 5px 0; }
|
||||
.flow-box { background: #e8f4fd; border: 1px solid #b3d9f2; border-radius: 6px; padding: 14px; margin: 10px 0; }
|
||||
ul, ol { padding-right: 22px; margin-bottom: 10px; }
|
||||
li { margin-bottom: 5px; }
|
||||
.footer { margin-top: 50px; padding-top: 15px; border-top: 2px solid #eee; text-align: center; color: #999; font-size: 0.85em; }
|
||||
.kbd { background: #eee; border: 1px solid #ccc; border-radius: 3px; padding: 2px 6px; font-family: monospace; }
|
||||
.section-num { color: #e94560; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ===== صفحه عنوان ===== -->
|
||||
<div class="cover page-break">
|
||||
<h1>X121 XReplay</h1>
|
||||
<div class="subtitle">ابزار پخش مجدد کندلها در متاتریدر ۵</div>
|
||||
<div class="subtitle" style="color:#e94560;">TradingView-Style Candle Replay Tool for MetaTrader 5</div>
|
||||
<div class="meta">
|
||||
<p><strong>نسخه:</strong> 1.00</p>
|
||||
<p><strong>توسعهدهنده:</strong> هادی خزاعی اصل</p>
|
||||
<p><strong>شرکت:</strong> فن آوران ساحر علم</p>
|
||||
<p><strong>SaherElm IT Center</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== بخش ۱: نیازمندی ===== -->
|
||||
<div class="page-break">
|
||||
<h1><span class="section-num">۱.</span> شرح نیازمندی</h1>
|
||||
|
||||
<h2>۱.۱ مسئله</h2>
|
||||
<p>
|
||||
معاملهگران برای تمرین و بکتست دستی استراتژیهای خود به ابزاری نیاز دارند که بتواند
|
||||
کندلهای بازار را از یک نقطه زمانی مشخص پنهان کند و سپس بهصورت تدریجی
|
||||
(کندل به کندل) آنها را نمایش دهد. این قابلیت در پلتفرم TradingView با نام
|
||||
<strong>Bar Replay</strong> وجود دارد، اما در MetaTrader 5 بهصورت پیشفرض
|
||||
در دسترس نیست.
|
||||
</p>
|
||||
|
||||
<h2>۱.۲ نیازمندیهای عملکردی</h2>
|
||||
<table>
|
||||
<tr><th>#</th><th>نیازمندی</th><th>توضیح</th></tr>
|
||||
<tr><td>۱</td><td>پنهانسازی کندلها</td><td>کندلهای بعد از نقطه cutoff باید از دید کاربر پنهان شوند</td></tr>
|
||||
<tr><td>۲</td><td>نمایش تدریجی</td><td>امکان نمایش کندلها یکییکی با دکمه یا کیبورد</td></tr>
|
||||
<tr><td>۳</td><td>پخش خودکار</td><td>امکان پخش خودکار کندلها با سرعت قابل تنظیم</td></tr>
|
||||
<tr><td>۴</td><td>بازنشانی</td><td>امکان بازگشت به نقطه شروع با یک کلیک</td></tr>
|
||||
<tr><td>۵</td><td>تغییر تایمفریم</td><td>حفظ وضعیت Replay هنگام تغییر تایمفریم چارت</td></tr>
|
||||
<tr><td>۶</td><td>بازیابی خودکار</td><td>بازیابی خودکار حالت چارت پس از حذف اندیکاتور</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۱.۳ محدودیتهای فنی MQL5</h2>
|
||||
<ul>
|
||||
<li>امکان حذف یا پنهانسازی مستقیم کندلهای واقعی وجود ندارد</li>
|
||||
<li>اندیکاتور نمیتواند دادههای تاریخی را تغییر دهد</li>
|
||||
<li>مدیریت رویدادهای چارت محدود به <code>OnChartEvent</code> است</li>
|
||||
<li>ذخیرهسازی وضعیت بین جلسات نیازمند Global Variables یا فایل است</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- ===== بخش ۲: معرفی ابزار ===== -->
|
||||
<div class="page-break">
|
||||
<h1><span class="section-num">۲.</span> معرفی ابزار</h1>
|
||||
|
||||
<h2>۲.۱ مشخصات کلی</h2>
|
||||
<table>
|
||||
<tr><th>مشخصه</th><th>مقدار</th></tr>
|
||||
<tr><td>نام</td><td><code>X121 XReplay</code></td></tr>
|
||||
<tr><td>نوع</td><td>اندیکاتور (Indicator)</td></tr>
|
||||
<tr><td>پلتفرم</td><td>MetaTrader 5 (MQL5)</td></tr>
|
||||
<tr><td>نسخه</td><td>1.00</td></tr>
|
||||
<tr><td>فایل</td><td><code>x-saherelm.x121.x-reply.mq5</code></td></tr>
|
||||
<tr><td>مسیر نصب</td><td><code>MQL5/Indicators/</code></td></tr>
|
||||
<tr><td>وابستگی</td><td><code>x-saherelm.common.lib.mq5</code></td></tr>
|
||||
<tr><td>توسعهدهنده</td><td>هادی خزاعی اصل</td></tr>
|
||||
<tr><td>شرکت</td><td>فن آوران ساحر علم (SaherElm IT Center)</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۲.۲ روش کار</h2>
|
||||
<p>
|
||||
ابزار از روش <strong>DRAW_COLOR_CANDLES</strong> با ۵ بافر برای رسم کندلها استفاده میکند.
|
||||
کندلهای واقعی چارت با تغییر استایل چارت (تبدیل رنگها به <code>CLR_NONE</code>)
|
||||
پنهان میشوند و کندلهای Replay توسط بافرهای اندیکاتور رسم میشوند.
|
||||
</p>
|
||||
|
||||
<h2>۲.۳ بافرها</h2>
|
||||
<table>
|
||||
<tr><th>بافر</th><th>نوع</th><th>کاربرد</th></tr>
|
||||
<tr><td><code>pBarOpenBuffer</code></td><td>INDICATOR_DATA</td><td>قیمت Open</td></tr>
|
||||
<tr><td><code>pBarHighBuffer</code></td><td>INDICATOR_DATA</td><td>قیمت High</td></tr>
|
||||
<tr><td><code>pBarLowBuffer</code></td><td>INDICATOR_DATA</td><td>قیمت Low</td></tr>
|
||||
<tr><td><code>pBarCloseBuffer</code></td><td>INDICATOR_DATA</td><td>قیمت Close</td></tr>
|
||||
<tr><td><code>pBarColorBuffer</code></td><td>INDICATOR_COLOR_INDEX</td><td>ایندکس رنگ کندل</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۲.۴ ایندکسهای رنگ</h2>
|
||||
<table>
|
||||
<tr><th>ایندکس</th><th>نام</th><th>کاربرد</th></tr>
|
||||
<tr><td>0</td><td><code>hideColorIDX</code></td><td>کندل پنهان (CLR_NONE)</td></tr>
|
||||
<tr><td>1</td><td><code>bullishColorIDX</code></td><td>کندل صعودی (clrDodgerBlue)</td></tr>
|
||||
<tr><td>2</td><td><code>bearishColorIDX</code></td><td>کندل نزولی (clrDarkOrange)</td></tr>
|
||||
<tr><td>3</td><td><code>neuturalColorIDX</code></td><td>کندل خنثی</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۲.۵ پارامترهای ورودی</h2>
|
||||
<table>
|
||||
<tr><th>گروه</th><th>پارامتر</th><th>پیشفرض</th><th>توضیح</th></tr>
|
||||
<tr><td rowspan="2">Replay Settings</td><td><code>startBar</code></td><td>20</td><td>تعداد کندلهای cutoff</td></tr>
|
||||
<tr><td><code>autoPlaySpeed</code></td><td>1000</td><td>سرعت پخش خودکار (ms)</td></tr>
|
||||
<tr><td rowspan="4">Presentation</td><td><code>panelButtonTextColor</code></td><td>clrYellow</td><td>رنگ متن دکمهها</td></tr>
|
||||
<tr><td><code>panelBackgroundColor</code></td><td>clrBlack</td><td>رنگ پسزمینه پنل</td></tr>
|
||||
<tr><td><code>infoColor</code></td><td>clrWhite</td><td>رنگ متن اطلاعات</td></tr>
|
||||
<tr><td><code>infoPanelBorderColor</code></td><td>clrBlack</td><td>رنگ حاشیه پنل</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۲.۶ کنترلها</h2>
|
||||
<table>
|
||||
<tr><th>دکمه</th><th>متن</th><th>عملکرد</th><th>کیبورد</th></tr>
|
||||
<tr><td>Prev</td><td><code>|<</code></td><td>یک کندل به عقب</td><td><span class="kbd">←</span> / <span class="kbd">↓</span></td></tr>
|
||||
<tr><td>Play</td><td><code>></code></td><td>شروع پخش خودکار</td><td><span class="kbd">Space</span></td></tr>
|
||||
<tr><td>Pause</td><td><code>||</code></td><td>توقف پخش</td><td><span class="kbd">Space</span></td></tr>
|
||||
<tr><td>Next</td><td><code>>|</code></td><td>یک کندل به جلو</td><td><span class="kbd">→</span> / <span class="kbd">↑</span></td></tr>
|
||||
<tr><td>Reset</td><td><code>R</code></td><td>بازنشانی به نقطه شروع</td><td><span class="kbd">R</span></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ===== بخش ۳: معماری ===== -->
|
||||
<div class="page-break">
|
||||
<h1><span class="section-num">۳.</span> معماری فنی</h1>
|
||||
|
||||
<h2>۳.۱ ساختار فایل</h2>
|
||||
<table>
|
||||
<tr><th>بخش</th><th>محتوا</th></tr>
|
||||
<tr><td><code>#region Imports</code></td><td>کتابخانههای مورد نیاز</td></tr>
|
||||
<tr><td><code>#region Definitions</code></td><td>ثابتها، ساختار XChartStyle، ایندکسهای رنگ</td></tr>
|
||||
<tr><td><code>#region Inputs</code></td><td>پارامترهای ورودی کاربر</td></tr>
|
||||
<tr><td><code>#region Buffers</code></td><td>تعریف ۵ بافر و پلات</td></tr>
|
||||
<tr><td><code>#region Variables</code></td><td>متغیرهای سراسری</td></tr>
|
||||
<tr><td><code>#region Event Handlers</code></td><td>OnInit، OnDeinit، OnCalculate، OnTimer، OnChartEvent</td></tr>
|
||||
<tr><td><code>#region Custm Functions</code></td><td>توابع کمکی و اعتبارسنجی</td></tr>
|
||||
<tr><td><code>#region Value Calculators</code></td><td>محاسبه مقادیر بافرها</td></tr>
|
||||
<tr><td><code>#region Chart Style</code></td><td>مدیریت استایل چارت</td></tr>
|
||||
<tr><td><code>#region UI</code></td><td>پنل کنترل و دکمهها</td></tr>
|
||||
<tr><td><code>#region Control Actions</code></td><td>اکشنهای پخش</td></tr>
|
||||
<tr><td><code>#region TimeFrame Change</code></td><td>مدیریت تغییر تایمفریم</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۳.۲ ساختار XChartStyle</h2>
|
||||
<p>این ساختار ۲۱ فیلد دارد و برای ذخیره و بازیابی کامل حالت چارت استفاده میشود:</p>
|
||||
<table>
|
||||
<tr><th>دسته</th><th>فیلدها</th></tr>
|
||||
<tr><td>شناسایی</td><td>chartId, mode</td></tr>
|
||||
<tr><td>نمایش</td><td>showBidLine, showAskLine, showGrid, showVolumes, showTradeLevels, autoScroll, quickNavigation</td></tr>
|
||||
<tr><td>رنگها</td><td>foreGroundColor, backGroundColor, upColor, downColor, bullishColor, bearishColor, gridColor, bidLineColor, askLineColor, lineColor, stopColor, volumesColor</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۳.۳ مکانیزم پنهانسازی</h2>
|
||||
<div class="flow-box">
|
||||
<ol>
|
||||
<li><strong>ReadChartStyle:</strong> خواندن حالت فعلی چارت و ذخیره در <code>xReplyChartStyle</code></li>
|
||||
<li><strong>SaveChartStyleToFile:</strong> ذخیره در فایل باینری با <code>FileWriteStruct</code></li>
|
||||
<li><strong>ساخت clearStyle:</strong> کپی از حالت اصلی با رنگهای <code>CLR_NONE</code></li>
|
||||
<li><strong>HideBars:</strong> اعمال <code>clearStyle</code> بر چارت → کندلهای واقعی نامرئی میشوند</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h2>۳.۴ مکانیزم رسم کندلهای Replay</h2>
|
||||
<div class="flow-box">
|
||||
<ol>
|
||||
<li><strong>OnCalculate:</strong> پر کردن بافرهای OHLC از دادههای واقعی</li>
|
||||
<li><strong>UpdateVisibleColors:</strong> تنظیم رنگ بافر بر اساس وضعیت Replay</li>
|
||||
<li>کندلهای قبل از cutoff → رنگ عادی (صعودی/نزولی)</li>
|
||||
<li>کندلهای بعد از cutoff → <code>hideColorIDX</code> (پنهان)</li>
|
||||
<li>کندلهای قابل نمایش Replay → رنگ عادی (صعودی/نزولی)</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h2>۳.۵ مدیریت تغییر تایمفریم</h2>
|
||||
<div class="flow-box">
|
||||
<p><strong>هنگام تغییر تایمفریم (OnDeinit با REASON_CHARTCHANGE):</strong></p>
|
||||
<ol>
|
||||
<li>محاسبه ایندکس آخرین کندل نمایش داده شده</li>
|
||||
<li>ذخیره زمان آن کندل در Global Variable</li>
|
||||
<li>ذخیره وضعیت فعال بودن در Global Variable</li>
|
||||
<li>ذخیره تعداد کندلهای قابل نمایش در Global Variable</li>
|
||||
</ol>
|
||||
<p><strong>در تایمفریم جدید (OnInit):</strong></p>
|
||||
<ol>
|
||||
<li>بررسی وجود Global Variables</li>
|
||||
<li>یافتن اولین کندل در تایمفریم جدید که شامل زمان ذخیرهشده است</li>
|
||||
<li>تنظیم <code>xReplyStartBarIndex</code> بر اساس کندل یافتشده</li>
|
||||
<li>بازیابی تعداد کندلهای قابل نمایش</li>
|
||||
<li>حذف Global Variables</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== بخش ۴: فرآیند انجام کار ===== -->
|
||||
<div class="page-break">
|
||||
<h1><span class="section-num">۴.</span> فرآیند و مراحل انجام کار</h1>
|
||||
|
||||
<h2>۴.۱ خلاصه مراحل توسعه</h2>
|
||||
<table>
|
||||
<tr><th>مرحله</th><th>شرح</th><th>نتیجه</th></tr>
|
||||
<tr><td>۱</td><td>تحلیل نیازمندی و بررسی محدودیتهای MQL5</td><td>شناسایی روش پنهانسازی</td></tr>
|
||||
<tr><td>۲</td><td>طراحی معماری با DRAW_COLOR_CANDLES</td><td>تعریف ۵ بافر و ۴ رنگ</td></tr>
|
||||
<tr><td>۳</td><td>پیادهسازی مدیریت Chart Style</td><td>ساختار XChartStyle با ۲۱ فیلد</td></tr>
|
||||
<tr><td>۴</td><td>پیادهسازی ذخیره/بازیابی فایل باینری</td><td>FileWriteStruct / FileReadStruct</td></tr>
|
||||
<tr><td>۵</td><td>پیادهسازی پنل UI و کنترلها</td><td>۵ دکمه + برچسب اطلاعات</td></tr>
|
||||
<tr><td>۶</td><td>پیادهسازی میانبرهای کیبورد</td><td>Arrow Keys + Space + R</td></tr>
|
||||
<tr><td>۷</td><td>پیادهسازی تایمر و پخش خودکار</td><td>StartTimer / StopTimer</td></tr>
|
||||
<tr><td>۸</td><td>پیادهسازی مدیریت تغییر تایمفریم</td><td>Global Variables</td></tr>
|
||||
<tr><td>۹</td><td>بهینهسازی و تست نهایی</td><td>نسخه 1.00</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۴.۲ تصمیمات فنی کلیدی</h2>
|
||||
<table>
|
||||
<tr><th>تصمیم</th><th>دلیل</th></tr>
|
||||
<tr><td>استفاده از DRAW_COLOR_CANDLES</td><td>کارآمدترین روش رسم کندل در MQL5 بدون ایجاد اشیاء گرافیکی</td></tr>
|
||||
<tr><td>پنهانسازی با CLR_NONE</td><td>تنها روش ممکن برای نامرئی کردن کندلهای واقعی بدون حذف آنها</td></tr>
|
||||
<tr><td>ذخیره Chart Style در فایل باینری</td><td>بازیابی خودکار پس از حذف اندیکاتور یا کرش ترمینال</td></tr>
|
||||
<tr><td>Global Variables برای تایمفریم</td><td>حفظ وضعیت بین OnDeinit و OnInit هنگام تغییر تایمفریم</td></tr>
|
||||
<tr><td>تایمر فقط در حالت Play</td><td>بهینهسازی مصرف CPU در حالت Pause</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>۴.۳ ساختار کدنویسی</h2>
|
||||
<p>کد بر اساس دستخط کدنویسی شرکت فن آوران ساحر علم نوشته شده است:</p>
|
||||
<ul>
|
||||
<li>بلوکبندی با <code>#region</code> / <code>#endregion</code></li>
|
||||
<li>کامنتهای ساختاریافته با <code>//</code></li>
|
||||
<li>پیشوند <code>xReply</code> برای متغیرهای مربوط به Replay</li>
|
||||
<li>توابع استاندارد: <code>ValidateInputs</code>، <code>InitRequirements</code>، <code>DefineBuffers</code>، <code>SetIndicatorName</code></li>
|
||||
<li>مدیریت خطا با الگوی <code>has</code> / <code>result</code></li>
|
||||
<li>پاکسازی منابع در <code>OnDeinit</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- ===== بخش ۵: راهنمای استفاده ===== -->
|
||||
<div class="page-break">
|
||||
<h1><span class="section-num">۵.</span> راهنمای استفاده</h1>
|
||||
|
||||
<h2>۵.۱ نصب</h2>
|
||||
<ol>
|
||||
<li>فایل <code>x-saherelm.x121.x-reply.mq5</code> را در مسیر <code>MQL5/Indicators/</code> قرار دهید</li>
|
||||
<li>در MetaEditor با <span class="kbd">F7</span> کامپایل کنید</li>
|
||||
<li>اندیکاتور را از Navigator روی چارت بکشید</li>
|
||||
<li>پارامتر <code>startBar</code> را تنظیم کنید (تعداد کندلهای cutoff)</li>
|
||||
</ol>
|
||||
|
||||
<h2>۵.۲ استفاده</h2>
|
||||
<ul>
|
||||
<li>با <span class="kbd">→</span> یا <span class="kbd">↑</span> یک کندل به جلو بروید</li>
|
||||
<li>با <span class="kbd">←</span> یا <span class="kbd">↓</span> یک کندل به عقب برگردید</li>
|
||||
<li>با <span class="kbd">Space</span> پخش خودکار را شروع/متوقف کنید</li>
|
||||
<li>با <span class="kbd">R</span> به نقطه شروع برگردید</li>
|
||||
<li>تایمفریم را آزادانه تغییر دهید — وضعیت حفظ میشود</li>
|
||||
</ul>
|
||||
|
||||
<h2>۵.۳ حذف</h2>
|
||||
<p>
|
||||
با حذف اندیکاتور از چارت، حالت چارت بهطور خودکار بازیابی میشود،
|
||||
فایل Chart Style حذف میشود و اشیاء UI پاک میشوند.
|
||||
</p>
|
||||
|
||||
<div class="success">
|
||||
<strong>✅ نکته:</strong> در صورت کرش ترمینال، فایل Chart Style باقی میماند و در اجرای بعدی
|
||||
بهجای خواندن از چارت، از فایل خوانده میشود. این تضمین میکند که حالت چارت همیشه درست بازیابی شود.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== فوتر ===== -->
|
||||
<div class="footer page-break">
|
||||
<h2 style="border:none; text-align:center; padding:0;">پایان سند</h2>
|
||||
<br>
|
||||
<p><strong>X121 XReplay</strong> — نسخه 1.00</p>
|
||||
<p>توسعهدهنده: هادی خزاعی اصل</p>
|
||||
<p>فن آوران ساحر علم | SaherElm IT Center</p>
|
||||
<br>
|
||||
<p style="color:#aaa; font-size:0.9em;">© تمامی حقوق محفوظ است</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
// Global Properties ...
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://saherelm.ir"
|
||||
#property version "2.00"
|
||||
#property version "1.00"
|
||||
#property description "SaherElm X121 XReplay Indicator"
|
||||
#property icon "../Images/SaherElm_Logo_Color.ico"
|
||||
#property strict
|
||||
@@ -25,8 +25,15 @@
|
||||
// #endregion
|
||||
|
||||
// #region Definitions ...
|
||||
|
||||
//
|
||||
#define ShortName "X121 XReplay"
|
||||
#define ShortName "X121-XReplay"
|
||||
|
||||
//
|
||||
// Global Variable Keys for TimeFrame Change ...
|
||||
#define GV_ACTIVE_SUFFIX "_Active"
|
||||
#define GV_TIME_SUFFIX "_LastVisibleTime"
|
||||
#define GV_VISIBLE_BARS_SUFFIX "_VisibleBars"
|
||||
|
||||
//
|
||||
#define hideColorIDX 0
|
||||
@@ -116,28 +123,10 @@ double pBarColorBuffer[];
|
||||
#property indicator_label1 "XPBar Open;XPBar High;XPBar Low;XPBar Close"
|
||||
#property indicator_type1 DRAW_COLOR_CANDLES
|
||||
#property indicator_color1 CLR_NONE, clrDodgerBlue, clrDarkOrange
|
||||
|
||||
//
|
||||
// Data Buffers ...
|
||||
|
||||
//
|
||||
// #define pBarTimeBufferIndex buffersCount + 5
|
||||
// datetime pBarTimeBuffer[];
|
||||
|
||||
//
|
||||
// #define pBarTickVolumeBufferIndex buffersCount + 6
|
||||
// long pBarTickVolumeBuffer[];
|
||||
|
||||
//
|
||||
// #define pBarVolumeBufferIndex buffersCount + 7
|
||||
// long pBarVolumeBuffer[];
|
||||
|
||||
//
|
||||
// #define pBarSpreadBufferIndex buffersCount + 8
|
||||
// long pBarSpreadBuffer[];
|
||||
// #endregion
|
||||
|
||||
// #region Variables ...
|
||||
|
||||
//
|
||||
int xReplyLimit;
|
||||
int xReplyMaxLength;
|
||||
@@ -161,10 +150,16 @@ string xReplyBtnReset;
|
||||
// Replay State ...
|
||||
int xReplyCandlesCount = 0;
|
||||
int xReplyStartBarIndex = 0;
|
||||
int xReplyCurrentBarIndex = 0;
|
||||
bool xReplyIsPlaying = false;
|
||||
ulong xReplyLastPlayTick = 0;
|
||||
datetime xReplyStartTime = NULL;
|
||||
int xReplyCurrentVisibleBars = 0;
|
||||
|
||||
//
|
||||
bool xReplyTimerActive = false; // Timer is active only when playing
|
||||
int xReplyLastDrawnBarCount = 0; // Track last drawn bar count for incremental draw
|
||||
bool xReplyIsResumedFromTFChange = false; // Flag: resumed from timeframe change
|
||||
// #endregion
|
||||
|
||||
// #region Event Handlers ...
|
||||
@@ -213,6 +208,10 @@ int OnInit()
|
||||
// Apply Chart Style ...
|
||||
ApplyCustomChartStyle();
|
||||
|
||||
//
|
||||
xReplyIsResumedFromTFChange = TryResumeFromTimeFrameChange();
|
||||
if (!xReplyIsResumedFromTFChange)
|
||||
{
|
||||
//
|
||||
int idx = startBar;
|
||||
if (idx >= Bars(_Symbol, _Period))
|
||||
@@ -229,20 +228,29 @@ int OnInit()
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
|
||||
//
|
||||
xReplyCurrentVisibleBars = 1;
|
||||
xReplyCurrentBarIndex = xReplyStartBarIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Validate Resumed State ...
|
||||
if (xReplyStartBarIndex < 0)
|
||||
{
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create UI Panel ...
|
||||
CreatePanel();
|
||||
|
||||
//
|
||||
// Initial Draw ...
|
||||
xReplyCurrentVisibleBars = 1;
|
||||
DrawVisibleCandles();
|
||||
UpdateInfoLabel();
|
||||
|
||||
//
|
||||
// Enable Timer for Auto Play ...
|
||||
EventSetMillisecondTimer(100);
|
||||
|
||||
//
|
||||
// Init Succeed ...
|
||||
return INIT_SUCCEEDED;
|
||||
@@ -267,6 +275,26 @@ int OnInit()
|
||||
*/
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if (reason == REASON_CHARTCHANGE)
|
||||
{
|
||||
//
|
||||
// Save Global Variables ...
|
||||
SaveReplayStateForTimeFrameChange();
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Remove Global Variables for Other Reasons ...
|
||||
RemoveReplayGlobalVariables();
|
||||
}
|
||||
|
||||
//
|
||||
// Kill Timer if it's Activated ...
|
||||
if (xReplyTimerActive)
|
||||
{
|
||||
StopTimer();
|
||||
}
|
||||
|
||||
//
|
||||
// Show Saved Chart Style ...
|
||||
ShowBars();
|
||||
@@ -278,10 +306,6 @@ void OnDeinit(const int reason)
|
||||
//
|
||||
// Remove UI Objects ...
|
||||
RemoveUIObjects();
|
||||
|
||||
//
|
||||
// Kill Timer ...
|
||||
EventKillTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,31 +349,15 @@ int OnCalculate(
|
||||
ArraySetAsSeries(spread, true);
|
||||
|
||||
//
|
||||
// Validate Calculated Bars ...
|
||||
|
||||
//
|
||||
bool isPassedRequiredCalculatedBars = true;
|
||||
if (!isPassedRequiredCalculatedBars)
|
||||
{
|
||||
return prev_calculated;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Size of Loop ...
|
||||
xReplyLimit = (prev_calculated > rates_total || prev_calculated <= 0)
|
||||
? rates_total
|
||||
//
|
||||
// First Call ...
|
||||
? rates_total - 1
|
||||
//
|
||||
// Subsequent calls: only new bars + current forming bar ...
|
||||
: (rates_total - prev_calculated) + 1;
|
||||
|
||||
//
|
||||
// Buffers Copy ...
|
||||
|
||||
//
|
||||
// Validate Copied Items ...
|
||||
bool isPassedRequiredCopiedItems = true;
|
||||
if (!isPassedRequiredCopiedItems)
|
||||
{
|
||||
return prev_calculated;
|
||||
}
|
||||
|
||||
//
|
||||
// Main Loop ...
|
||||
for (int i = xReplyLimit - 1; i >= 0 && !IsStopped(); i--)
|
||||
@@ -369,12 +377,8 @@ int OnCalculate(
|
||||
}
|
||||
|
||||
//
|
||||
if (prev_calculated == 0)
|
||||
{
|
||||
//
|
||||
string message = "History Finished ...";
|
||||
Print(message);
|
||||
}
|
||||
// Incremental color update ...
|
||||
UpdateVisibleColors();
|
||||
|
||||
//
|
||||
return rates_total;
|
||||
@@ -388,6 +392,12 @@ void OnTimer()
|
||||
//
|
||||
if (!xReplyIsPlaying)
|
||||
{
|
||||
//
|
||||
// Stop Timer ...
|
||||
if (xReplyTimerActive)
|
||||
{
|
||||
StopTimer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -401,7 +411,7 @@ void OnTimer()
|
||||
|
||||
//
|
||||
// Auto Stop at Current Market Bar ...
|
||||
if (xReplyStartBarIndex - xReplyCurrentVisibleBars <= 0)
|
||||
if (xReplyCurrentBarIndex <= 0)
|
||||
{
|
||||
//
|
||||
xReplyIsPlaying = false;
|
||||
@@ -585,6 +595,7 @@ bool InitRequirements()
|
||||
void DefineBuffers()
|
||||
{
|
||||
// #region Plot Buffers ...
|
||||
|
||||
//
|
||||
// SIGNAL Bar ...
|
||||
|
||||
@@ -617,26 +628,6 @@ void DefineBuffers()
|
||||
// Close ...
|
||||
ArraySetAsSeries(pBarCloseBuffer, true);
|
||||
SetIndexBuffer(pBarCloseBufferIndex, pBarCloseBuffer, INDICATOR_DATA);
|
||||
|
||||
//
|
||||
// Time ...
|
||||
// ArraySetAsSeries(pBarTimeBuffer, true);
|
||||
// SetIndexBuffer(pBarTimeBufferIndex, pBarTimeBuffer, INDICATOR_CALCULATIONS);
|
||||
|
||||
//
|
||||
// Tick Volume ...
|
||||
// ArraySetAsSeries(pBarTickVolumeBuffer, true);
|
||||
// SetIndexBuffer(pBarTickVolumeBufferIndex, pBarTickVolumeBuffer, INDICATOR_CALCULATIONS);
|
||||
|
||||
//
|
||||
// Volume ...
|
||||
// ArraySetAsSeries(pBarVolumeBuffer, true);
|
||||
// SetIndexBuffer(pBarVolumeBufferIndex, pBarVolumeBuffer, INDICATOR_CALCULATIONS);
|
||||
|
||||
//
|
||||
// Spread ...
|
||||
// ArraySetAsSeries(pBarSpreadBuffer, true);
|
||||
// SetIndexBuffer(pBarSpreadBufferIndex, pBarSpreadBuffer, INDICATOR_CALCULATIONS);
|
||||
// #endregion
|
||||
}
|
||||
|
||||
@@ -700,6 +691,32 @@ void FillBuffersZero(int barIndex)
|
||||
{
|
||||
pBarColorBuffer[barIndex] = hideColorIDX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Timer only when needed ...
|
||||
*/
|
||||
void StartTimer()
|
||||
{
|
||||
//
|
||||
if (!xReplyTimerActive)
|
||||
{
|
||||
EventSetMillisecondTimer(100);
|
||||
xReplyTimerActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop Timer to save resources ...
|
||||
*/
|
||||
void StopTimer()
|
||||
{
|
||||
//
|
||||
if (xReplyTimerActive)
|
||||
{
|
||||
EventKillTimer();
|
||||
xReplyTimerActive = false;
|
||||
}
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Value Calculators ...
|
||||
@@ -1203,35 +1220,27 @@ void RemoveUIObjects()
|
||||
void UpdateInfoLabel()
|
||||
{
|
||||
//
|
||||
int shownBars = MathMin(
|
||||
xReplyCurrentVisibleBars,
|
||||
xReplyStartBarIndex + 1 //
|
||||
);
|
||||
int totalBars = Bars(_Symbol, _Period);
|
||||
int shownBars = totalBars - xReplyCurrentBarIndex;
|
||||
|
||||
//
|
||||
int currentBarIdx = xReplyStartBarIndex - shownBars + 1;
|
||||
if (currentBarIdx < 0)
|
||||
{
|
||||
currentBarIdx = 0;
|
||||
}
|
||||
|
||||
//
|
||||
datetime barTime = iTime(_Symbol, _Period, currentBarIdx);
|
||||
datetime barTime = iTime(_Symbol, _Period, xReplyCurrentBarIndex);
|
||||
string status = xReplyIsPlaying
|
||||
? "PLAYING"
|
||||
: "PAUSED";
|
||||
|
||||
//
|
||||
string info = StringFormat(
|
||||
"Bar: %d / %d | %s | %s",
|
||||
shownBars,
|
||||
xReplyStartBarIndex + 1,
|
||||
totalBars,
|
||||
TimeToString(barTime, TIME_DATE | TIME_MINUTES),
|
||||
status //
|
||||
);
|
||||
|
||||
//
|
||||
ObjectSetString(0, xReplyLblInfo, OBJPROP_TEXT, info);
|
||||
|
||||
//
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
@@ -1247,56 +1256,40 @@ void DrawVisibleCandles()
|
||||
}
|
||||
|
||||
//
|
||||
// Destroy Existing Candle Objects ...
|
||||
ArrayInitialize(pBarColorBuffer, hideColorIDX);
|
||||
UpdateVisibleColors();
|
||||
|
||||
//
|
||||
int barsToDraw = MathMin(
|
||||
xReplyCurrentVisibleBars,
|
||||
xReplyStartBarIndex + 1 //
|
||||
);
|
||||
// Track drawn count for future optimization ...
|
||||
xReplyLastDrawnBarCount = xReplyCurrentVisibleBars;
|
||||
|
||||
//
|
||||
int barSeconds = PeriodSeconds(_Period);
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
//
|
||||
// Resize Candle Array ...
|
||||
xReplyCandlesCount = barsToDraw;
|
||||
|
||||
//
|
||||
// Main Loop ...
|
||||
bool isBullish = false;
|
||||
int colorIDX = hideColorIDX;
|
||||
for (int i = 0; i < barsToDraw; i++)
|
||||
/**
|
||||
* Called after OHLC buffers are filled in OnCalculate
|
||||
*/
|
||||
void UpdateVisibleColors()
|
||||
{
|
||||
//
|
||||
int barIdx = xReplyStartBarIndex - i;
|
||||
if (barIdx < 0)
|
||||
int bufferSize = ArraySize(pBarColorBuffer);
|
||||
if (bufferSize <= 0)
|
||||
{
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
isBullish =
|
||||
pBarCloseBuffer[barIdx] >= pBarOpenBuffer[barIdx];
|
||||
colorIDX =
|
||||
isBullish
|
||||
? bullishColorIDX
|
||||
: bearishColorIDX;
|
||||
pBarColorBuffer[barIdx] = colorIDX;
|
||||
\ for (int i = 0; i < xReplyCurrentBarIndex && i < bufferSize; i++)
|
||||
{
|
||||
pBarColorBuffer[i] = hideColorIDX;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = xReplyStartBarIndex + 1; i < ArraySize(pBarColorBuffer); i++)
|
||||
for (int i = xReplyCurrentBarIndex; i < bufferSize; i++)
|
||||
{
|
||||
//
|
||||
isBullish =
|
||||
pBarCloseBuffer[i] >= pBarOpenBuffer[i];
|
||||
colorIDX =
|
||||
isBullish
|
||||
? bullishColorIDX
|
||||
: bearishColorIDX;
|
||||
pBarColorBuffer[i] = colorIDX;
|
||||
bool isBullish = pBarCloseBuffer[i] >= pBarOpenBuffer[i];
|
||||
pBarColorBuffer[i] = isBullish ? bullishColorIDX : bearishColorIDX;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1311,17 +1304,13 @@ void DrawVisibleCandles()
|
||||
void StepForward()
|
||||
{
|
||||
//
|
||||
int maxBars = xReplyStartBarIndex + 1;
|
||||
if (xReplyCurrentVisibleBars < maxBars)
|
||||
if (xReplyCurrentBarIndex > 0)
|
||||
{
|
||||
//
|
||||
xReplyCurrentVisibleBars++;
|
||||
xReplyCurrentBarIndex--;
|
||||
DrawVisibleCandles();
|
||||
UpdateInfoLabel();
|
||||
|
||||
//
|
||||
int currentBarIndex = xReplyStartBarIndex - xReplyCurrentVisibleBars + 1;
|
||||
ScrollToBar(currentBarIndex);
|
||||
ScrollToBar(xReplyCurrentBarIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1331,16 +1320,14 @@ void StepForward()
|
||||
void StepBackward()
|
||||
{
|
||||
//
|
||||
if (xReplyCurrentVisibleBars > 1)
|
||||
int totalBars = Bars(_Symbol, _Period);
|
||||
if (xReplyCurrentBarIndex < totalBars - 1)
|
||||
{
|
||||
//
|
||||
xReplyCurrentVisibleBars--;
|
||||
xReplyCurrentBarIndex++;
|
||||
DrawVisibleCandles();
|
||||
UpdateInfoLabel();
|
||||
|
||||
//
|
||||
int currentBarIndex = xReplyStartBarIndex - xReplyCurrentVisibleBars + 1;
|
||||
ScrollToBar(currentBarIndex);
|
||||
ScrollToBar(xReplyCurrentBarIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1350,7 +1337,7 @@ void StepBackward()
|
||||
void ResetReplay()
|
||||
{
|
||||
//
|
||||
xReplyCurrentVisibleBars = 1;
|
||||
xReplyCurrentBarIndex = xReplyStartBarIndex;
|
||||
xReplyIsPlaying = false;
|
||||
|
||||
//
|
||||
@@ -1386,3 +1373,178 @@ void ScrollToBar(int barIndex)
|
||||
ChartRedraw();
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region TimeFrame Change State Management ...
|
||||
/**
|
||||
* Save Replay State for TimeFrame Change ...
|
||||
* Called in OnDeinit when REASON_CHARTCHANGE
|
||||
*/
|
||||
void SaveReplayStateForTimeFrameChange()
|
||||
{
|
||||
//
|
||||
// Calculate Last Visible Bar Index ...
|
||||
int lastVisibleBarIndex = xReplyStartBarIndex - xReplyCurrentVisibleBars + 1;
|
||||
if (lastVisibleBarIndex < 0)
|
||||
{
|
||||
lastVisibleBarIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Last Visible Bar Time ...
|
||||
datetime lastVisibleTime = iTime(_Symbol, _Period, lastVisibleBarIndex);
|
||||
|
||||
//
|
||||
// Validate Time ...
|
||||
if (!IsXValid(lastVisibleTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Generate Global Variable Names ...
|
||||
string gvTimeName = ShortName + _Symbol + GV_TIME_SUFFIX;
|
||||
string gvActiveName = ShortName + _Symbol + GV_ACTIVE_SUFFIX;
|
||||
string gvVisibleBarsName = ShortName + _Symbol + GV_VISIBLE_BARS_SUFFIX;
|
||||
|
||||
//
|
||||
// Save Last Visible Time ...
|
||||
GlobalVariableSet(gvTimeName, (double)lastVisibleTime);
|
||||
|
||||
//
|
||||
// Save Active State ...
|
||||
GlobalVariableSet(gvActiveName, 1.0);
|
||||
|
||||
//
|
||||
// Save Visible Bars Count ...
|
||||
GlobalVariableSet(gvVisibleBarsName, (double)xReplyCurrentVisibleBars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to Resume Replay from TimeFrame Change ...
|
||||
* Called in OnInit to check if we should resume
|
||||
*
|
||||
* @return ( bool ) - true if resumed successfully
|
||||
*/
|
||||
bool TryResumeFromTimeFrameChange()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
// Generate Global Variable Names ...
|
||||
string gvTimeName = ShortName + _Symbol + GV_TIME_SUFFIX;
|
||||
string gvActiveName = ShortName + _Symbol + GV_ACTIVE_SUFFIX;
|
||||
string gvVisibleBarsName = ShortName + _Symbol + GV_VISIBLE_BARS_SUFFIX;
|
||||
|
||||
//
|
||||
// Check Global Variables Exists ...
|
||||
bool wasActive = GlobalVariableCheck(gvActiveName);
|
||||
bool hasSavedTime = GlobalVariableCheck(gvTimeName);
|
||||
|
||||
//
|
||||
result = wasActive && hasSavedTime;
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
// Clean up if partial state exists ...
|
||||
RemoveReplayGlobalVariables();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Saved Time ...
|
||||
double savedTimeDouble = GlobalVariableGet(gvTimeName);
|
||||
datetime savedTime = (datetime)savedTimeDouble;
|
||||
|
||||
//
|
||||
// Validate Saved Time ...
|
||||
result = IsXValid(savedTime);
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
// Clean up if partial state exists ...
|
||||
RemoveReplayGlobalVariables();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Find First Bar in New TimeFrame at or after Saved Time ...
|
||||
// iBarShift with exact=false returns the bar containing or before the time
|
||||
int newBarIndex = iBarShift(_Symbol, _Period, savedTime, false);
|
||||
|
||||
//
|
||||
// Validate New Bar Index ...
|
||||
result = newBarIndex >= 0;
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
// Clean up if partial state exists ...
|
||||
RemoveReplayGlobalVariables();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Replay State for New TimeFrame ...
|
||||
xReplyStartTime = iTime(_Symbol, _Period, newBarIndex);
|
||||
xReplyStartBarIndex = newBarIndex;
|
||||
|
||||
//
|
||||
// Try to restore visible bars count ...
|
||||
if (GlobalVariableCheck(gvVisibleBarsName))
|
||||
{
|
||||
//
|
||||
double savedVisibleBars = GlobalVariableGet(gvVisibleBarsName);
|
||||
xReplyCurrentVisibleBars = (int)savedVisibleBars;
|
||||
|
||||
//
|
||||
// Clamp to valid range ...
|
||||
int maxBars = xReplyStartBarIndex + 1;
|
||||
if (xReplyCurrentVisibleBars > maxBars)
|
||||
{
|
||||
xReplyCurrentVisibleBars = maxBars;
|
||||
}
|
||||
if (xReplyCurrentVisibleBars < 1)
|
||||
{
|
||||
xReplyCurrentVisibleBars = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xReplyCurrentVisibleBars = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Clean Global Variables after successful restore ...
|
||||
RemoveReplayGlobalVariables();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Replay Global Variables ...
|
||||
*/
|
||||
void RemoveReplayGlobalVariables()
|
||||
{
|
||||
//
|
||||
string gvTimeName = ShortName + _Symbol + GV_TIME_SUFFIX;
|
||||
if (GlobalVariableCheck(gvTimeName))
|
||||
{
|
||||
GlobalVariableDel(gvTimeName);
|
||||
}
|
||||
|
||||
//
|
||||
string gvActiveName = ShortName + _Symbol + GV_ACTIVE_SUFFIX;
|
||||
if (GlobalVariableCheck(gvActiveName))
|
||||
{
|
||||
GlobalVariableDel(gvActiveName);
|
||||
}
|
||||
|
||||
//
|
||||
string gvVisibleBarsName = ShortName + _Symbol + GV_VISIBLE_BARS_SUFFIX;
|
||||
if (GlobalVariableCheck(gvVisibleBarsName))
|
||||
{
|
||||
GlobalVariableDel(gvVisibleBarsName);
|
||||
}
|
||||
}
|
||||
// #endregion
|
||||
Reference in New Issue
Block a user