مثال از یک اندیکاتور جدید و LSTM شرطی
در دنیای پویا و متغیر بازارهای مالی، معاملهگران و تحلیلگران همواره به دنبال روشهای نوآورانه برای کسب برتری نسبت به رقبای خود هستند. این مقاله به بررسی یک روش جدید برای معاملهگری خودکار میپردازد که تواناییهای پیشبینی یادگیری عمیق را با قدرت تحلیلهای فنی سنتی ترکیب میکند. هدف ما توسعه یک تکنیک معاملاتی پایدار و انعطافپذیر است که بتواند پیچیدگیهای بازارهای مدرن را مدیریت کند. این امر با ادغام یک مدل شبکه عصبی پیچیده از نوع Conditional Long Short-Term Memory (LSTM) با یک شاخص فنی اختصاصی به نام Volatility Adjusted Momentum (VAM) امکانپذیر میشود.
شاخصهای فنی برای مدت طولانی در صنعت مالی بهعنوان ابزاری برای شناسایی روندها و فرصتهای احتمالی معاملاتی استفاده میشوند. با وجود اهمیت این شاخصها، آنها اغلب نمیتوانند پیچیدگیهای دینامیک بازار را بهطور کامل در زمانهایی که نوسانات شدید یا تغییرات ناگهانی وجود دارد، به تصویر بکشند. اما، معماریهای یادگیری عمیق مانند LSTM بهویژه در شناسایی الگوها و پیشبینیها در دادههای پیچیده و وابسته به زمان، پتانسیل شگفتانگیزی را نشان دادهاند. با این حال، این مدلها همیشه قابلیت تفسیر و دانش تخصصی مربوط به حوزه را که تحلیلهای فنی سنتی ارائه میدهند، ندارند.
استراتژی ما هدف دارد تا این شکاف را پر کند و با ادغام مزایای هر دو رویکرد، به دنبال یک راهحل جامع باشد. این مقاله ابزاری جدید به نام شاخص Volatility Adjusted Momentum (VAM) را معرفی میکند که سعی دارد حرکت بازار را در نظر بگیرد و در عین حال نوسانات زیرین را لحاظ کند. این شاخص، نسبت به شاخصهای حرکتی سنتی، تصویر دقیقتری از دینامیک بازار ارائه میدهد. VAM با توجه به نوسانات، سعی دارد سیگنالهای قابل اعتمادتری را در شرایط مختلف بازار از آرام تا طوفانی ارائه دهد.
برای تقویت شاخص VAM، ما از مدل Conditional LSTM استفاده میکنیم، که نوعی شبکه عصبی بازگشتی است که برای پردازش دادههای توالیدار با دادههای زمینهای اضافی طراحی شده است. این مدل با استفاده از دادههای قیمت تاریخی و شاخصهای فنی آموزش میبیند و میتواند ارتباطات پیچیده و غیرخطی بازار را شناسایی کند که روشهای تحلیل سنتی قادر به شناسایی آنها نیستند. با توجه به ویژگی “شرطی” LSTM، این مدل میتواند متغیرهای بیشتری از بازار را در نظر بگیرد که میتواند منجر به پیشبینیهایی دقیقتر و آگاه از زمینه شود.
مشاور خبره (EA) که یک سیستم معاملاتی خودکار طراحیشده است، مغز متفکر استراتژی ماست و ترکیب شاخص VAM با پیشبینیهای مدل Conditional LSTM را انجام میدهد. این مشاور خبره (EA) بهطور یکپارچه در پلتفرم معروف MetaTrader 5 گنجانده شده است تا به معاملهگران کمک کند تصمیمات آگاهانهتری بگیرند. همچنین، این سیستم دارای قابلیتهای مدیریت ریسک پویا است که سطوح سود و ضرر را با توجه به نوسانات بازار تنظیم میکند.
در این مقاله، به بررسی مبانی نظری مدلهای Conditional LSTM و VAM خواهیم پرداخت و به مزایای آنها و نحوه تعامل بهترین شکل آنها خواهیم پرداخت. ما هر مرحله از ایجاد و پیادهسازی مشاور خبره (EA) را بررسی خواهیم کرد، از جمله تنظیم دادهها، آموزش مدل و ادغام آن در محیط MetaTrader 5. علاوه بر این، نتایج بهینهسازی و آزمونهای مجدد جامع را نمایش خواهیم داد و کارایی استراتژی صرفاً VAM را با استراتژی ترکیبی VAM و Conditional LSTM مقایسه خواهیم کرد.
در اینجا همچنین به چالشها و عواملی که در ادغام روشهای پیشرفته یادگیری ماشین با تحلیلهای فنی سنتی وجود دارد، خواهیم پرداخت. هدف ما ارائه یک مرور جامع از عناصر عملی پیادهسازی چنین سیستمی است که شامل کیفیت دادهها، قابلیت تفسیر مدل و نیازهای محاسباتی اجرای مدلهای پیچیده در شرایط واقعی معاملاتی است.
خوانندگان در پایان این مقاله، درک کاملی از چگونگی استفاده از تکنیکهای پیشرفته یادگیری ماشین برای تقویت تحلیلهای فنی سنتی و بهبود نتایج معاملاتی خواهند داشت. این بررسی از VAM و Conditional LSTM در معاملات خودکار، بینشهای ارزشمندی درباره آینده معاملات الگوریتمی ارائه میدهد، صرفنظر از اینکه شما یک معاملهگر، دانشمند داده یا محققی هستید که در حال کاوش در مرزهای مالی کمی هستید.
Volatility Adjusted Momentum (VAM)
مفهوم اصلی VAM این است که هنگام ارزیابی حرکت بازار، نوسانات بازار را در نظر بگیرد. این شاخص اختلاف بین قیمت کنونی و قیمت گذشته (حرکت) را محاسبه کرده و سپس آن را بر حسب حاصلضرب نوسان و جذر دوره حرکتی تقسیم میکند. این مقدار که با یک عامل مقیاسگذاری شده است، قدرت حرکت را که با توجه به نوسانات اخیر بازار تنظیم شده است، نشان میدهد.
مدل یادگیری عمیق
این مقاله از مدل Conditional LSTM استفاده میکند که نوعی شبکه عصبی بازگشتی (RNN) مناسب برای دادههای زمانی مالی است. این مدل دادههای قیمت تاریخی و شاخصهای فنی (مانند MACD که در اینجا استفاده میشود) را بهعنوان ورودی گرفته و پیشبینیهای حرکتی قیمت آینده را انجام میدهد. مزیت Conditional LSTMها در توانایی آنها برای شناسایی روابط پیچیده بین عوامل مختلف بازار نهفته است.
مشاور خبره (EA)
این مقاله به ایجاد یک EA میپردازد که پیشبینیهای مدل یادگیری عمیق را با VAM ترکیب میکند. در زیر خلاصهای از ویژگیهای اصلی آن ارائه میشود:
- راهاندازی: EA مدل یادگیری عمیق ONNX پیشآموزشدیده را بارگذاری و پارامترهای ورودی و خروجی را پیکربندی میکند.
- دادهکاوی و نرمالسازی: EA مقادیر MACD و دادههای قیمت گذشته را جمعآوری میکند و قبل از وارد کردن این متغیرها به مدل یادگیری عمیق، آنها را نرمالسازی میکند.
- محاسبه VAM: با استفاده از دادههای قیمت تاریخی و کنونی، EA شاخص VAM را محاسبه میکند.
- منطق معاملاتی و پیشبینی: EA پیشبینی قیمتی را از مدل یادگیری عمیق میکشد و پیشبینی را با مقدار VAM ترکیب میکند:
- اگر VAM بالا باشد و پیشبینی به افزایش قیمت اشاره کند، EA یک معامله خرید را آغاز میکند.
- در مقابل، اگر VAM پایین باشد و پیشبینی نشان دهد که قیمت کاهش خواهد یافت، EA یک معامله فروش را آغاز میکند.
- EA ریسک را با تعیین سطوح توقف ضرر و سود بهصورت پویا بر اساس دامنه واقعی متوسط (ATR) مدیریت میکند.
نتایج
این مقاله به نتایج آزمونهای مجدد EA با استراتژیهای VAM با و بدون Conditional LSTM اشاره میکند.
بیایید یک شاخص جدید (VAM) ایجاد کنیم
فرض کنید یک شاخص جدید ایجاد کنیم، مثلاً همین شاخص:
// Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000;
ما از مومنتوم و نوسان برای ایجاد یک شاخص جدید استفاده خواهیم کرد که این شاخص VAM نامیده میشود.
مومنتوم بر حاصلضرب جذر دوره مومنتوم و نوسان تقسیم میشود.
برای مقیاسبندی، نتیجه در نهایت در عدد ۱۰,۰۰۰ ضرب میشود.
با در نظر گرفتن نوسان، شاخص VAM تلاش میکند تا مومنتوم را کمّیسازی کند. این شاخص سعی میکند مومنتوم را در شرایط مختلف بازار متعادل سازد، با تقسیم مومنتوم بر نوسان. استفاده از جذر دوره مومنتوم در مخرج فرمول به استانداردسازی شاخص در دورههای زمانی مختلف کمک میکند.
یک مقدار مثبت VAM نشاندهنده مومنتوم صعودی و یک مقدار منفی VAM نشاندهنده مومنتوم نزولی است. بزرگی مقدار VAM قدرت مومنتوم را، که با توجه به نوسانات اخیر بازار تنظیم شده است، نمایش میدهد.
این شاخص میتواند برای شناسایی بازگشتهای احتمالی روند یا ارزیابی قدرت روندهای فعلی بازار استفاده شود و در عین حال نوسانات بازار را در نظر بگیرد.
با استفاده از این شاخص، میتوانیم یک مشاور خبره (EA) ایجاد کنیم و بررسی کنیم که آیا این استراتژی سودآور است یا خیر.
استراتژی به این صورت خواهد بود:
void OnTick() { int bars = iBars(NULL, 0); if(bars < MathMax(momentum_period, MathMax(volatility_period, (vam_period))))//, MathMax(ma_long_period, rsi_period))))) return; double close_price = iClose(NULL, 0, 0); // Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000; double atr = iATR(_Symbol,PERIOD_CURRENT,14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul*atr,_Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul*atr,_Digits); double slPriceSell = NormalizeDouble(Ask + slmul*atr,_Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul*atr,_Digits); // Señales if(vam > VAMTHRESH)// && ma_short > ma_long)// && rsi < 70 && ma_short > ma_long ) { // Comprar trade.Buy(lot_size,_Symbol, Ask, slPriceBuy, tpPriceBuy, " BUY EA "); } else if(vam < -VAMTHRESH)// && ma_short < ma_long)// rsi > 30 && ma_short < ma_long ) { // Vender trade.Sell(lot_size,_Symbol, Bid, slPriceSell, tpPriceSell, " SELL EA "); } }
تابع iBars(NULL, 0)
تعداد کل میلههای در دسترس برای نماد و بازه زمانی مشخص شده را برمیگرداند.
bars int
: مقدار بازگشتی، یعنی تعداد کل میلهها، در متغیر bars ذخیره میشود.
MathMax: این تابع مقدار بیشینه بین اعداد ورودی را برمیگرداند. در این مورد، به صورت تودرتو استفاده میشود تا حداکثر مقدار را در چندین دوره زمانی تعیین کند.
متغیرهای momentum_period، volatility_period، vam_period، ma_long_period و rsi_period که از قبل تعریف شدهاند، نشاندهنده دورههای زمانی مختلف شاخصها یا محاسبات هستند.
If: شرط بررسی میکند که آیا تعداد کل میلهها کمتر از مجموع زمانهای تخصیص دادهشده است یا خیر.
اگر شرط if درست باشد (یعنی تعداد میلهها کافی نباشد)، تابع فوراً متوقف میشود و بقیه کد اجرا نمیشود.
نتایج VAM
نتایج به این صورت است (پس از یک بهینهسازی سریع، که هنوز تکمیل نشده است):
این به نظر خوب میرسد، برای یک استراتژی ساده و یک اندیکاتور ساده.
بیایید ببینیم چه چیزی میتوانیم با استفاده از یک مدل یادگیری عمیق به دست آوریم (اما امروز قرار است از چیز دیگری استفاده کنیم)، ما قرار است یک مدل یادگیری عمیق با چندین اندیکاتور بسازیم تا ببینیم کدام یک بهتر عمل میکند.
مدلهای یادگیری عمیق
ما این مدل را به فرمت ONNX صادر خواهیم کرد، اما ابتدا باید مقایسه کنیم که کدام یک بهتر است.
برای انجام همه این کارها، از Google Colab استفاده خواهیم کرد (تا منابع رایانههای خود را مصرف نکنیم) با اسکریپت پایتون متصل شده.
از آنجایی که این یک وبسایت MQL5 است، من توضیحاتی در مورد کد پایتون نخواهم داد.
دو اسکریپت پایتون وجود دارد، اولین اسکریپت شامل تمام اندیکاتورهای استفادهشده است و دومین اسکریپت همان اسکریپت است، اما فقط با اندیکاتور MACD (زیرا در اسکریپت اول فرض کردیم که MACD دارای نرخ موفقیت و R² خوبی است و خطاهای کمی دارد).
نتایج گرافیکی از اسکریپت اول به صورت زیر است:
پس از اینکه تصمیم به استفاده از MACD گرفتیم، اسکریپت را آماده کردیم و تاریخها را برای اول ژانویه 2024 تنظیم کردیم (تا بتوانیم نتایج را از تاریخ 1/1/2024 به بعد در MQL5 تست کنیم).
نتایج اسکریپت دوم به این شکل بود (بسیار مشابه).
و غیره… (میتوانید خودتان آن را بسازید و نتایج را با کولاب بررسی کنید).
اسکریپت پایتون برای کولاب طراحی شده است. ابتدا باید سلول اول را اجرا کنید و وقتی تمام کتابخانهها نصب شدند، سلول دوم را اجرا کنید، تأیید کنید که مدلها و گرافها در درایو شما ذخیره شوند و فقط منتظر بمانید تا کار به پایان برسد.
دادهها از MQL5 به دست میآیند، زیرا متاتریدر در کولاب نصب نیست (مقادیر باید مشابه باشند).
همانطور که در گروه دوم تصاویر مشاهده میکنید، مدل MACD دارای نرخ دقت بسیار خوبی است و به همین دلیل آن را انتخاب کردیم.
LSTM شرطی
LSTM شرطی نسخهای بهبود یافته از شبکه عصبی حافظه طولانی-کوتاه (LSTM) سنتی است. با افزودن دادهها یا شرایط زمینهای بیشتر به فرایند پیشبینی معماری LSTM، این مدل را بهبود میبخشد. از آنجا که عوامل زیادی میتوانند بر تغییرات قیمت در بازارهای مالی تأثیر بگذارند، این مدل بهویژه برای پیشبینی بازارهای مالی جالب است.
یک ابزار مؤثر در زمینه پیشبینی سهام یا فارکس، رگرسیون لجستیک شرطی است. این مدل به پیشبینی اجازه میدهد که علاوه بر دادههای قیمت گذشته، تعدادی از شاخصهای بازار و متغیرهای خارجی را نیز در نظر بگیرد. این میتواند شامل دادههای احساسات، شاخصهای اقتصادی عمومی و شاخصهای فنی مانند RSI یا میانگینهای متحرک باشد. مدل سعی میکند با ادغام این ورودیهای مختلف، تصویری جامعتر از دینامیک بازار ارائه دهد.
یکی از مزایای اصلی استفاده از LSTM شرطی برای پیشبینی مالی، آگاهی از زمینه است. بازارهای مالی سیستمهای پیچیدهای هستند که تحت تأثیر عوامل مختلفی قرار میگیرند. با توجه به اینکه LSTM شرطی میتواند چندین شاخص را ترکیب کند، ممکن است قادر به آشکارسازی روابط پیچیده بین دینامیکهای متعدد بازار باشد. توانایی آن در مدیریت ویژگیهای ایستا و دادههای سری زمانی، این مدل را برای بازارهای مالی که در آنها روندهای گذشته و شرایط کنونی به یک اندازه اهمیت دارند، مناسب میسازد.
علاوه بر این، LSTMهای شرطی در شناسایی وابستگیهای بلندمدت در دادههای سری زمانی، درست مانند LSTMهای سنتی، مهارت بالایی دارند. این ویژگی بهویژه در بازارهای مالی که ممکن است الگوهای بلندمدت به وجود آید، مفید است. بهدلیل توانایی آن در حفظ اطلاعات مرتبط در طول دنبالههای طولانی، این مدل میتواند الگوهایی را شناسایی کند که مدلهای سادهتر ممکن است از دست بدهند.
با این حال، استفاده از LSTM شرطی برای پیشبینی مالی با چالشهایی نیز همراه است. اگرچه پیچیدگی بیشتر مدل میتواند مزایایی داشته باشد، اما چالشهایی را نیز به همراه دارد. احتمال بیشبرازش (Overfitting) با پیچیدهتر شدن آموزش، بهویژه هنگام کار با مجموعه دادههای کوچک، افزایش مییابد. این پیچیدگی همچنین هزینههای محاسباتی بیشتری را به همراه دارد که ممکن است عاملی مهم در برنامههای معاملاتی در زمان واقعی باشد.
کیفیت و ارتباط دادهها با LSTMهای شرطی اهمیت بیشتری پیدا میکند. این مدل نه تنها به دادههای قیمت، بلکه به دادههای شاخصهای مرتبط و باکیفیت نیز نیاز دارد. تضمین دادههای دقیق و یکپارچه در تمام این ابعاد میتواند در دنیای مالی که سریعالسیر و گاهی غیرشفاف است، چالشبرانگیز باشد.
همچنین، هنگام ارزیابی پتانسیل LSTMهای شرطی، مهم است که به ماهیت بنیادی بازارهای مالی توجه شود. بازارها تحت تأثیر رویدادهای غیرقابل پیشبینی و رفتار انسانی قرار دارند، که میتواند اثربخشی هر مدلی را محدود کند، هرچقدر هم که پیچیده باشد. این مدل ممکن است در شناسایی الگوها در دادههای تاریخی خوب عمل کند، اما در مواجهه با شرایط بازار بیسابقه یا شوکهای اقتصادی عمده با مشکل مواجه شود.
یکی دیگر از مسائل مربوط به LSTMهای شرطی، مانند بسیاری از مدلهای یادگیری عمیق، قابلیت تفسیر آنها است. حتی اگر این مدلها پیشبینیهای دقیقی تولید کنند، درک دلایل پشت آنها ممکن است دشوار باشد. جنبه “جعبه سیاه” این مدل میتواند در برنامههای مالی که نیاز به توضیحپذیری و شفافیت دارند، مشکلاتی ایجاد کند.
در نهایت، اگرچه LSTMهای شرطی فرصتهای جالبی برای پیشبینی سهام و ارز با استفاده از شاخصها دارند، اما باید به آنها با دقت نزدیک شد. توانایی آنها در ترکیب دادههای پیچیده و چندوجهی ممکن است منجر به پیشبینیهای دقیقتر و دقیقتری شود. با این حال، به دلیل چالشهایی که ناشی از پیچیدگی روزافزون، نیازهای دادهای و عدمقابل پیشبینی ذاتی بازارهای مالی است، باید بهعنوان بخشی از یک رویکرد تحلیلی جامع و بهدقت طراحیشده استفاده شوند. استفاده از چنین تکنیکهای پیشرفتهای در حوزه پرریسک معاملات مالی نیاز به آزمایشهای پسنگر (backtesting) گسترده و درک محدودیتهای مدل در شرایط واقعی دارد.
مدل (همانطور که در اسکریپت پایتون انجام شده) به این شکل است:
و ورودیها و خروجیهای آن باید به این شکل باشد:
کد مشاور متخصص (EA)
هدف اصلی این مشاور متخصص (EA) اتوماسیون تصمیمگیریهای معاملاتی بر اساس ترکیبی از شاخصهای فنی و پیشبینیهای حاصل از یک مدل یادگیری عمیق (ONNX) است. این EA از شاخص «مومنتوم تنظیم شده با نوسانات» (VAM) و «MACD» (همگرایی و واگرایی میانگین متحرک) به همراه پیشبینیهای قیمتی که توسط مدل یادگیری ماشین ارائه شده است، استفاده میکند. این EA با توجه به ترکیب این عناصر، معاملات را اجرا میکند.
این EA با تعریف چندین ویژگی و کتابخانه شروع میشود. کلاس CTrade
برای اجرای معاملات گنجانده شده است و هدرهای دیگری برای توابع آماری و مدیریت آرایهها وجود دارد. پارامترهای ورودی برای محاسبه VAM و اجرای معاملات مانند momentum_period
، volatility_period
و vam_period
تعریف شدهاند که برای کنترل منطق محاسبه مومنتوم و نوسان استفاده میشوند. پارامترهای معاملاتی مانند lot_size
و ضریبهای مربوط به استاپ لاس (slmul
) و تیک پروفیت (tpmul
) نیز در اینجا تعریف شدهاند که انعطافپذیری بیشتری به رفتار EA میبخشند. علاوه بر این، ثابتهایی که پارامترهای مدل ONNX را تعریف میکنند، مانند BATCH_SIZE
و SEQUENCE_LENGTH
، نیز گنجانده شدهاند تا نحوهی انتقال دادهها به مدل یادگیری عمیق مدیریت شود.
//+------------------------------------------------------------------+ //| VAM + DL(MACD) EA | //| Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera | //| https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Javier Santiago Gaston de Iriarte Cabrera" #property link "https://www.mql5.com/en/users/jsgaston/news" #property version "1.01" #include <Trade\Trade.mqh> #include <Math\Stat\Math.mqh> #include <Arrays\ArrayFloat.mqh> CTrade trade; // Inputs input int momentum_period = 13; input int volatility_period = 7; input int vam_period = 9; input double lot_size = 0.01; input int slippage = 3; input double VAMTHRESH = 9.0; input int slmul = 2; input int tpmul = 4; // ONNX model parameters #define BATCH_SIZE 1 #define SEQUENCE_LENGTH 30 #define INPUT_FEATURES 3 #define CONDITION_FEATURES 2 #define HIDDEN_DIM 128 #define NUM_LAYERS 2 float input_x[][SEQUENCE_LENGTH][INPUT_FEATURES]; float input_condition[][CONDITION_FEATURES]; float h0[][BATCH_SIZE][HIDDEN_DIM]; float c0[][BATCH_SIZE][HIDDEN_DIM]; #define PRICE_UP 0 #define PRICE_SAME 1 #define PRICE_DOWN 2 long ExtHandle = INVALID_HANDLE; int ExtPredictedClass = -1; datetime ExtNextBar = 0; datetime ExtNextDay = 0; float ExtMin = 0.0; float ExtMax = 1.0; // Initialize to 1.0 to prevent division by zero float predicted_last; #resource "/Files/stock_prediction_model_MACD.onnx" as uchar ExtModel[]
تابع راهاندازی OnInit()
نقش مهمی دارد زیرا مدل ONNX را از یک منبع باینری (stock_prediction_model_MACD.onnx
) بارگذاری میکند و شکلهای ورودی و خروجی مدل را تنظیم میکند. ورودی به مدل ONNX شامل دادههای قیمت تاریخی، مقادیر MACD و وضعیتهای مخفی و سلولی اولیه (h0
، c0
) برای لایههای تکراری مدل است. اگر مدل با موفقیت بارگذاری شود، این تابع همچنین حداقل و حداکثر مقادیر قیمت (ExtMin
و ExtMax
) را که برای نرمالسازی دادههای ورودی به مدل ONNX استفاده خواهد شد، تنظیم میکند. اگر در حین بارگذاری مدل خطایی رخ دهد، مقدار INIT_FAILED
را بازمیگرداند که بهطور مؤثری عملیات EA را متوقف میکند.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("BATCH_SIZE: ", BATCH_SIZE, ", CONDITION_FEATURES: ", CONDITION_FEATURES); ExtHandle = OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(ExtHandle == INVALID_HANDLE) { Print("OnnxCreateFromBuffer error ", GetLastError()); return(INIT_FAILED); } // Set input shapes long input_shape[] = {BATCH_SIZE, SEQUENCE_LENGTH, INPUT_FEATURES}; if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape)) { Print("OnnxSetInputShape for input_x error ", GetLastError()); return(INIT_FAILED); } long condition_shape[] = {BATCH_SIZE,CONDITION_FEATURES}; if(!OnnxSetInputShape(ExtHandle, 1, condition_shape)) { Print("OnnxSetInputShape for input_condition error ", GetLastError()); return(INIT_FAILED); } long h0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 2, h0_shape)) { Print("OnnxSetInputShape for h0 error ", GetLastError()); return(INIT_FAILED); } long c0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 3, c0_shape)) { Print("OnnxSetInputShape for c0 error ", GetLastError()); return(INIT_FAILED); } const long output_shape[] = {1,1}; if(!OnnxSetOutputShape(ExtHandle,0,output_shape)) { Print("OnnxSetOutputShape error ",GetLastError()); return(INIT_FAILED); } // Initialize ExtMin and ExtMax GetMinMax(); Print("Initializing EA with VAM and ONNX integration"); return(INIT_SUCCEEDED); }
تابع OnTick()
منطق اصلی است که در هر تیک قیمتی اجرا میشود. این تابع با بررسی اینکه آیا روز جدیدی آغاز شده است شروع میشود و حداقل و حداکثر قیمتها را با استفاده از تابع GetMinMax()
بهروز میکند. بلوک بعدی تضمین میکند که تابع تنها زمانی ادامه یابد که یک میله قیمتی جدید در دسترس باشد. سپس EA متغیرهای ExtMin
و ExtMax
را به مقادیر قیمت اخیر بهروز میکند. قلب این تابع ترکیب محاسبه VAM و پیشبینی ONNX است. VAM با گرفتن تفاوت قیمت (مومنتوم) و تقسیم آن بر حاصلضرب نوسان و جذر momentum_period
محاسبه میشود که بهوسیله ۱۰,۰۰۰ مقیاس مییابد. اگر VAM از یک آستانه خاص (VAMTHRESH
) فراتر رود، نشاندهنده یک روند قوی در بازار است که سیگنالی برای یک معامله بالقوه میدهد.
سپس EA نتایج پیشبینی و VAM را ترکیب میکند. اگر VAM بالا (بیش از VAMTHRESH
) باشد و مدل ONNX افزایش قیمت را پیشبینی کند، EA یک معامله خرید با یک حد ضرر و حد سود محاسبهشده بر اساس نوسان واقعی متوسط (ATR) باز میکند. به همین ترتیب، اگر VAM پایین (زیر منفی VAMTHRESH
) باشد و مدل ONNX کاهش قیمت را پیشبینی کند، EA یک معامله فروش باز میکند. این معاملات با استفاده از کلاس CTrade
که با توابع معاملاتی پلتفرم MetaTrader 5 تعامل دارد، اجرا میشوند.
از نظر مدیریت ریسک، سطوح حد ضرر و حد سود بهطور پویا بر اساس ATR دارایی محاسبه میشوند. این اطمینان میدهد که استراتژی با نوسانات بازار تطابق پیدا کند و خروجهای تجاری انعطافپذیری را بسته به شرایط فعلی بازار ارائه دهد.
void OnTick() { // Check for new day and update ExtMin and ExtMax if(TimeCurrent() >= ExtNextDay) { GetMinMax(); ExtNextDay = TimeCurrent() - TimeCurrent() % PeriodSeconds(PERIOD_D1) + PeriodSeconds(PERIOD_D1); } // Check for new bar if(TimeCurrent() < ExtNextBar) return; ExtNextBar = TimeCurrent() - TimeCurrent() % PeriodSeconds() + PeriodSeconds(); // Update ExtMin and ExtMax double close = iClose(_Symbol, _Period, 0); if(ExtMin > close) ExtMin = (float)close; if(ExtMax < close) ExtMax = (float)close; int bars = iBars(_Symbol, PERIOD_CURRENT); if(bars < MathMax(momentum_period, MathMax(volatility_period, MathMax(vam_period, SEQUENCE_LENGTH)))) return; // Calculate VAM double momentum = close - iClose(_Symbol, PERIOD_CURRENT, momentum_period); double volatility = iStdDev(_Symbol, PERIOD_CURRENT, volatility_period, 0, MODE_SMA, PRICE_CLOSE); double vam = (momentum / (volatility * MathSqrt(momentum_period))) * 10000; Print("VAM ", vam); // Get ONNX prediction int result=GetPrediction(); // Trading logic combining VAM and ONNX prediction double atr = iATR(_Symbol, PERIOD_CURRENT, 14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul * atr, _Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul * atr, _Digits); double slPriceSell = NormalizeDouble(Ask + slmul * atr, _Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul * atr, _Digits); //Print(result); if(vam > VAMTHRESH && result == 0) { trade.Buy(lot_size, _Symbol, Ask, slPriceBuy, tpPriceBuy, "BUY VAM+ONNX"); } else if(vam < -VAMTHRESH && result == 2) { trade.Sell(lot_size, _Symbol, Bid, slPriceSell, tpPriceSell, "SELL VAM+ONNX"); } }
پیشبینی مدل ONNX با فراخوانی تابع GetPrediction()
بهدست میآید. ورودی مدل با استفاده از تابع PrepareInputs()
آماده میشود که قیمتهای بسته شدن تاریخی و دادههای MACD را جمعآوری کرده و آنها را با استفاده از دامنه قیمت (ExtMin
و ExtMax
) نرمالیزه میکند و آرایههای ورودی مورد انتظار توسط مدل را پر میکند. این تابع دادهها را برای توالی قیمت ورودی (input_x
) و شرایط مبتنی بر MACD (input_condition
) تنظیم میکند و در عین حال حالتهای پنهان (h0
و c0
) را بازنشانی میکند. هنگامی که ورودی آماده شد، مدل توسط تابع OnnxRun()
اجرا میشود که قیمت پیشبینیشده را محاسبه میکند. تفاوت بین قیمت پیشبینیشده و آخرین قیمت پیشبینیشده برای تعیین اینکه آیا مدل انتظار دارد قیمت بالا برود، پایین بیفتد یا ثابت بماند، استفاده میشود. اگر تغییر در پیشبینی بسیار کوچک باشد، مدل پیشنهاد میکند که حرکتی صورت نگیرد (قیمت ثابت بماند).
void PrepareInputs() { ArrayResize(input_x, BATCH_SIZE); ArrayResize(input_condition, BATCH_SIZE); ArrayResize(h0, NUM_LAYERS); ArrayResize(c0, NUM_LAYERS); for(int i = 0; i < SEQUENCE_LENGTH; i++) { input_x[0][i][0] = (float)((iClose(_Symbol, PERIOD_CURRENT, i) - ExtMin) / (ExtMax - ExtMin)); double macd_main[], macd_signal[]; int macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle, 0, i, 1, macd_main); CopyBuffer(macd_handle, 1, i, 1, macd_signal); input_x[0][i][1] = (float)((macd_main[0] - ExtMin) / (ExtMax - ExtMin)); input_x[0][i][2] = (float)((macd_signal[0] - ExtMin) / (ExtMax - ExtMin)); } double macd_main2[], macd_signal2[]; int macd_handle2 = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle2, 0, 0, 1, macd_main2); CopyBuffer(macd_handle2, 1, 0, 1, macd_signal2); input_condition[0][0] = (float)macd_main2[0]; input_condition[0][1] = (float)macd_signal2[0]; ArrayInitialize(h0, 0.0f); ArrayInitialize(c0, 0.0f); } //+------------------------------------------------------------------+ //| Get prediction from ONNX model | //+------------------------------------------------------------------+ int GetPrediction() { PrepareInputs(); float output_data[]; ArrayResize(output_data, 1); // Run the ONNX model if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, input_x, input_condition, h0, c0, output_data)) { Print("OnnxRun error: ", GetLastError()); return ExtPredictedClass = -1; } float predicted=output_data[0]*(ExtMax-ExtMin)+ExtMin; Print("Predicted last ", predicted_last); Print("Predicted ",predicted); float last_close = (float)iClose(_Symbol, PERIOD_CURRENT, 0); Print("last close ",last_close); float delta = predicted_last - predicted; predicted_last=predicted; Print("Delta ",delta); if(MathAbs(delta) <= 0.00001) ExtPredictedClass = PRICE_SAME; else if(delta < 0) ExtPredictedClass = PRICE_UP; else ExtPredictedClass = PRICE_DOWN; Print(ExtPredictedClass); return ExtPredictedClass; }
void GetMinMax() { double close[]; int copied = CopyClose(_Symbol, PERIOD_D1, 0, SEQUENCE_LENGTH, close); if(copied > 0) { ExtMin = (float)MathMin(close); ExtMax = (float)MathMax(close); } else { Print("Failed to copy price data. Error: ", GetLastError()); ExtMin = 0; ExtMax = 1; // Prevent division by zero } }
به طور خلاصه، این EA ترکیبی از تحلیل تکنیکال (از طریق VAM و MACD) و پیشبینیهای یادگیری ماشین از یک مدل ONNX است تا تصمیمات معاملاتی خودکار و آگاهانهای بگیرد. تحلیل تکنیکال به شناسایی روندها کمک میکند، در حالی که مدل یادگیری ماشین حرکت قیمت را پیشبینی میکند و در نتیجه یک استراتژی ترکیبی ایجاد میشود.
void OnDeinit(const int reason) { if(ExtHandle != INVALID_HANDLE) { OnnxRelease(ExtHandle); ExtHandle = INVALID_HANDLE; } }
پس از بهینهسازی
دانلود فایل های اکسپرت
نتیجهگیری
این مقاله به بررسی ادغام یادگیری عمیق، بهویژه مدلهای LSTM شرطی، با شاخص مومنتوم تعدیلشده با نوسان (VAM) میپردازد تا سیستمهای معاملات خودکار را بهبود بخشد. با ترکیب قابلیتهای پیشبینی LSTM و تحلیل مومنتوم حساس به نوسان VAM، این استراتژی به دنبال درک پیچیدگیهای دینامیک بازار است. این سیستم که بر روی MetaTrader 5 پیادهسازی شده، سیگنالهای معاملاتی تولید میکند و مدیریت ریسک را بهصورت پویا تطبیق میدهد.
نتایج آزمونهای بازگشتی نشان میدهد که وقتی LSTM با VAM ترکیب میشود، نتایج بهتری حاصل میشود. با وجود چالشهایی مانند بیشبرازش و نیازهای محاسباتی، این مطالعه پیشنهاد میکند که ادغام یادگیری عمیق با تحلیل تکنیکال میتواند بهطور قابلتوجهی استراتژیهای معاملاتی الگوریتمی را بهبود بخشد.
نظرات کاربران