ডুয়াল মুভিং এভারেজ ট্রেডিং কৌশলটি একটি দ্রুত ইএমএ এবং ধীর ইএমএ গঠনের জন্য বিভিন্ন সময়সীমার এক্সপোনেনশিয়াল মুভিং এভারেজ (ইএমএ) গণনা করে এবং তাদের সোনার ক্রস এবং মৃত্যুর ক্রস পর্যবেক্ষণ করে ট্রেডিং সংকেত তৈরি করে। যখন দ্রুত ইএমএ ধীর ইএমএর উপরে অতিক্রম করে তখন এটি দীর্ঘ হয় এবং যখন দ্রুত ইএমএ ধীর ইএমএর নীচে অতিক্রম করে তখন এটি সংক্ষিপ্ত হয়। এই কৌশলটি চলমান গড়ের প্রবণতা বিপরীত পয়েন্টগুলি ক্যাপচার করে এবং এটি একটি প্রবণতা অনুসরণকারী কৌশল যা সাধারণত ব্যবহৃত হয়।
দ্বৈত চলমান গড় কৌশলটির মূল সূচকগুলি হল দ্রুত ইএমএ এবং ধীর ইএমএ। দ্রুত ইএমএর ডিফল্ট প্যারামিটার 12 দিন, যখন ধীর ইএমএর ডিফল্ট প্যারামিটার 26 দিন। এক্সপোনেনশিয়াল চলমান গড়ের সূত্রটি হলঃ
EMA (t) = (C (t) - EMA (t-1)) x SF + EMA (t-1)
যেখানে C (t) হল আজকের বন্ধের মূল্য এবং SF হল মসৃণকরণ ফ্যাক্টর। সাধারণ চলমান গড়ের থেকে ভিন্ন, EMA সাম্প্রতিক তথ্যের জন্য আরো ওজন দেয় এবং তাই মূল্য পরিবর্তনের জন্য দ্রুত প্রতিক্রিয়া জানায়।
ব্যবসায়ের নিয়ম হল:
নিম্ন থেকে ধীর EMA এর উপরে দ্রুত EMA এর সোনালী ক্রস এ লং পজিশন প্রবেশ করুন।
উপরে থেকে ধীর EMA এর নীচে দ্রুত EMA এর মৃত্যুর ক্রসিংয়ের শর্ট পজিশন প্রবেশ করান।
ইএমএ-র বিচ্ছিন্নতার উপর পজিশনগুলি প্রস্থান করুন।
ইএমএ-র ক্রসওভার প্যাটার্নগুলি ক্যাপচার করে এটি বাজারের প্রবণতা প্রতিফলিত করতে পারে এবং লাভজনকতা বাড়িয়ে তুলতে পারে।
একটি পরিপক্ক প্রযুক্তিগত সূচক কৌশল হিসাবে, দ্বৈত চলমান গড় কৌশল নিম্নলিখিত শক্তি আছেঃ
এর যুক্তি স্পষ্ট এবং বোঝা এবং বাস্তবায়ন করা সহজ।
এটি বাজারের চাহিদা ও সরবরাহ সম্পর্কে অত্যন্ত নির্ভুল মূল্যায়ন দেয় এবং তাই এর লাভের হার তুলনামূলকভাবে বেশি।
এটি কার্যকরভাবে বাজারের গোলমাল ফিল্টার করে এবং প্রধান প্রবণতাগুলি ধরা পড়ে।
এটি বিভিন্ন উপকরণ এবং সময়সীমার মধ্যে প্রয়োগ করা যেতে পারে।
এটি কৌশল সমৃদ্ধির জন্য অন্যান্য সূচকগুলির সাথে একত্রিত করা যেতে পারে।
বড় মূলধন ব্যবসায়ের জন্য এটির মূলধন ব্যবহারের দক্ষতা বেশি।
এই কৌশলটির কিছু সীমাবদ্ধতা রয়েছে:
বাজারের তীব্র গতিবিধি যেমন হ্রাস বাজার বিক্রির ক্ষেত্রে এটি প্রতিক্রিয়া জানাতে ব্যর্থ হয়।
এটি প্রায়শই মিথ্যা সংকেত এবং সাইডওয়াইড রেঞ্জযুক্ত বাজারে হুইপস তৈরি করে।
এর পরামিতিগুলিকে বিভিন্ন বাজারে এবং সময়সীমার মধ্যে অপ্টিমাইজ করার প্রয়োজন।
এটি প্রবণতার উপযুক্ত বিপরীত মাত্রা নির্ধারণ করতে পারে না।
এই কৌশলকে আরও শক্তিশালী করার জন্য EMA সময়কাল সংশোধন, অতিরিক্ত ফিল্টার ইত্যাদি যোগ করে ঝুঁকিগুলি হ্রাস করা যেতে পারে।
নিম্নলিখিত দিকগুলি থেকে দ্বৈত চলমান গড় কৌশল উন্নত করা যেতে পারেঃ
প্রবণতা শক্তি বিচার এবং ভুল ট্রেড এড়াতে MACD সূচক অন্তর্ভুক্ত করুন।
সত্যিকারের ব্রেকআউট সংকেত নিশ্চিত করার জন্য ট্রেডিং ভলিউম যোগ করুন।
আরো সুনির্দিষ্ট প্রবেশ এবং প্রস্থান নিয়মের জন্য বোলিংজার ব্যান্ড, ক্যান্ডেলস্টিক প্যাটার্নের সাথে একত্রিত করুন।
আরও ভাল অভিযোজনযোগ্যতার জন্য স্বয়ংক্রিয়ভাবে প্যারামিটারগুলি অনুকূল করতে LSTM এর মতো মেশিন লার্নিং পদ্ধতিগুলি ব্যবহার করুন।
দ্বৈত চলমান গড় ট্রেডিং কৌশলটি স্থিতিশীল মুনাফার জন্য প্রবণতা বিপরীত পয়েন্টগুলি নির্ধারণের জন্য ইএমএ সোনার ক্রস এবং মৃত্যুর ক্রস থেকে ট্রেডিং সুযোগগুলি ক্যাপচার করে। সরলতা, মূলধন দক্ষতা এবং বাস্তবায়নের সহজতার সুবিধার সাথে এটি অ্যালগরিদমিক ট্রেডিং নতুনদের জন্য একটি পছন্দসই পছন্দ। তবে এর ভুল সংকেত তৈরির মতো কিছু ত্রুটিও রয়েছে। নির্দিষ্ট বাজার এবং পরিবেশের জন্য এটি অনুকূল করার জন্য আরও সূচক প্রবর্তন করা উচিত। সামগ্রিকভাবে বলতে গেলে, এটি একটি খুব ব্যবহারিক এবং দরকারী প্রযুক্তিগত সূচক কৌশল।
/*backtest start: 2022-11-24 00:00:00 end: 2023-11-30 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © antondmt //@version=5 strategy("Returns & Drawdowns Table", "R & DD", true, calc_on_every_tick = false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, process_orders_on_close = true) i_eq_to_dd = input.string("Compound Equity", "Mode", ["Simple Equity", "Compound Equity", "Drawdown"], group = "R & DD Table") i_precision = input.int(2, "Return Precision", group = "R & DD Table") i_headers_col = input.color(#D4D4D4, "Headers Color", group = "R & DD Table") i_headers_text_col = input.color(color.black, "Headers Text Color", group = "R & DD Table") i_pos_col = input.color(color.green, "Positive Color", group = "R & DD Table") i_neg_col = input.color(color.red, "Negative Color", group = "R & DD Table") i_zero_col = input.color(#DDDDDD, "Zero Color", group = "R & DD Table") i_cell_text_col = input.color(color.white, "Cell Text Color", group = "R & DD Table") // TIME { var month_times = array.new_int(0) // Array of all month times new_month = month(time) != month(time[1]) if(new_month or barstate.isfirst) array.push(month_times, time) var year_times = array.new_int(0) new_year = year(time) != year(time[1]) if (new_year or barstate.isfirst) array.push(year_times, time) //} // SIMPLE EQUITY CALCULATIONS { // Simple equity is strictly calculated from start to end of each month/year equity. There is no compound var monthly_simp_pnls = array.new_float(0) // Array of all monthly profits and losses var yearly_simp_pnls = array.new_float(0) if(i_eq_to_dd == "Simple Equity") var initial_monthly_equity = strategy.equity // Starting equity for each month cur_month_pnl = nz((strategy.equity - initial_monthly_equity) / initial_monthly_equity) // Current month's equity change if(new_month or barstate.isfirst) initial_monthly_equity := strategy.equity array.push(monthly_simp_pnls, cur_month_pnl) else array.set(monthly_simp_pnls, array.size(monthly_simp_pnls) - 1, cur_month_pnl) var initial_yearly_equity = strategy.equity cur_year_pnl = nz((strategy.equity - initial_yearly_equity) / initial_yearly_equity) if (new_year or barstate.isfirst) initial_yearly_equity := strategy.equity array.push(yearly_simp_pnls, cur_year_pnl) else array.set(yearly_simp_pnls, array.size(yearly_simp_pnls) - 1, cur_year_pnl) // } // COMPOUND EQUITY CALCULATIONS { // Compound equity is strictly calculated based on equity state from the beginning of time until the end of each month/year equity. It shows the exact equity movement through time var monthly_comp_pnls = array.new_float(0) // Array of all monthly profits and losses var yearly_comp_pnls = array.new_float(0) if(i_eq_to_dd == "Compound Equity") var initial_equity = strategy.equity cur_month_pnl = nz((strategy.equity - initial_equity) / initial_equity) // Current month's equity change if(new_month or barstate.isfirst) array.push(monthly_comp_pnls, cur_month_pnl) else array.set(monthly_comp_pnls, array.size(monthly_comp_pnls) - 1, cur_month_pnl) cur_year_pnl = nz((strategy.equity - initial_equity) / initial_equity) if (new_year or barstate.isfirst) array.push(yearly_comp_pnls, cur_year_pnl) else array.set(yearly_comp_pnls, array.size(yearly_comp_pnls) - 1, cur_year_pnl) // } // DRAWDOWN CALCULATIONS { // Drawdowns are calculated from highest equity to lowest trough for the month/year var monthly_dds = array.new_float(0) // Array of all monthly drawdowns var yearly_dds = array.new_float(0) if (i_eq_to_dd == "Drawdown") total_equity = strategy.equity - strategy.openprofit var cur_month_dd = 0.0 var m_ATH = total_equity // Monthly All-Time-High (ATH). It is reset each month m_ATH := math.max(total_equity, nz(m_ATH[1])) m_drawdown = -math.abs(total_equity / m_ATH * 100 - 100) / 100 // Drawdown at current bar if(m_drawdown < cur_month_dd) cur_month_dd := m_drawdown if(new_month or barstate.isfirst) cur_month_dd := 0.0 m_ATH := strategy.equity - strategy.openprofit array.push(monthly_dds, 0) else array.set(monthly_dds, array.size(monthly_dds) - 1, cur_month_dd) var cur_year_dd = 0.0 var y_ATH = total_equity y_ATH := math.max(total_equity, nz(y_ATH[1])) y_drawdown = -math.abs(total_equity / y_ATH * 100 - 100) / 100 if(y_drawdown < cur_year_dd) cur_year_dd := y_drawdown if (new_year or barstate.isfirst) cur_year_dd := 0.0 y_ATH := strategy.equity - strategy.openprofit array.push(yearly_dds, 0) else array.set(yearly_dds, array.size(yearly_dds) - 1, cur_year_dd) // } // TABLE LOGIC { var main_table = table(na) table.clear(main_table, 0, 0, 13, new_year ? array.size(year_times) - 1 : array.size(year_times)) main_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_times) + 1, border_width = 1) t_set_headers() => // Sets time headers of the table // Set month headers table.cell(main_table, 0, 0, "", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 1, 0, "Jan", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 2, 0, "Feb", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 3, 0, "Mar", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 4, 0, "Apr", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 5, 0, "May", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 6, 0, "Jun", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 7, 0, "Jul", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 8, 0, "Aug", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 9, 0, "Sep", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 10, 0, "Oct", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 11, 0, "Nov", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 12, 0, "Dec", text_color = i_headers_text_col, bgcolor = i_headers_col) table.cell(main_table, 13, 0, str.tostring(i_eq_to_dd), text_color = i_headers_text_col, bgcolor = i_headers_col) // Set year headers for i = 0 to array.size(year_times) - 1 table.cell(main_table, 0, i + 1, str.tostring(year(array.get(year_times, i))), text_color = i_headers_text_col, bgcolor = i_headers_col) t_set_months() => // Sets inner monthly data of the table display_array = switch i_eq_to_dd "Simple Equity" => monthly_simp_pnls "Compound Equity" => monthly_comp_pnls => monthly_dds for i = 0 to array.size(month_times) - 1 m_row = year(array.get(month_times, i)) - year(array.get(year_times, 0)) + 1 m_col = month(array.get(month_times, i)) m_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 30) : color.new(i_neg_col, transp = 30) table.cell(main_table, m_col, m_row, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = m_color, text_color = i_cell_text_col) t_set_years() => // Sets inner yearly data of the table display_array = switch i_eq_to_dd "Simple Equity" => yearly_simp_pnls "Compound Equity" => yearly_comp_pnls => yearly_dds for i = 0 to array.size(year_times) - 1 y_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 20) : color.new(i_neg_col, transp = 20) table.cell(main_table, 13, i + 1, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = y_color, text_color = i_cell_text_col) t_set_headers() t_set_months() t_set_years() // } // PLACE YOUR STRATEGY CODE HERE { // This is a sample code of a working strategy to show the table in action fastLength = input(12) slowlength = input(26) MACDLength = input(9) MACD = ta.ema(close, fastLength) - ta.ema(close, slowlength) aMACD = ta.ema(MACD, MACDLength) delta = MACD - aMACD if (ta.crossover(delta, 0)) strategy.entry("MacdLE", strategy.long, comment = "MacdLE") if (ta.crossunder(delta, 0)) strategy.entry("MacdSE", strategy.short, comment = "MacdSE") // }