Skrip Pine ini menawarkan kerangka kerja yang kuat untuk pengujian dan pengoptimalan strategi perdagangan grid di TradingView menggunakan fungsionalitas strategi. order (() untuk eksekusi otomatis dan backtesting.
Prinsip inti di balik strategi ini terletak pada konsep sistem grid dinamis yang terdiri dari tingkat tingkat harga yang memandu masuk dan keluar.
Secara khusus, posisi yang lebih panjang dimasukkan di dekat support dalam downtrends. Keuntungan ditangkap dengan meratakan posisi pada tingkat resistensi kunci dalam uptrends. Lebar grid dan rasio beradaptasi berdasarkan volatilitas pasar dan profil perdagangan.
Melalui mekanisme jaringan otomatis ini, strategi ini bertujuan untuk memanfaatkan peluang dari osilasi harga dua arah untuk mengumpulkan pengembalian positif yang konsisten.
Keuntungan utama dari strategi ini meliputi:
Grid Dinamis: Jenis grid yang dapat disesuaikan, pengaturan lebar dan resolusi pivot sesuai dengan dinamika pasar.
Aturan Smart Entry: Opsi pembelian yang fleksibel, konfigurasi ukuran posisi dan kontrol kuantitas pembelian berdasarkan tren.
Pintu Keluar Taktis: Pendekatan mengambil keuntungan yang dioptimalkan melalui ukuran posisi, pengaturan jumlah penjualan dan batas kerugian.
Pengaturan Serbaguna: Mode perdagangan spot atau margin untuk memenuhi berbagai kebutuhan perdagangan.
Konfigurasi Ekstensif: Disesuaikan dengan parameter seperti modal awal, komisi, tingkat margin dll.
Panel Informasi: Visualisasi intuitif dari data penting untuk meningkatkan keputusan.
Terlepas dari kemampuan, penggunaan dunia nyata membutuhkan kesadaran tentang:
Batas-batas dari backtest: Hasil masa lalu mungkin tidak dapat memprediksi kinerja masa depan dengan akurat.
Ketidakpastian Pasar: Harga dapat berfluktuasi secara tak terduga, mempengaruhi strategi.
Isu Pertukaran: Kegagalan dalam sistem broker dapat menyebabkan penundaan atau penolakan pesanan.
Kegagalan Sistem: Gangguan dalam proses pembuatan pesanan, komunikasi atau penerimaan.
Waktu Lag: Penundaan selama perdagangan langsung dapat menyebabkan hasil yang tidak terduga.
Risiko yang melekat ini harus dievaluasi sebelum terlibat dalam perdagangan otomatis langsung menggunakan strategi ini untuk memungkinkan eksekusi yang bijaksana dan terukur.
Optimasi yang mungkin termasuk:
Masukkan logika stop-loss untuk membatasi kerugian dalam gerakan ekstrim.
Melaksanakan pembelajaran mesin untuk mengkalibrasi pengaturan grid secara dinamis.
Mengintegrasikan indikator kuantitatif untuk perkiraan tren dan tingkat kunci untuk meningkatkan keputusan.
Memperkenalkan pengendalian risiko untuk mencegah risiko margin call.
Menganalisis rentang waktu untuk waktu yang efisien dari entri perdagangan dan keluar.
Peningkatan seperti itu dapat membuka kinerja yang lebih baik baik dalam backtest dan lingkungan hidup.
Skrip Pine ini memberikan dasar yang kuat untuk menguji dan menyempurnakan metodologi grid. Meskipun ada keterlambatan pelaksanaan, penerapan yang hati-hati dengan penyesuaian risiko yang tepat akan memungkinkan strategi ini berfungsi sebagai sistem perdagangan grid otomatis yang efektif di pasar keuangan.
/*backtest start: 2023-02-19 00:00:00 end: 2024-02-01 05:20: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/ // © AssassinsGrid // Embark on an automated grid-based trading journey with this Pine script tailored for backtesting in TradingView using strategy.orders(). // Whether you're a seasoned trader or new to the world of financial markets, this script is designed to enhance your trading experience across various assets. // It's essential to note that while powerful, this script may have a slightly delayed execution compared to the original Assassin's Grid due to the nature of strategy.orders() and strategy.close() functions, // which execute on the following bar after the price crosses the grid. // // Key Features: // // 📊 Dynamic Grid Configuration: Define the grid type, width, and pivot point resolution to adapt to market dynamics. // // 📈 Smart Buy Strategies: Choose from various buy types, set quantities, and control the number of buy positions based on market trends. // // 💹 Strategic Selling: Optimize sell strategies with flexible options, including setting quantities, controlling sell positions, and defining loss thresholds. // // 🌐 Versatile Trading: Select between spot and margin trading modes, offering flexibility for diverse trading preferences. // // ⚙️ Detailed Configuration: Fine-tune your strategy with parameters like initial capital, commission values, margin rates, and more. // // 📊 Informative Chart Elements: Visualize critical information with adjustable labels, table size, grid visibility, and an insightful information panel. // // Conclusion: // // Whether you're a seasoned trader or a trading enthusiast exploring markets beyond cryptocurrencies, this Pine script provides a robust framework for testing and refining your strategies. // While powerful, be aware that the execution may have a slight delay compared to the original Assassin's Grid. // Dive into the dynamic world of grid-based trading, explore various configurations, and refine your approach across a spectrum of financial assets. Happy trading! 🚀💰 //@version=5 strategy("Assassin's Grid B", shorttitle = "AAGG📈", overlay = true, max_labels_count = 500, initial_capital = 10000, default_qty_value = 0, process_orders_on_close = true) // INPUTS // Grid parameters WOption = input.string('Geometric (% Fall)', 'Width Type', ['Arithmetic (Price)', 'Geometric (% Sell)', 'Geometric (% Fall)'], group = "GRID", tooltip = "Select the type of width for the grid:\n\n- Arithmetic (Price): Fixed width in price units, maintaining constant separation on the chart.\n\n- Geometric (% Sell): Width based on a percentage of the sell price, dynamically adjusting grid lines. (Typically between 5-15%)\n\n- Geometric (% Fall): Width based on a percentage of potential market decline from the last sale, helping visualize potential drops. (Usually between 40-80%)") Width = input.float(75, 'Width Parameter', minval = 0, step = 0.5, group = "GRID", tooltip = "Set the width parameter for the grid. Larger values result in wider grid lines.") ppPeriod = input.string('4W', 'Pivot Point Resolution', group = "GRID", tooltip = "Set the resolution for the Pivot Point. Type a timeframe that suits your trading style: 'H, D, W, M'") MARes = input.timeframe('D', 'EMA Resolution', group = "GRID", tooltip = "Set the resolution for the Exponential Moving Average (EMA). Choose a timeframe that suits your analysis.") MALength = input.int(100, 'MA Length', minval = 1, group = "GRID", tooltip = "Set the length for the Moving Average (MA). This affects the responsiveness of the MA to price changes.") // Buy BuyType = input.string('Cash / n Buys', 'Buy Type', ['Contracts', 'Cash', '% Cash', 'Cash / n Buys', 'Cash / n Buys +'], group = "BUY", tooltip = "Select the type of buy: \n- Contracts: Specify the number of contracts to buy. \n- Cash: Specify the amount of cash to invest. \n- % Cash: Specify the percentage of available cash to invest. \n- Cash / n Buys: Distribute available cash equally across n buy positions. \n- Cash / n Buys +: Similar to Cash / n Buys, but the quantity on each buy increases proportionally with the buy number.") BuyQ = input.float(10.0, 'Contracts / Cash / % Cash', minval = 0, group = "BUY", tooltip = "Set the quantity for buy. For 'Contracts' mode, it represents the number of contracts to buy. For 'Cash' and '% Cash' modes, it represents the amount to invest or the percentage of cash to invest, respectively.") NBuysUp = input.int(4, 'N Buys over MA', minval = 1, maxval = 30, group = "BUY", tooltip = "Set the maximum number of buy positions allowed above the Moving Average (MA). This helps control the number of buys in an uptrend.") NBuysDown = input.int(5, 'N Buys under MA (Max.)', minval = 1, maxval = 30, group = "BUY", tooltip = "Set the maximum number of buy positions allowed below the Moving Average (MA). This helps control the number of buys in a downtrend.") LastXtrades = input.int(2, 'Buy all in last Trades', minval = 0, maxval = 10, group = "BUY", tooltip = "Set the number of the most recent buy trades to consider for making a buy decision. For the '% Cash' option only, this setting enables buying all available cash in the last specified number of trades.") // Sel SellType = input.string('Position / n Sells +', 'Sell Type', ['Contracts', 'Cash', '% Position', 'Position / n Sells', 'Position / n Sells +'], group = "SELL", tooltip = "Select the type of sell: \n- Contracts: Specify the number of contracts to sell. \n- Cash: Specify the amount of cash to disinvest. \n- % Position: Specify the percentage of the position to sell. \n- Position / n Sells: Distribute the position equally across n sell positions. \n- Position / n Sells +: Similar to Position / n Sells, but the quantity on each sell increases proportionally with the sell number.") SellQ = input.float(5.0, 'Contracts / Cash / % Position', minval = 0, group = "SELL", tooltip = "Set the quantity for sell. For 'Contracts' mode, it represents the number of contracts to sell. For 'Cash' and '% Position' modes, it represents the amount to disinvest or the percentage of the position to sell, respectively.") NSellsUp = input.int(20, 'N Sells over MA (Max.)', minval = 1, maxval = 30, group = "SELL", tooltip = "Set the maximum number of sell positions allowed above the Moving Average (MA). This helps control the number of sells in an uptrend.") NSellsDown = input.int(4, 'N Sells under MA', minval = 1, maxval = 30, group = "SELL", tooltip = "Set the maximum number of sell positions allowed below the Moving Average (MA). This helps control the number of sells in a downtrend.") LossAllowed = input.string('Never', 'Loss Allowed', ['Never', 'Last buy', 'Always'], group = "SELL", tooltip = "Set the loss allowed criteria: \n- Never: No loss allowed for selling. \n- Last buy: Allow selling if the current price is above the price of the last buy. \n- Always: Allow selling at any price.") // Trading TradingType = input.string('Spot', 'Trading Type', ['Spot', 'Margin'], group = "TRADING", tooltip = "Select the type of trading: \n- Spot: Regular trading without margin. \n- Margin: Trading with margin, allowing for leveraged positions.") InitialContracts = input.float(10.0, '% Initial Capital 1st Trade', minval = 1, maxval = 100, group = "TRADING", tooltip = "Set the percentage of the initial capital to be used for the first trade. This determines the position size for the first trade.") / 100 CommissionValue = input.float(0.1, '% Commission Value', minval = 0, maxval = 100, step = 0.1, group = "TRADING", tooltip = "Set the percentage of the trade value to be considered as a commission. This is deducted from the trading capital.") / 100 MarginRate = input.float(1.0, '% Margin Rate', minval = 0, maxval = 100, step = 0.5, group = "TRADING", tooltip = "Set the percentage of margin rate to be applied. This is relevant only in margin trading scenarios.") / 100 StartDate = timestamp('01 Jan 1970 00:00 +000') testPeriodStart = input(StartDate, 'Start of Trading', group = "TRADING", tooltip = "Set the start date for trading. The strategy will start evaluating trades from this date onwards.") TableSizeInput = input.string('Small', 'Table Size', ['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group = "PLOTTING", tooltip = "Set the size of the information table. Choose a size that suits your preference.") ShowGrid = input(true, 'Level Grid', group = "PLOTTING", tooltip = "Show or hide the level grid on the chart. The grid represents price levels.") ShowPanel = input(false, 'Information Panel', group = "PLOTTING", tooltip = "Show or hide the information panel on the chart. The panel displays key information about the strategy and current market conditions.") ShowLiquidationPrice = input(false, 'Liquidation Price', group = "PLOTTING", tooltip = "Show or hide the liquidation price on the chart. The liquidation price is the level at which liquidation may occur, if applicable.") // VARIABLES // Grid levels on buys var float _ldown = na bool _pb = false bool _buy = false // Grid levels on sells var float _lup = na bool _ps = false bool _sell = false // First Buy CloseFirstBar = ta.valuewhen(bar_index == 0, open, 0) TimeFirstBar = ta.valuewhen(bar_index == 0, time, 0) CloseStart = ta.valuewhen(time <= testPeriodStart, open, 0) FirstClose = testPeriodStart > TimeFirstBar ? CloseStart : CloseFirstBar TimeFirstClose = testPeriodStart > TimeFirstBar ? testPeriodStart : TimeFirstBar // Buy and Sell prices var float FinalBuyPrice = na var float FinalSellPrice = na var float FinalOpenPrice = na var float BuyLimitPrice = na var float SellLimitPrice = na // Number of trades var int nBuys = na nBuys := nz(nBuys[1]) var int nSells = na nSells := nz(nSells[1]) var int NBuys = NBuysDown var int NSells = NSellsDown // Quantities var float BuyQuantity = 0 var float BuyAmount = 0 var float SellQuantity = 0 var float SellAmount = 0 var float Commission = 0 var float Gains = 0 var float Losses = 0 // Position calculation var float PositionCash = 0 var float PositionSize = 0 var int BarIndex = 0 // Average Price Calculation var float AvgPrice = 0 var float hl2Bar = 0 // Backtest information var float Balance = 500000 var float Equity = 0 var float RealizedPnL = 0 var float PRealizedPnL = 0 var float Floating = 0 var float PFloating = 0 var float URealizedPnL = 0 var float PURealizedPnL = 0 var float Cash = Balance var float Margin = 0 var float BuyAndHold = 0 var float PBuyAndHold = 0 var float CLeverage = 0 var float LiquidationPrice = 0 var bool Liquidation = false var float ProfitFactor = 0 var int TradingTime = 0 // Fibonacci Pivots level calculation var float PP = open // Information panel label labelBalance = na // Analyzing when the period changes bool PeriodChange = false // Grid with arrays aDown = array.new_float(30) aUp = array.new_float(30) aBuy = array.new_bool(30) aSell = array.new_bool(30) // Labels size fTextSize(_SizeInput)=> if _SizeInput == 'Auto' size.auto else if _SizeInput == 'Tiny' size.tiny else if _SizeInput == 'Small' size.small else if _SizeInput == 'Normal' size.normal else if _SizeInput == 'Normal' size.normal else if _SizeInput == 'Large' size.large else if _SizeInput == 'Huge' size.huge // Variable reference var float MaxFinalOpenPrice = FirstClose // Value of the MA var float sMAValue = na // GRID // Function to calculate the Width fWidth(_Width) => // If price is constant if WOption == 'Arithmetic (Price)' _Width // If price is the Max % of the next Sell else if WOption == 'Geometric (% Sell)' MaxFinalOpenPrice * (_Width / 100) // If price is a part of the % of the maximum fall else if WOption == 'Geometric (% Fall)' MaxFinalOpenPrice / NBuysDown * (_Width / 100) // Origin from Rounded Pivot Points or last Sell fDownGrid(_GridWidth) => if na(FinalOpenPrice) FirstClose else if FinalSellPrice <= PP if PositionSize > 0 if na(FinalBuyPrice) if WOption == 'Arithmetic (Price)' (math.floor(FinalSellPrice / _GridWidth) * _GridWidth) - _GridWidth else FinalSellPrice - _GridWidth else FinalBuyPrice - _GridWidth else if PositionSize == 0 if WOption == 'Arithmetic (Price)' (math.floor(PP / _GridWidth) * _GridWidth) - _GridWidth else PP else if na(FinalBuyPrice) if WOption == 'Arithmetic (Price)' (math.floor(PP / _GridWidth) * _GridWidth) - _GridWidth else if (FinalSellPrice - _GridWidth) > PP PP else (FinalSellPrice - _GridWidth) else FinalBuyPrice - _GridWidth // Origin for sells from Rounded Position Price fUpGrid(_GridWidth) => if na(FinalSellPrice) if LossAllowed == 'Never' if WOption == 'Arithmetic (Price)' math.ceil(math.max(AvgPrice, (FinalBuyPrice + _GridWidth)) / _GridWidth) * _GridWidth else math.max(AvgPrice, (FinalBuyPrice + _GridWidth)) else if LossAllowed == 'Last buy' if nBuys == NBuys FinalBuyPrice + _GridWidth else if WOption == 'Arithmetic (Price)' math.ceil(math.max(AvgPrice, (FinalBuyPrice + _GridWidth)) / _GridWidth) * _GridWidth else math.max(AvgPrice, (FinalBuyPrice + _GridWidth)) else if LossAllowed == 'Always' FinalBuyPrice + _GridWidth else FinalSellPrice + _GridWidth // FUNCTIONS // Function to sum factorial fSum(_Num)=> (math.pow(_Num, 2) + _Num) / 2 // Function when "Cash / n Buys" or "Position / n Sells" fCaPo_N(_N, _n) => 1 / (_N - nz(_n)) // Function when "Cash / n Buys +" or "Position / n Sells +" fCaPo_Nplus(_OnSells, _N, _n) => if TradingType == 'Spot' or _OnSells == 1 (nz(_n)+1) / (fSum(_N) - fSum(nz(_n))) else (nz(_n)+1) / fSum(_N) // One of the correct ways to use security f_security(_sym, _res, _src, _rep) => request.security(_sym, _res, _src[not _rep and barstate.isrealtime ? 1 : 0])[_rep or barstate.isrealtime ? 0 : 1] // Pivot points PP := f_security(syminfo.tickerid, ppPeriod, hlc3, false) // Moving Average MA = ta.ema(close, MALength) sMA = f_security(syminfo.tickerid, MARes, MA, false) // Analyzing when the period changes PeriodChange := ta.change(time(ppPeriod)) != 0 // On Bullish trend, less Number of Buys and more amounts per trade; // on Bearish more Number of Buys and less amounts per trade // Max. number of buys NBuys := if (BuyType == "Cash / n Buys" or BuyType == "Cash / n Buys +") if BuyLimitPrice >= sMAValue NBuysUp else NBuysDown else NBuysDown // On Bullish trend, more Number of Sells and less amounts per trade; // on Bearish less Number of Sells and more amounts per trade // Max. number of sells NSells := if (SellType == "Position / n Sells" or SellType == "Position / n Sells +") if SellLimitPrice < sMAValue NSellsDown else NSellsUp else NSellsUp // TRADING // Start of trading if time >= TimeFirstClose // Final Trade Price, Average Price & Backtest for _i = 1 to math.max(NBuys, NSells) // Grid on Buys array.insert(aDown, _i, fDownGrid(fWidth(Width))) // Crossing between price and levels of grid array.insert(aBuy, _i, (low <= array.get(aDown, _i) or open <= array.get(aDown, _i)) and nBuys <= NBuys-1) // Grid on Sells array.insert(aUp, _i, fUpGrid(fWidth(Width))) // Crossing between price and levels of grid array.insert(aSell, _i, (high >= array.get(aUp, _i) or open >= array.get(aUp, _i)) and nSells <= NSells-1) strategy.initial_capital = 50000 // Financial Data RealizedPnL := Balance - strategy.initial_capital PRealizedPnL := (RealizedPnL / strategy.initial_capital) * 100 Floating := ((close - AvgPrice) / AvgPrice) * PositionSize * AvgPrice PFloating := (Floating / Balance) * 100 URealizedPnL := RealizedPnL + Floating PURealizedPnL := (URealizedPnL / strategy.initial_capital) * 100 Equity := Balance + Floating Margin := TradingType == 'Spot' ? 0 : (PositionSize * AvgPrice * MarginRate) Cash := TradingType == 'Spot' ? math.max(0, Balance - (PositionSize * AvgPrice)) : math.max(0, Balance - Margin) BuyAndHold := ((close - FirstClose) / FirstClose) * strategy.initial_capital PBuyAndHold := (BuyAndHold / strategy.initial_capital) * 100 CLeverage := (PositionSize * AvgPrice) / Balance LiquidationPrice := TradingType == 'Spot' ? 0 : AvgPrice - ((Balance - (Margin * 1)) / PositionSize) Liquidation := (ta.valuewhen(LiquidationPrice >= low, time , 0) <= timenow) ProfitFactor := Gains / Losses TradingTime := timenow - TimeFirstClose // Quantities to buy according to inputs if BuyType == "Contracts" if na(FinalOpenPrice) BuyQuantity := ((Cash * InitialContracts) / FirstClose) else BuyQuantity := math.min((Cash / AvgPrice), BuyQ) else if BuyType == "Cash" if na(FinalOpenPrice) BuyQuantity := (Cash * InitialContracts) else BuyQuantity := math.min(Cash, BuyQ) else if BuyType == "% Cash" if na(FinalOpenPrice) BuyQuantity := (Cash * InitialContracts) else if nBuys >= NBuys - LastXtrades BuyQ := (1 / (NBuys - nz(nBuys))) * 100 BuyQuantity := math.min(Cash, (BuyQ / 100) * Cash) else if BuyType == "Cash / n Buys" if na(FinalOpenPrice) BuyQuantity := (Cash * InitialContracts) else BuyQuantity := math.min(Cash, fCaPo_N(NBuys, nBuys) * Cash) else if BuyType == "Cash / n Buys +" if na(FinalOpenPrice) BuyQuantity := (Cash * InitialContracts) else BuyQuantity := math.min(Cash, fCaPo_Nplus(0, NBuys, nBuys) * Cash) // Quantities to sell according to inputs if SellType == "Contracts" SellQuantity := math.min(PositionSize, SellQ) else if SellType == "Cash" SellQuantity := math.min((PositionSize * AvgPrice), SellQ) else if SellType == "% Position" SellQuantity := math.min(PositionSize, (SellQ / 100) * PositionSize) else if SellType == "Position / n Sells" SellQuantity := math.min(PositionSize, fCaPo_N(NSells, nSells) * PositionSize) else if SellType == "Position / n Sells +" SellQuantity := math.min(PositionSize, fCaPo_Nplus(1, NSells, nSells) * PositionSize) // First buy limit order from every change of the period if (PP != PP[1]) and nz(nBuys) == 0 and not nz(nSells) == 0 and not na(nBuys) and not na(fDownGrid(fWidth(Width))) // Value of the MA sMAValue := sMA // Buy price of the limit order BuyLimitPrice := fDownGrid(fWidth(Width)) // Buying at better Price if array.get(aBuy, _i) and BuyQuantity > 0 // Value of the MA sMAValue := sMA // Price of buy orders and resetting sales FinalBuyPrice := math.min(open, array.get(aDown, _i)) FinalSellPrice := na FinalOpenPrice := FinalBuyPrice // Number of buys and resetting sales nBuys += 1 nSells := na // Redefining buy quantity if BuyType == "Contracts" BuyAmount := BuyQuantity else BuyAmount := (BuyQuantity / FinalBuyPrice) // Calculating the priority and secondary price average PositionCash += FinalBuyPrice * BuyAmount PositionSize += BuyAmount AvgPrice := PositionCash / PositionSize // Calculating net profit Balance -= (BuyAmount * FinalBuyPrice * CommissionValue) // Comissions losses Losses += (BuyAmount * FinalBuyPrice * CommissionValue) // Fees paid Commission += (BuyAmount * FinalBuyPrice * CommissionValue) // Avoiding overlap BarIndex := bar_index // Variable reference MaxFinalOpenPrice := math.max(FinalBuyPrice, nz(MaxFinalOpenPrice)) // Buy & Sell price of the limit orders if nBuys <= NBuys-1 BuyLimitPrice := FinalBuyPrice - fWidth(Width) else BuyLimitPrice := na SellLimitPrice := fUpGrid(fWidth(Width)) // Strategy orders strategy.order("Buy", strategy.long, BuyAmount) // Buy shapes //string BuyText = str.tostring(BuyAmount,'#.####') + "\n" + str.tostring(((BuyAmount * FinalBuyPrice) / Cash) * 100, '#.##') + "%" //c_BuyGrad = color.from_gradient(((NBuys - nBuys) / NBuys) * 100, 1, 100, color.lime, color.blue) //label.new(bar_index, FinalBuyPrice, BuyText, textcolor = color.new(color.white, 50), color = c_BuyGrad, style = label.style_diamond, size = fTextSize(LabelSizeInput)) // Selling at better Price else if array.get(aSell, _i) and SellQuantity > 0 and BarIndex != bar_index // Value of the MA sMAValue := sMA // Price of sale orders and resetting buys FinalBuyPrice := na FinalSellPrice := math.max(open, array.get(aUp, _i)) FinalOpenPrice := FinalSellPrice // Number of sales and resetting buys nBuys := na nSells += 1 // Redefining sell quantity if SellType == "Cash" SellAmount := SellQuantity / FinalSellPrice else SellAmount := SellQuantity // Calculating the priority and resetting secondary price average PositionCash -= AvgPrice * SellAmount PositionSize -= SellAmount // Calculating net profit Balance += (FinalSellPrice - AvgPrice) * SellAmount Balance -= (SellAmount * FinalSellPrice * CommissionValue) // Gains and Losses if FinalSellPrice >= AvgPrice Gains += (FinalSellPrice - AvgPrice) * SellAmount else Losses += (AvgPrice - FinalSellPrice) * SellAmount // Comission losses Losses += (SellAmount * FinalSellPrice * CommissionValue) // Fees paid Commission += (SellAmount * FinalSellPrice * CommissionValue) // Variable reference MaxFinalOpenPrice := FinalSellPrice // Buy & Sell price of the limit orders BuyLimitPrice := fDownGrid(fWidth(Width)) if nSells <= NSells-1 SellLimitPrice := FinalSellPrice + fWidth(Width) else SellLimitPrice := na // Strategy orders strategy.close("Buy", comment = 'Sell', qty = SellAmount) // Sell shapes //string SellText = str.tostring(SellAmount,'#.####') + "\n" + str.tostring((SellAmount / (PositionSize + SellAmount)) * 100, '#.##') + "%" //c_SellGrad = color.from_gradient(((NSells - nSells) / NSells) * 100, 1, 100, color.yellow, color.red) //label.new(bar_index, FinalSellPrice, SellText, textcolor = color.new(color.white, 50), color = c_SellGrad, style = label.style_diamond, size = fTextSize(LabelSizeInput)) // PLOTTING // Price of the limit orders bool LastBar = (time >= timenow - (timeframe.multiplier * 1000 * 60)) plotshape(ShowGrid ? BuyLimitPrice : na, "Buy level", shape.cross, location.absolute, color.new(color.blue, 30), size = size.auto) plotshape(ShowGrid ? SellLimitPrice : na, "Sell level", shape.cross, location.absolute, color.new(color.red, 30), size = size.auto) // Table var InfoPanel = table.new(position.middle_left, 2, 12, na, color.new(color.white, 80), 1, color.new(color.white, 80), 1) ftable(_table_id, _column, _row, _text, _bgcolor) => table.cell(_table_id, _column, _row, _text, 0, 0, _bgcolor, text.align_left, text.align_center, fTextSize(TableSizeInput), na) tfString(int timeInMs) => // @function Produces a string corresponding to the input time in days, hours, and minutes. // @param (series int) A time value in milliseconds to be converted to a string variable. // @returns (string) A string variable reflecting the amount of time from the input time. float s = timeInMs / 1000 float m = s / 60 float h = m / 60 float d = h / 24 float mo = d / 30.416 int tm = math.floor(m % 60) int th = math.floor(h % 24) int td = math.floor(d % 30.416) int tmo = math.floor(mo % 12) int ys = math.floor(d / 365) string result = switch d == 30 and th == 10 and tm == 30 => "1M" d == 7 and th == 0 and tm == 0 => "1W" => string yStr = ys ? str.tostring(ys) + "Y " : "" string moStr = tmo ? str.tostring(tmo) + "M " : "" string dStr = td ? str.tostring(td) + "D " : "" string hStr = th ? str.tostring(th) + "H " : "" string mStr = tm ? str.tostring(tm) + "min" : "" yStr + moStr + dStr + hStr + mStr if ShowPanel ftable(InfoPanel, 0, 0, 'Equity: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 1, 'Position: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 2, 'Cash: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 3, 'Margin: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 4, 'Current Leverage: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 5, 'Commission Paid: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 6, 'Floating: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 7, 'Realized PnL: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 8, 'Unrealized PnL: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 9, 'Buy n Hold: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 10, 'Profit Factor: ' , color.new(color.white, 50)) ftable(InfoPanel, 0, 11, 'Time of Trading: ' , color.new(color.white, 50)) ftable(InfoPanel, 1, 0, Liquidation ? 'Liquidation' : str.tostring(Equity, '#.####') + ' ' + syminfo.currency , Liquidation ? color.red : color.green) ftable(InfoPanel, 1, 1, str.tostring(PositionSize, '#.####') + ' ' + syminfo.basecurrency , color.green) ftable(InfoPanel, 1, 2, str.tostring(Cash, '#.####') + ' ' + syminfo.currency , color.green) ftable(InfoPanel, 1, 3, str.tostring(Margin, '#.####') + ' ' + syminfo.currency , color.green) ftable(InfoPanel, 1, 4, TradingType == 'Spot' ? 'Spot' : str.tostring(CLeverage, '#.##') + 'x' , color.green) ftable(InfoPanel, 1, 5, str.tostring(Commission, '#.####') + ' ' + syminfo.currency , Commission == 0 ? color.green : color.red) ftable(InfoPanel, 1, 6, str.tostring(PFloating, '#.##') + ' %' , PFloating >= 0 ? color.green : color.red) ftable(InfoPanel, 1, 7, str.tostring(PRealizedPnL, '#.##') + ' %' , PRealizedPnL >= 0 ? color.green : color.red) ftable(InfoPanel, 1, 8, str.tostring(PURealizedPnL, '#.##') + ' %' , PURealizedPnL >= 0 ? color.green : color.red) ftable(InfoPanel, 1, 9, str.tostring(PBuyAndHold, '#.##') + ' %' , PBuyAndHold >= 0 ? color.green : color.red) ftable(InfoPanel, 1, 10, str.tostring(ProfitFactor, '#.##') , ProfitFactor >= 1 ? color.green : color.red) ftable(InfoPanel, 1, 11, tfString(TradingTime) , color.new(color.white, 50)) // Plotting pivot points plot(PP, title = "PP", style = plot.style_stepline, color = color.silver, linewidth = 1) // Plotting the average price plotshape(barstate.isrealtime and ta.change(AvgPrice) != 0 ? AvgPrice : na, "AvgPricepr", shape.diamond, location.absolute, color.new(color.yellow, 10), size = size.tiny) plotshape( ta.change(AvgPrice[1]) != 0 ? AvgPrice[1] : na, "AvgPricep", shape.diamond, location.absolute, color.new(color.yellow, 40), size = size.tiny) plotshape(TimeFirstClose == time ? FirstClose : na, "FirstClose", shape.diamond, location.absolute, color.new(color.yellow, 40), size = size.tiny) // Plotting the moving average plot((BuyType == "Cash / n Buys" or BuyType == "Cash / n Buys +") and NBuysUp != NBuysDown ? sMA : na, title = "Moving Average Buys", color = color.new(color.blue, 50), linewidth = 2) plot((SellType == "Position / n Sells" or SellType == "Position / n Sells +") and NSellsUp != NSellsDown ? sMA : na, title = "Moving Average Sells", color = color.new(color.red, 50), linewidth = 2) // Plotting the liquidation price plot(ShowLiquidationPrice and LiquidationPrice > 0 ? LiquidationPrice : na, "Liquidation Price", Liquidation ? color.new(color.red, 30) : color.new(color.lime, 30), 2) barcolor(Liquidation ? color.red : na) //⚠️ IMPORTANT NOTICE: LIVE ALGORITHMIC TRADING RISKS //🚨 Engaging in live algorithmic trading poses several inherent risks that you should be aware of: //📉 Backtesting Limitations: Historical performance (backtesting) may not accurately predict future results. Past success does not guarantee future profits. //🌐 Market Unpredictability: The market is dynamic and may fail or exhibit unexpected behavior, impacting your trading strategies. //🛑 Broker Infrastructure Issues: Your broker's infrastructure may experience failures, execution delays, or reject your orders, affecting real-time trading. //🤖 System Failures: The systems used for order generation, communication with your broker, and result reception might fail, disrupting the trading process. //⏳ Time Lag Challenges: Time lags during live trading can lead to unexpected behavior and outcomes, requiring careful consideration. //🤝 Third-Party System Risks: Systems of third parties, including service providers, brokers, and securities markets, may fail or malfunction, impacting overall functionality. //💡 It's crucial to acknowledge and understand these risks before embarking on live algorithmic trading. Stay informed, be cautious, and adapt your strategies accordingly. // Happy and safe trading! 🚀💰