SMMD V2.51 SMOD
stableDescription
Modification of SMMD V2.51.
-FIX budget value option
Additional method to set the budget balance. The value is NOT percentage but the fiat/coin amount you want to allocate for the bot. This option is not compounding profit into budget balance. If your wallet balance < the value you entered then bot will use the wallet amount.
Budget Isolation
Rather than using ratio between current open position and max open position to reduce/SL, this option will use the ratio of working balance to budget/wallet balance. Depends on the % of size reduction setting. For me it is NOT A GOOD IDEA if you have PERCENTAGE budget calculation and size reduction 100%.
FIX : working balance : budget balance >= 1
PERCENTAGE: working balance : wallet balance >= 1
Options to disable trading details in logs
Now you have option to see or not to see those trading details in the log.
Cloud version friendly
Deleting leverage and contract value entry and read from the setting in cloud version.
Binance Notional Value Mod
Binance has minimum $5 notional value for theirs Futures. It means, the $ value of your order should not less than $5. I have add a mod that when the size calculation result is below that amount then bot will use the minimum size according to the notional value rule.
May the profits be with you!
More questions ? Find me in Haasonline Discord.
If you would like to buy me a cup of coffee or diamond:
ENS: smokyho.eth
Lightning: [email protected]
HaasScript
-- Modified version of Phsai's amazing Simple Market Maker that intended
-- ONLY FOR BINANCE FUTURES USDT/COIN HEDGE MODE ENABLED
--
----------------------------------------------------------------------------
--Log('Update 7')
EnableHighSpeedUpdates(true)
HideOrderSettings()
HideTradeAmountSettings()
-- inputs
InputGroupHeader('Bot Settings')
local okLong = Input('01. Allow Long', false, 'Allow bot to open Long')
local okShort = Input('02. Allow Short', false, 'Allow bot to open Short')
local wtfStop = Input('03. Stop at no position', false, 'Deactivate bot when there is no open position')
local FStop = Input('04. Force Close Position', false, 'Closes open positions')
local showInfo = Input('05. Details in Log', true, 'Show detail information in logs about the bot condition')
InputGroupHeader('Backtest Settings')
local wtfBal = Input('01. Deactivate on Over Budget', false, 'Deactivate when Working Balance > Budget Balance')
local wtfRatio = Input('02. Deactivate on specific Bal Ratio', false, 'Deactivate when Bal Ratio hit trigger below')
local wtfRatioV = Input('02A. Bal Ratio Trigger', 0.5)
local wtfAmount = Input('03. Deactivate on Over Size', false, 'Deactivate when one of position size > Max Open')
local wtfWallet = Input('04. Deactivate on Wallet = 0', false, 'Why bother continuing the backtest?')
local testWallet = Input('05. Use Custom Wallet', false, 'ONLY FOR BACKTEST. DO NOT USE WHEN ON RUNNING BOT')
local testWalletAmount = Input('05A. Custom Wallet Balance', 0, 'ONLY FOR BACKTEST. DO NOT USE WHEN ON RUNNING BOT')
InputGroupHeader('LONG and SHORT Ratio')
local enableRatio = Input('01. Enable ratios', true)
local longRatio = Input('01A. Long ratio', 4, 'Long ratio, compared to short, default is 1, must be greater than 0')
local shortRatio = Input('01B. Short ratio', 1, 'Short ratio, compared to long, default is 1, must be greater than 0')
InputGroupHeader('Budget & Safety')
local maxSizeM = Input('01. Max. Open '..AmountLabel(), 0, 'Maximum open contracts at any given time also as minimum for Dynamic Max Open. After exceeding this value, the bot will dump a portion of position at a loss.')
local autoMax = Input('01A. Dynamic Max Open', true, 'Dynamically change max open contracts based on available balanca')
local leverage = GetLeverage() --Input('01B. Leverage', 50, 'MUST be filled even if using Cross Margin. Important for trading budget.')
local contVal = ContractValue() --Input('01C. COIN-M Value', 10, 'ONLY if bot trading on INVERSE Futures then enter the Contract Value. Ignore if trade on USDT')
local budgetTypes = {'Fix', 'Percentage'}
local budgetType = InputOptions('01C.Budget Calculation', 'Fix', budgetTypes, 'Fix = Static budget balance. Profit not compounding. Percentage = Dynamic following wallet balance. Profit compounding')
local budgetIsolation = Input('01D. Budget Isolation', false, 'If activated reduction is when working balance >= budget balance. Else if position size > max size')
local maxBudget = Input('01E. Balance Budget', 0, 'How much from wallet balance allocated for this bot. If % then 0.5 is 50% of wallet balance. If Fix then the fiat/coin amount.')
local maxOpen = Input('01F. Position Budget', 0.1, 'How much from the Balance Budget allocated for opening positions. 0.1 is 10% of Balance Budget')
local reduceSize = Input('02. Size Reduction %', 21, 'How big of a portion the bot will dump once reduction condition triggered')
local reduceOrderType = InputOrderType('03. Reduction Order Type', MarketOrderType, 'The order type for size reduction dump')
local noReduce = Input('04. Disable Size Reduction', false, 'Are you sure?')
InputGroupHeader('Grid Settings')
local slotCount = Input('01. Slot Count', 1, 'How many orders are constantly kept open on both long and short side')
local slotSizeM = Input('02. Slot Size', 0.001, 'Minimum trade amount per slot if Dynamic Slot Size activated or fix value if bot dynamic')
local slotMultiplier = Input('02A. Slot Size Multiplier', 2, 'Trade amount multipler per slot')
local autoSlot = Input('03A. Dynamic Slot Size', true, 'DSSize - Dynamically change slot size based on budget')
local slotBudget = Input('03B. Max. Open Divider', 377, 'DSSize feature - Divide max open position with this value to get new Slot Size. Example Max Open is 1000 and devider is 200 then slot size is 5')
local slotSpreadL = Input('04A. Slot Spread Long %', 0.4, 'Percentage for longs based spread value between each slot')
local slotSpreadS = Input('04B. Slot Spread Short %', 0.6, 'Percentage for shorts based spread value between each slot')
local slotSpreadM = Input('04C. Slot Spread Multiplier', 1, 'Order Spread Multipler per slot')
local incLVLOneShort = Input('04C. LVL 1 inc Short size at %', 10, 'Level 1 increase for shorts in Percentage')
local slotCancel = Input('05. Cancel Distance %', 0.236, 'How much price can move to the opposite direction before orders are cancelled and replaced')
local minSpread = Input('06. Minimum Spread %', 0.236, 'Minimum spread percentage between the first long and short entries. This setting only works when bot has no position.')
local dynamicSpreadInterval = InputInterval("07. Dynamic Spread Interval", 15)
local dynamicSpreadLookback = Input("07A. Dynamic Spread Lookback", 3)
InputGroupHeader('Profit Settings')
local takeProfitL = Input('01. LONG Take-Profit %', 0.236, 'Fixed take-profit value, based on price change')
local takeProfitS = Input('02. SHORT Take-Profit %', 0.236, 'Fixed take-profit value, based on price change')
local tpOrderType = InputOrderType('03. TP Order Type', MakerOrCancelOrderType, 'The order type for take-profit')
local preplacedTP = Input('04. Pre-Place TP', false, 'Place Exit Position as soon as has open position')
-- price and data
local getMarket = PriceMarket()
local isBinance = StringContains(getMarket, 'BINANCE')
local cp = CurrentPrice()
local c = ClosePrices()
local SRCounter = Load('SRCounter', 0)
-- positions
local hedge_longPosId = Load('hedge_longPosId', NewGuid())
local hedge_shortPosId = Load('hedge_shortPosId', NewGuid())
local dir_l = GetPositionDirection(hedge_longPosId)
local aep_l = GetPositionEnterPrice(hedge_longPosId)
local pamt_l = GetPositionAmount(hedge_longPosId)
local delta_l = pamt_l > 0 and (cp.close - aep_l) / aep_l * 100 or 0
local proi_l = delta_l * leverage
local dir_s = GetPositionDirection(hedge_shortPosId)
local aep_s = GetPositionEnterPrice(hedge_shortPosId)
local pamt_s = GetPositionAmount(hedge_shortPosId)
local delta_s = pamt_s > 0 and (aep_s - cp.close) / aep_s * 100 or 0
local proi_s = delta_s * leverage
if showInfo then
Log('LONG position ROI: '..Round(proi_l, 2)..'%')
Log('SHORT position ROI: '..Round(proi_s, 2)..'%')
end
-- not using spread if we have a position
-- if pamt_l > 0 or pamt_s > 0 then
-- minSpread = 0
-- end
-- manage position ids
if pamt_l == 0 and IsPositionClosed(hedge_longPosId) then
if IsAnyOrderOpen(hedge_longPosId) then
CancelAllOrders(hedge_longPosId)
else
hedge_longPosId = NewGuid()
dir_l = GetPositionDirection(hedge_longPosId)
aep_l = GetPositionEnterPrice(hedge_longPosId)
pamt_l = GetPositionAmount(hedge_longPosId)
proi_l = GetPositionROI(hedge_longPosId)
end
end
if pamt_s == 0 and IsPositionClosed(hedge_shortPosId) then
if IsAnyOrderOpen(hedge_shortPosId) then
CancelAllOrders(hedge_shortPosId)
else
hedge_shortPosId = NewGuid()
dir_s = GetPositionDirection(hedge_shortPosId)
aep_s = GetPositionEnterPrice(hedge_shortPosId)
pamt_s = GetPositionAmount(hedge_shortPosId)
proi_s = GetPositionROI(hedge_shortPosId)
end
end
-- get pos id
local getPositionId = function(isLong)
return isLong and hedge_longPosId or hedge_shortPosId
end
--Dynamic Spread
local candleSpread = HighPrices(dynamicSpreadInterval) - LowPrices(dynamicSpreadInterval)
local candleSpreadWithLookback = Range(candleSpread, 0, dynamicSpreadLookback)
local averageSpread = Round(Average(candleSpreadWithLookback), 8)
local averageSpreadPercentage = Round(averageSpread / CurrentPrice().close * 100, 4)
if showInfo then
Log("Dynamic Average Spread: "..averageSpread.." "..QuoteCurrency())
Log("Dynamic Average Spread: "..averageSpreadPercentage.."%")
end
local minSpread = minSpread / 2.0
-- wallet check
local profitLabel = ProfitLabel()
if profitLabel == nil then profitLabel = QuoteCurrency() end
local availBal = WalletAmount(getMarket, profitLabel)
local getProfitL = GetCurrentProfit(PositionLong)
local getProfitS = GetCurrentProfit(PositionShort)
local getProfit = getProfitL + getProfitS
local usedLong = UsedMargin(getMarket, aep_l, pamt_l, leverage)
local usedShort = UsedMargin(getMarket, aep_s, pamt_s, leverage)
--Log('usedLong '..usedLong..' usedShort '..usedShort)
local botProfit = GetBotProfit()
-- balance warning
local walletBal = testWallet and (testWalletAmount + botProfit) or availBal
local workBal = usedLong + usedShort - getProfit
if budgetType == 'Fix' then
budgetBal = IfElse(walletBal > maxBudget, maxBudget, walletBal)
else
budgetBal = maxBudget * walletBal
end
--Log('walletBal '..walletBal)
local budRatio = budgetBal > 0 and workBal / budgetBal or 0
local walRatio = budgetBal > 0 and workBal / walletBal or 0
local balRatio = budgetIsolation and budRatio or walRatio
if balRatio > 0.5 and balRatio < 0.8 and budgetIsolation then Log('Working balance is > 50% of Budget!!!', Yellow) end
if balRatio > 0.8 and budgetIsolation then Log('Working balance is > 80% of Budget!!!', Yellow) end
if walRatio > 0.8 then LogWarning('WALLET IN DANGER. Working balance is > 80% of WALLET Balance!!!') end
if showInfo then
Log('Balance Monitor -> Wallet: '..Round(walletBal, 5)..' '..profitLabel..' | Budget: '..Round(budgetBal, 5)..' '..profitLabel..' | Working Balance: '..Round(workBal, 5)..' '..profitLabel..' | Ratio: '..Round(balRatio, 3))
end
if budgetType == 'Percentage' then
if maxBudget > 1 then
DeactivateBot('Percentage Budget calculation. Balance budget can not > 1', true)
end
else
if walletBal < budgetBal then
Log('Wallet Balance is lower than Budget Balance', Yellow)
end
end
local BRCounter = Load('BRCounter', 0)
if balRatio > BRCounter then Save('BRCounter', balRatio) end
-- dynamics
--max position
if profitLabel == 'USD' or profitLabel == 'USDT' or profitLabel == 'BUSD' or profitLabel == 'USDC' or profitLabel == 'TUSD' then
maxMax = budgetBal * maxOpen / cp.close
else
maxMax = budgetBal * maxOpen * cp.close / contVal
end
local maxCheck = autoMax and (maxMax * leverage)
local maxValue = autoMax and (maxCheck > maxSizeM) and maxCheck or maxSizeM
local maxSize = autoMax and maxValue or maxSizeM
-- check max open
if autoMax then
if maxCheck > maxSizeM then
if showInfo then
Log('Dynamic Max Open: '..Round(maxCheck, 5)..' '..AmountLabel())
end
else
if showInfo then
Log('Dynamic Max Open: '..Round(maxCheck, 5)..' but using default value: '..Round(maxSizeM, 5)..' '..AmountLabel())
end
end
end
-- auto slot size
local slotCheck = autoSlot and (maxSize / slotBudget)
local slotValue = autoSlot and (slotCheck > slotSizeM) and slotCheck or slotSizeM
local slotSize = autoSlot and slotValue or slotSizeM
local getSlotRatio = function (size)
local baseRatio
if longRatio >= shortRatio then
baseRatio = longRatio
else
baseRatio = shortRatio
end
return baseRatio
end
local calcRatioSlotSize = function (size, ratio, long)
if long == true then
if ratio == longRatio then
local round = Round(size, 2)
return ArrayGet(round, 1)
elseif ratio == shortRatio then
local round = Round(((longRatio / shortRatio) * size), 2)
return ArrayGet(round, 1)
end
end
if long == false then
if ratio == shortRatio then
local round = Round(size, 2)
return ArrayGet(round, 1)
elseif ratio == longRatio then
local round = Round(((shortRatio / longRatio) * size), 2)
return ArrayGet(round, 1)
end
end
end
if autoSlot then
if slotCheck > slotSizeM then
slotSizeL = slotSize
slotSizeS = slotSize
if enableRatio == true and longRatio > 0 and shortRatio > 0 then
local base = getSlotRatio(slotSize)
slotSizeL = calcRatioSlotSize(slotSize, base, true)
slotSizeS = calcRatioSlotSize(slotSize, base, false)
if pamt_s > (maxSize / incLVLOneShort) then
LogWarning("It's bigger than 10 %")
slotSizeS = slotSizeS * (longRatio / shortRatio)
end
end
if showInfo then
Log('Dynamic Slot Size for long: '..Round(slotSizeL, 5))
Log('Dynamic Slot Size for short: '..Round(slotSizeS, 5))
end
else
slotSizeL = slotSize
slotSizeS = slotSize
if enableRatio == true and longRatio > 0 and shortRatio > 0 then
local base = getSlotRatio(slotSize)
slotSizeL = calcRatioSlotSize(slotSize, base, true)
slotSizeS = calcRatioSlotSize(slotSize, base, false)
if pamt_s > (maxSize / incLVLOneShort) then
LogWarning("It's bigger than 10 %")
slotSizeS = slotSizeS * (longRatio / shortRatio)
end
end
if showInfo then
Log('DSSize: '..Round(slotCheck, 5)..' But using default value: '..Round(slotSizeM, 5))
end
end
else
slotSizeL = slotSizeM
slotSizeS = slotSizeM
if enableRatio == true and longRatio > 0 and shortRatio > 0 then
local base = getSlotRatio(slotSize)
slotSizeL = calcRatioSlotSize(slotSize, base, true)
slotSizeS = calcRatioSlotSize(slotSize, base, false)
if pamt_s > (maxSize / incLVLOneShort) then
LogWarning("It's bigger than 10 %")
slotSizeS = slotSizeS * (longRatio / shortRatio)
end
end
if showInfo then
Log('Slot Size Value for long: '..Round(slotSizeL, 5))
Log('Slot Size Value for short: '..Round(slotSizeS, 5))
end
end
-- SMM CORE LOGIC HEDGE MODE
-- slot function
local slot = function(isLong, index, amount, spread, cancelDist, canPlace)
local prefix = isLong and 'L' or 'S'
local name = prefix .. index
local cmd = isLong and PlaceGoLongOrder or PlaceGoShortOrder
local priceBase = isLong
and cp.bid
or cp.ask
local spr = Min(averageSpreadPercentage, minSpread) + spread * index
local posId = getPositionId(isLong)
local aep = isLong and aep_l or aep_s
-- if we have average entry price
if aep > 0 then
priceBase = isLong
and Min(aep, priceBase)
or Max(aep, priceBase)
end
-- get price
local price = isLong
and SubPerc(priceBase, spr)
or AddPerc(priceBase, spr)
-- Binance notional value mod
if isBinance then
notionalSize = 5.1 / price
if amount < notionalSize then
amount = notionalSize
end
end
local oid = Load(name..'oid', '') -- order id
if oid != '' then
local order = OrderContainer(oid)
if order.isOpen then
local delta = isLong
and Delta(AddPerc(order.price, spr), priceBase)
or Delta(priceBase, SubPerc(order.price, spr))
if delta >= cancelDist then
CancelOrder(oid)
LogWarning('Delta cancelled '..name)
elseif not canPlace then
CancelOrder(oid)
LogWarning('Not allowed right now '..name)
end
else
oid = ''
end
else
if canPlace then
oid = cmd(price, amount, {type = MakerOrCancelOrderType, note = name, timeout = 3600, positionId = posId})
end
end
Save(name..'oid', oid)
end
-- update take-profit
local updateTakeProfit = function(isLong, entryPrice, targetRoi, cancelDist)
local prefix = isLong and 'Long' or 'Short'
local name = prefix .. ' TP'
local oid = Load(prefix .. 'tp_oid', '')
local timer = Load(prefix .. 'tp_timer', 0)
local posId = getPositionId(isLong)
local tp_delta = isLong and Delta(entryPrice, cp.bid) or Delta(cp.ask, entryPrice)
if oid != '' then
local order = OrderContainer(oid)
if order.isOpen then
local delta = isLong
and Delta(order.price, cp.close)
or Delta(cp.close, order.price)
if delta >= cancelDist then
CancelOrder(oid)
LogWarning('Delta cancelled '..name)
end
else
if order.isCancelled then
timer = 0
end
oid = ''
end
else
if preplacedTP then
if isLong and pamt_l > 0 then
local exitL = AddPerc(aep_l, takeProfitL)
oid = PlaceExitPositionOrder({price= exitL, type = tpOrderType, note = 'Pre-Placed '..name, timeout = 200, positionId = hedge_longPosId})
end
if not isLong and pamt_s > 0 then
local exitS = SubPerc(aep_s, takeProfitS)
oid = PlaceExitPositionOrder({price= exitS, type = tpOrderType, note = 'Pre-Placed '..name, timeout = 200, positionId = hedge_shortPosId})
end
elseif not preplacedTP and tp_delta >= targetRoi and Time() >= timer then
oid = PlaceExitPositionOrder({type = tpOrderType, note = name, timeout = 200, positionId = posId})
timer = Time() + 60 -- 1min
end
end
Save(prefix .. 'tp_oid', oid)
Save(prefix .. 'tp_timer', timer)
end
-- update position size
local updatePositionManagement = function(isLong, currentSize, sizeLimit, cancelDist)
local prefix = isLong and 'Long' or 'Short'
local name = prefix .. ' Size Reduction'
local oid = Load(prefix .. 'pos_oid', '')
local posId = getPositionId(isLong)
local amount = SubPerc(currentSize, 100 - reduceSize) -- take X% of position
local price = isLong
and cp.ask
or cp.bid
local cmd = isLong
and PlaceExitLongOrder
or PlaceExitShortOrder
local timer = Load(prefix .. 'pos_timer', Time())
local okReduce = IfElse(budgetIsolation, balRatio >= 1, currentSize > sizeLimit)
if oid != '' then
local order = OrderContainer(oid)
if order.isOpen then
local delta = isLong
and Delta(order.price, cp.close)
or Delta(cp.close, order.price)
if delta >= cancelDist then
CancelOrder(oid)
LogWarning('Delta cancelled '..name)
end
elseif order.isFilled then
sizeRed = 1
Save('SRCounter', SRCounter + sizeRed)
oid = ''
else
oid = ''
end
else
if okReduce and Time() >= timer then
oid = cmd(price, amount, {type = reduceOrderType, note = name, timeout = 6000, positionId = posId})
timer = Time() + 60 -- 1min
end
end
Save(prefix .. 'pos_oid', oid)
Save(prefix .. 'pos_timer', timer)
end
-- da logica
-- take profit
updateTakeProfit(true, aep_l, takeProfitL, slotCancel)
updateTakeProfit(false, aep_s, takeProfitS, slotCancel)
-- risk management
updatePositionManagement(true, pamt_l, maxSize, slotCancel)
updatePositionManagement(false, pamt_s, maxSize, slotCancel)
-- update slots
for i = 1, slotCount do
slot(true, i, slotSizeL, slotSpreadL, slotCancel, okLong) -- long slot
slotSizeL = slotSizeL * slotMultiplier
slotSpreadL = slotSpreadL * slotSpreadM
end
for i = 1, slotCount do
slot(false, i, slotSizeS, slotSpreadS, slotCancel, okShort) -- short slot
slotSizeS = slotSizeS * slotMultiplier
slotSpreadS = slotSpreadS * slotSpreadM
end
-- WTF
if wtfStop then
local longNull = pamt_l == 0
local shortNull = pamt_s == 0
if longNull and shortNull then
DeactivateBot('Deactivate on No Position is active', true)
else
LogWarning('Will deactivate on No Position, waiting...maybe next second, maybe never :)')
end
end
if wtfBal then
if workBal >= budgetBal then
DeactivateBot('Over Budget', true)
end
end
if wtfAmount then
if pamt_l > maxSize or pamt_s > maxSize then
DeactivateBot('Over Size', true)
end
end
if wtfRatio then
if balRatio > wtfRatioV then
DeactivateBot('Bal Ratio is over '..wtfRatioV, true)
end
end
if wtfWallet then
if walletBal <= 0 then
DeactivateBot('Wallet is 0', true)
end
end
-- Force Exit Positions
if FStop then
local name = 'Force Exit'
oid = PlaceExitPositionOrder({type = reduceOrderType, note = name, timeout = 3600})
timer = Time() + 60 -- 1min
end
-- PLOT
-- AEP Plot
if aep_l > 0 then
local posId = getPositionId(true)
Plot(0, 'AvgEP Long', aep_l, {c=Teal, id=posId, w=2})
end
if aep_s > 0 then
local posId = getPositionId(false)
Plot(0, 'AvgEP Short', aep_s, {c=Purple, id=posId, w=2})
end
-- EXPOSURE
local lineLong = IfElse(pamt_l > 0, pamt_l, 0)
local lineShort = IfElse(pamt_s > 0, -pamt_s, 0)
Plot(1, 'Longs', lineLong, {c=Green, s=Step})
Plot(1, 'Max Longs', maxSize, {c=White, s=Step})
Plot(1, 'Shorts', lineShort, {c=Red, s=Step})
Plot(1, 'Max Shorts', -maxSize, {c=White, s=Step})
ChartSetOptions(1, 'Exposure')
--BALANCE MONITOR
Plot(2, 'Budget Balance', budgetBal, {c=White, s=Step})
Plot(2, 'WorkBal', workBal, {c=Red, s=Step})
Plot(2, 'Wallet Balance', walletBal, {c=DarkGreen, s=Step})
ChartSetOptions(2, 'Balance Monitor')
-- Misc Logs
if showInfo then
Log('Size Reduction: '..SRCounter..' times')
end
if not okLong then
LogWarning('Bot is not allowed to open LONG')
end
if not okShort then
LogWarning('Bot is not allowed to open SHORT')
end
-- custom reports
Finalize(function()
CustomReport('Final Wallet Balance', Round(walletBal, 5)..' '..profitLabel)
CustomReport('Size Reduction', SRCounter..' times')
CustomReport('Highest Balance Ratio', Round(100 * BRCounter, 2)..'%')
if testWallet then
if budgetType == 'Fix' then
profitPercent = Round(botProfit / maxBudget * 100, 2)
else
local startBal = testWalletAmount * maxBudget
profitPercent = Round(botProfit / startBal * 100, 2)
end
CustomReport('Profit %: ', profitPercent..'%')
CustomReport('Profit to Highest Bal. Ratio', Round(profitPercent / (100 * BRCounter), 2))
end
end)
Save('hedge_longPosId', hedge_longPosId)
Save('hedge_shortPosId', hedge_shortPosId)
if showInfo then
Log(' ')
end
2 Comments
Sign in to leave a comment.
4. 30 Jun 2023 22:37:00 ERROR: The script is invalid.
3. 30 Jun 2023 22:37:00 ERROR: Unknown references: GetLeverage
2. 30 Jun 2023 22:37:00 This script is compatible with margin and leverage trading.
1. 30 Jun 2023 22:37:00 Doing compile test...
upd
on v4 works
yes because GetLeverage is not compatible with V3.
if you want to have it on V3, try change line 35 and 36 with the commented out command...or compare it with the original SMMD V2.51