[CMD] BacktestSettings
stableDescription
This expands from the balance monitor command as most of these things are all used together so I have combined most of the usual settings used for back testing into a single easy to use command which will provide inputs via script and on the settings dialog on the left. Just add it onto any script you are creating and it should be good to go. You can then change the settings via the tickboxes/boxes or via script parameters.
Required Commands -
SetPerc
ElapsedTime
EventTime
CC_BacktestSettings()
HaasScript
-- Author: Strooth
-- Feel free to donate to support my work or if my script helped you in any way <3
-- BTC Adress: 33MsEAbA8tg7SpohgnCpSrmPTBih2UkhxQ
DefineCommand('BacktestSettings', 'Final Wallet Balance, Exposure, compound, Test wallet, deactivate on overbudget, oversize and liquidation')
if Load('start', 0) == 0 then Save('startdate', CreateTimestamp()) end
local grp = '~Backtest Settings'
local btsettings_enabled = DefineParameter(BooleanType, 'enabled', 'enable backtest settings', false, true, 'true/false, boolean, Input')
local btp = {
cindex = DefineParameter(NumberType, 'ChartIndex', 'The index to plot the chart', false, -10, 'Number, Input'),
market = DefineParameter(StringType, 'market', 'the market to run the settings on', false, PriceMarket(), 'PriceMarket(), Input'),
maxBudget = DefineParameter(NumberType, 'maxBudget', 'how much of the wallet balance to allocate to the bot', false, CC_SetPerc(' Wallet Budget', '80%', grp), 'Number, Input'),
compound = DefineParameter(BooleanType, 'AddProfit', 'Add profit into balance', false, Parse(Input('Compound', true, 'Enable to add profit to the balance during backtest', {group=grp}), BooleanType), 'true/false, boolean, Input'),
deact = DefineParameter(BooleanType, 'StopOnLiquidation', 'Deactivate bot on liquidation', false, Parse(Input('Deactivate on Liquidation', true, 'Deactivate the bot on liquidation',{group=grp}), BooleanType), 'true/false, boolean, Input'),
testWallet = DefineParameter(BooleanType, 'Test Wallet', 'Simulate with test wallet balance', false, Parse(Input(' Test Wallet', false, 'Enable using the test wallet balance',{group=grp}), BooleanType), 'true/false, boolean, Input'),
testBal = DefineParameter(NumberType, 'Test Balance', 'Test Balance Amount', false, Input(' Test Wallet Size', 5000, 'The size of the balance if using test wallet',{group=grp}), 'Number, Input'),
plotexp = DefineParameter(BooleanType, 'Plot Exposure', 'Plot exposure amount', false, Parse(Input('Plot Exposure', false, 'Enable ploting the exposure of long and short positions',{group=grp}), BooleanType), 'true/false, boolean, Input'),
plotratio = DefineParameter(BooleanType, 'Plot Ratio', 'Plot balance ratio', false, Parse(Input('Plot Ratio', false, 'Enable showing the plot of balance ratio on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
plotprofit = DefineParameter(BooleanType, 'Plot Profit', 'Plot total profit', false, Parse(Input('Plot Profit', false, 'Enable showing the plot of total profit on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
plotroi = DefineParameter(BooleanType, 'Plot Roi', 'Plot total ROI', false, Parse(Input('Plot ROI', false, 'Enable showing the plot of total ROI on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
plotwallet = DefineParameter(BooleanType, 'Plot Balance', 'Plot the balance monitor', false, Parse(Input('Plot Balance', true, 'Enable showing the plot of wallet balance on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
plotaeps = DefineParameter(BooleanType, 'Plot EnterPrices', 'Plot the average long and short enter prices', false, Parse(Input('Plot EnterPrices', true, 'Plot the average long and short enter prices on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
plotrr = DefineParameter(BooleanType, 'Plot Risk/Reward', 'Plot the risk and reward for long and short positions', false, Parse(Input('Plot Risk/Reward', false, 'Plot the risk/reward for long and short positions on the chart', {group=grp}), BooleanType), 'true/false, boolean, Input'),
overbudget = DefineParameter(BooleanType, 'StopOverBudget', 'Deactivate bot over budget', false, Parse(Input('Deactivate on Over Budget', true, {group=grp}), BooleanType), 'true/false, boolean, Input'),
oversize = DefineParameter(BooleanType, 'StopOverSize', 'Deactivate bot Over Size', false, Parse(Input('Deactivate on Over Size', true, {group=grp}), BooleanType), 'true/false, boolean, Input'),
log = DefineParameter(BooleanType, 'log', 'verbose logging', false, false, 'true/false, boolean, Input'),
}
local main, workBal, walletBal, output, stop, reason, elapsedtime, zrb, WorkBalline, Budgetline, Walletline, plot, zr, lngs, mlngs, shrts, mshrts, maxSize, lineLong, lineShort, exposure,
exposureclouds, profclouds, runtime, pltratio, zrrp, roiclouds, roilinen, roilinep, roilinenp, roilinepp, zrr, usevpm, vpm, ratioclouds, ratz, ratline, plotprof, finish, text, plotaep,
xlong, xshort, plotclouds, walletclouds, plotwal, availBal, longAmount, shortAmount, getProfitL, getProfitS, getRoiL, getRoiS, getProfit, usedLong, usedShort, botProfit, time, type,
stop, leverage, profitLabel, budgetBal, balRatio, maxriskl, maxrewardl, riskl, rewardl, maxrisks, maxrewards, risks, rewards, risk, reward, finish, coinm
main = function()
coinm = UnderlyingAsset(btp.market) == BaseCurrency(btp.market)
local totall = {enterPrice = {}, amount = {}, roi = {}, profit = {}, weight = {}}
local totals = {enterPrice = {}, amount = {}, roi = {}, profit = {}, weight = {}}
for i, p in pairs(GetAllOpenPositions()) do
local pos = PositionContainer(p.positionId, true)
if pos.isLong then
totall.enterPrice[i] = pos.enterPrice
totall.amount[i] = pos.amount
totall.roi[i] = pos.roi
totall.profit[i] = pos.profit
totall.weight[i] = pos.enterPrice * pos.amount
else
totals.enterPrice[i] = pos.enterPrice
totals.amount[i] = pos.amount
totals.roi[i] = pos.roi
totals.profit[i] = pos.profit
totals.weight[i] = pos.enterPrice * pos.amount
end
end
xlong = {amount = ArraySum(totall.amount), roi = ArraySum(totall.roi), profit = ArraySum(totall.profit), enterPrice = Div(ArraySum(totall.weight), ArraySum(totall.amount))}
xshort = {amount = ArraySum(totals.amount), roi = ArraySum(totals.roi), profit = ArraySum(totals.profit), enterPrice = Div(ArraySum(totals.weight), ArraySum(totals.amount))}
local currentprofitl = Switch(coinm==true, Round(Sub(xlong.amount*ContractValue(btp.market)/CurrentPrice(btp.market).ask, xlong.amount*ContractValue(btp.market)/xlong.enterPrice),2), Round(Sub(xlong.amount*CurrentPrice(btp.market).ask, xlong.amount*xlong.enterPrice),2))
local currentprofits = Switch(coinm==true, Round(Sub(xshort.amount*ContractValue(btp.market)/xshort.enterPrice, xshort.amount*ContractValue(btp.market)/CurrentPrice(btp.market).bid),2), Round(Sub(xshort.amount*xshort.enterPrice, xshort.amount*CurrentPrice(btp.market).bid),2))
local currentprofit = currentprofitl+currentprofits
stop = false
leverage = Leverage() or 0
profitLabel = ProfitLabel(btp.market)
if profitLabel == nil then profitLabel = QuoteCurrency(btp.market) end
availBal = btp.testWallet and btp.testBal or WalletAmount(AccountGuid(), UnderlyingAsset(btp.market))
longAmount = LongAmount(btp.market)
shortAmount = ShortAmount(btp.market)
getProfitL = currentprofitl
getProfitS = currentprofits
getRoiL = GetCurrentROI(PositionLong, btp.market)
getRoiS = GetCurrentROI(PositionShort, btp.market)
getProfit = getProfitL + getProfitS
usedLong = UsedMargin(AccountGuid(), xlong.enterPrice, longAmount, leverage)
usedShort = UsedMargin(AccountGuid(), xshort.enterPrice, shortAmount, leverage)
botProfit = GetBotProfit(btp.market)
time = {minutes = 60,hours = 3600,days = 86400,months = 2629743,years = 31556926,}
type = {minutes = 'Minutes',hours = 'Hours',days = 'Days',months = 'Months',years = 'Years',}
walletBal = btp.compound and (availBal + botProfit) or availBal
if Load('start') == 0 then Save('walletbal', walletBal); Save('start', 1) end
workBal = usedLong + usedShort - getProfit
budgetBal = btp.maxBudget * walletBal
balRatio = budgetBal > 0 and workBal / budgetBal or 0
if btp.log then
-- balance warning
if balRatio > 0.5 and balRatio < 0.8 then btp.logWarning('Working balance is > 50% of Budget!!!') end
if balRatio > 0.8 then btp.logWarning('Working balance is > 80% of Budget!!!') end
btp.log('Balance Monitor Binance -> Budget Balance: '..Round(budgetBal, 5)..' '..profitLabel..' | Working Balance: '..Round(workBal, 5)..' '..profitLabel..' | Ratio: '..Round(balRatio, 3))
end
local BRCounter = Load('BRCounter', 0)
if balRatio > BRCounter then Save('BRCounter', balRatio) end
if btp.overbudget then
if workBal > budgetBal then
PlotShape(0, ShapeText, White, 20, true, 'Over budget', White, 11)
PlotShape(0, ShapeCross, White, 20, true, '', White, 10)
PlotShape(0, ShapeText, White, 20, false, 'Over budget', White, 11)
PlotShape(0, ShapeCross, White, 20, false, '', White, 10)
PlotVerticalLine(0, 'Over Budget', Red, Time(), Dashed)
stop = true
reason = 'btp.deactivate Bot, Wallet Use is Above Allowed Budget '
end
end
if btp.oversize then
if longAmount > MaxLongAmount(btp.market) or ShortAmount(btp.market) > MaxShortAmount(btp.market) then
stop = true
reason = 'btp.deactivate Bot, Position Size is Over Allowed Size Limit'
end
end
if btp.deact and workBal > walletBal then
PlotShape(0, ShapeText, White, 20, false, 'Liquidated', White, 11)
PlotShape(0, ShapeCross, White, 20, false, '', White, 10)
PlotShape(0, ShapeText, White, 20, true, 'Liquidated', White, 11)
PlotShape(0, ShapeCross, White, 20, true, '', White, 10)
PlotVerticalLine(0, 'Liquidated', Red, Time(), Dashed)
stop = true
reason = 'btp.deactivate Bot, Account Liquidated'
end
riskl = Load('riskl', 0)
risks = Load('risks', 0)
risk = Load('risk', 0)
rewardl = Load('rewardl', 0)
rewards = Load('rewards', 0)
reward = Load('reward', 0)
local bigl = Load('bigl', 0)
local bigs = Load('bigs', 0)
if xlong.amount > 0 then
if xlong.amount > bigl then
Save('bigl', xlong.amount)
end
end
if xshort.amount > 0 then
if xshort.amount > bigs then
Save('bigs', xshort.amount)
end
end
if currentprofitl < 0 then
if Abs(currentprofitl) > riskl then
Save('riskl', Abs(currentprofitl))
end
else
if currentprofitl > rewardl then
Save('rewardl', currentprofitl)
end
end
if riskl != Load('riskl', 0) then
Save('maxrisktimel', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleDown, Red, 11, false, 'Max Risk Long', White)
MarkCandle(0, 1)
end
end
if rewardl != Load('rewardl', 0) then
Save('maxrewardtimel', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleDown, Green, 11, true, 'Max Reward Long', White)
MarkCandle(0, 1)
end
end
if currentprofits < 0 then
if Abs(currentprofits) > risks then
Save('risks', Abs(currentprofits))
end
else
if currentprofits > rewards then
Save('rewards', currentprofits)
end
end
if risks != Load('risks', 0) then
Save('maxrisktimes', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleDown, Red, 11, true, 'Max Risk Short', White)
MarkCandle(0, 1)
end
end
if rewards != Load('rewards', 0) then
Save('maxrewardtimes', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleUp, Green, 11, false, 'Max Reward Short', White)
MarkCandle(0, 1)
end
end
if currentprofit < 0 then
if Abs(currentprofit) > risk then
Save('risk', Abs(currentprofit))
end
else
if currentprofit > reward then
Save('reward', currentprofit)
end
end
if risk != Load('risk', 0) then
Save('maxrisktime', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleDown, Black, 11, true, 'Max Risk Total', White)
MarkCandle(0, 1)
end
end
if reward != Load('reward', 0) then
Save('maxrewardtime', Time())
if btp.plotrr then
PlotShape(0, ShapeTriangleUp, Purple, 11, false, 'Max Reward Total', White)
MarkCandle(0, 1)
end
end
return stop
end
if btp.plotexp then
exposure = function()
maxSize = Average(MaxLongAmount(btp.market),MaxShortAmount(btp.market))
lineLong = FilterBelow(longAmount, 0)
lineShort = FilterAbove(shortAmount, 0)
zr = Plot(btp.cindex+1, '0', 0, {c=White(10), w=2, s=Step})
lngs = Plot(btp.cindex+1, 'Longs', lineLong, {c=ChangeColorOpacity(Green,10), s=Step})
mlngs = Plot(btp.cindex+1, 'Max Longs', maxSize, {c=ChangeColorOpacity(Green,30), s=Step})
shrts = Plot(btp.cindex+1, 'Shorts', lineShort, {c=ChangeColorOpacity(Red, 10), s=Step})
mshrts = Plot(btp.cindex+1, 'Max Shorts', -maxSize, {c=ChangeColorOpacity(Red, 30), s=Step})
end
exposureclouds = function()
PlotStackedArea({
PlotBands(lngs, zr, ChangeColorOpacity(White,10)),
PlotCloud(mlngs, lngs, 10),
PlotCloud(shrts, zr, 10),
PlotCloud(mshrts, shrts, 10),
})
ChartSetOptions(btp.cindex+1, 'Exposure', 100, Spread)
end
end
if btp.plotratio then
pltratio = function()
ratz = Plot(btp.cindex+2, '0', 0, {c=White(10), w=2})
ratline = Plot(btp.cindex+2, 'Balance Ratio', balRatio, {c=White(90)})
end
ratioclouds = function()
PlotStackedArea({
PlotBands(ratline, ratz, ChangeColorOpacity(White,10)),
PlotCloud(ratz, ratline, 10),
})
ChartSetOptions(btp.cindex+2, 'Balance Ratio', 100, Spread)
end
end
if btp.plotroi then
btp.plotroi = function()
zrr = Plot(btp.cindex+3, '0', 0, {c=White(10), w=2, s=Smooth})
roilinep = Plot(btp.cindex+3, 'ROI %+', FilterBelow(getRoiS+getRoiL, 0), {c=DarkGreen(70), s=Smooth})
roilinen = Plot(btp.cindex+3, 'ROI %-', FilterAbove(getRoiS+getRoiL, 0), {c=Red(30), s=Smooth})
end
roiclouds = function()
PlotStackedArea({
PlotBands(roilinep, zrr, ChangeColorOpacity(DarkGreen,10)),
PlotBands(zrr, roilinen, ChangeColorOpacity(Maroon,10)),
})
ChartSetOptions(btp.cindex+3, 'Return On Investment %', 100, Spread)
end
end
if btp.plotprofit then
plotprof = function()
zrrp = Plot(btp.cindex+4, '0', 0, {c=White(10), w=2, s=Step})
roilinepp = Plot(btp.cindex+4, 'Profit +', FilterBelow(getProfit, 0), {c=Teal(90), s=Step})
roilinenp = Plot(btp.cindex+4, 'Profit -', FilterAbove(getProfit, 0), {c=Fuchsia(30), s=Step})
end
profclouds = function()
PlotStackedArea({
PlotBands(roilinepp, zrrp, ChangeColorOpacity(Teal,10)),
PlotBands(zrrp, roilinenp, ChangeColorOpacity(Fuchsia,10)),
})
ChartSetOptions(btp.cindex+4, 'Profit & Loss', 100, Spread)
end
end
if btp.plotwallet then
plotwal = function()
zrb = Plot(btp.cindex, '0', 0, {c=White(1), w=1})
WorkBalline = Plot(btp.cindex, 'WorkBal', workBal, {c=Yellow, s=Step})
Budgetline = Plot(btp.cindex, 'Budget Balance', (walletBal * btp.maxBudget), {c=Orange, s=Step})
Walletline = Plot(btp.cindex, 'Wallet Balance', (walletBal), {c=Red, s=Step})
end
walletclouds = function()
PlotBands(WorkBalline, zrb, ChangeColorOpacity(White,10))
if IsSmallerThan(workBal, (walletBal * btp.maxBudget)) then
PlotCloud(Budgetline, WorkBalline, 10)
end
if IsSmallerThan(workBal, (walletBal * btp.maxBudget)) then
PlotCloud(Walletline, Budgetline, 10)
elseif IsSmallerThan(workBal, walletBal) then
PlotCloud(Walletline, WorkBalline, 10)
end
end
end
if btp.plotaeps then
plotaep = function()
if xlong.enterPrice > 0 then
local lguid = Load('lguid', NewGuid())
Plot(0, 'Long AEP', Round(IfNull(xlong.enterPrice,0),3), {c=Teal, id=lguid})
Save('lguid', lguid)
else
Save('lguid', NewGuid())
end
if xshort.enterPrice > 0 then
local sguid = Load('sguid', NewGuid())
Plot(0, 'Short AEP', Round(IfNull(xshort.enterPrice,0),3), {c=Fuchsia, id=sguid})
Save('sguid', sguid)
else
Save('sguid', NewGuid())
end
end
end
plot = function()
if btp.plotwallet then
plotwal()
end
if btp.plotprofit then
plotprof()
end
if btp.plotratio then
pltratio()
end
if btp.plotexp then
exposure()
end
if btp.plotroi then
btp.plotroi()
end
if btp.plotaeps then
plotaep()
end
end
plotclouds = function()
if btp.plotwallet then
walletclouds()
end
if btp.plotexp then
exposureclouds()
end
if btp.plotprofit then
profclouds()
end
if btp.plotroi then
roiclouds()
end
if btp.plotratio then
ratioclouds()
end
return true
end
finish = function()
local grp = 'Strooths Backtest Report'
plotclouds()
ChartSetOptions(btp.cindex, 'Balance Monitor', 100)
local wcolor = walletBal > Load('walletbal', walletBal) and Teal or Fuchsia
local adjust = coinm==true and Mult or Div
if btp.testWallet then
local profitPercent = Round(PercentageChange(btp.testBal, walletBal), 2)
CustomReport('Profit % ', profitPercent..'%', grp)
end
local underlyingasset = ' '..UnderlyingAsset(btp.market)
local _maxrisks = Round(Load('risks', 0),2)
local _maxrewards = Round(Load('rewards', 0),2)
local _maxriskl = Round(Load('riskl', 0),2)
local _maxrewardl = Round(Load('rewardl', 0),2)
local _maxrisk = Round(Load('risk', 0),2)
local _maxreward = Round(Load('reward', 0),2)
local srr, lrr = 0, 0
if And(_maxrewardl > 0, _maxriskl > 0) then
lrr = Round(Div(_maxrewardl, _maxriskl),2)
end
if And(_maxrewards > 0, _maxrisks > 0) then
srr = Round(Div(_maxrewards, _maxrisks),2)
end
PlotVerticalLine(0, 'Max Risk Total '.._maxrisk..underlyingasset, Black, Load('maxrisktime', 0))
PlotVerticalLine(0, 'Max Reward Total '.._maxreward..underlyingasset, Purple, Load('maxrewardtime', 0))
PlotVerticalLine(0, 'Max Risk Long '.._maxriskl..underlyingasset, Red, Load('maxrisktimel', 0))
PlotVerticalLine(0, 'Max Reward Long '.._maxrewardl..underlyingasset, Green, Load('maxrewardtimel', 0))
PlotVerticalLine(0, 'Max Risk Short '.._maxrisks..underlyingasset, Red, Load('maxrisktimes', 0))
PlotVerticalLine(0, 'Max Reward Short '.._maxrewards..underlyingasset, Green, Load('maxrewardtimes', 0))
CustomReport('Risk Reward Ratio Long ', '1:'..lrr, grp)
CustomReport('Risk Reward Ratio Short ', '1:'..srr, grp)
CustomReport('Maximum Risk Time Long ', CC_EventTime(Load('maxrisktimel', 0)), grp)
CustomReport('Maximum Reward Time Long ', CC_EventTime(Load('maxrewardtimel', 0)), grp)
CustomReport('Maximum Risk Time Short ', CC_EventTime(Load('maxrisktimes', 0)), grp)
CustomReport('Maximum Reward Time Short ', CC_EventTime(Load('maxrewardtimes', 0)), grp)
CustomReport('Maximum Risk Time Total ', CC_EventTime(Load('maxrisktime', 0)), grp)
CustomReport('Maximum Reward Time Total ', CC_EventTime(Load('maxrewardtime', 0)), grp)
CustomReport('Maximum Risk Long ', _maxriskl..underlyingasset, grp)
CustomReport('Maximum Risk Short ', _maxrisks..underlyingasset, grp)
CustomReport('Maximum Risk Total ', _maxrisk..underlyingasset, grp)
CustomReport('Maximum Reward Long ', _maxrewardl..underlyingasset, grp)
CustomReport('Maximum Reward Short ', _maxrewards..underlyingasset, grp)
CustomReport('Maximum Reward Total ', _maxreward..underlyingasset, grp)
CustomReport('Largest Short Position ', Load('bigs', 0), grp)
CustomReport('Largest Long Position ', Load('bigl', 0), grp)
CustomReport('Final Short EnterPrice ', IfNull(xshort.enterPrice, 0), grp)
CustomReport('Final Long EnterPrice ', Round(IfNull(xlong.enterPrice,0),2),grp)
CustomReport('Final Size Total ', (xlong.amount+xshort.amount), grp)
CustomReport('Final Size Short ', xshort.amount, grp)
CustomReport('Final Size Long ', xlong.amount, grp)
CustomReport('Final ROI Total ', (xlong.roi+xshort.roi), grp)
CustomReport('Final ROI Short ', xshort.roi, grp)
CustomReport('Final ROI Long ', xlong.roi, grp)
CustomReport('Final Wallet Balance ', walletBal..underlyingasset, grp)
CustomReport('Final Wallet Value ', adjust(walletBal, ContractValue(btp.market))..underlyingasset, grp)
CustomReport('Final Profit Total ', Round(xlong.profit+xshort.profit,2)..underlyingasset, grp)
CustomReport('Final Profit Short ', Round(xshort.profit,2)..underlyingasset, grp)
CustomReport('Final Profit Long ', Round(xlong.profit,2)..underlyingasset, grp)
CustomReport('Final Open Unrealised ROI ', GetBotROI(btp.market)+(xlong.roi+xshort.roi), grp)
CustomReport('Final Open Unrealised Profit ', GetBotProfit(btp.market)+(xlong.profit+xshort.profit)..underlyingasset, grp)
CustomReport('Final Open Realised ROI ', GetBotROI(btp.market), grp)
CustomReport('Final Open Realised Profit ', GetBotProfit(btp.market)..underlyingasset, grp)
CustomReport('Backtest length ', CC_ElapsedTime(Load('startdate', CreateTimestamp())), grp)
if stop then
CustomReport('Liquidated', walletBal..underlyingasset, 'Liquidated')
end
end
do
if btsettings_enabled == true then
main()
if stop then
if btp.deactivateBot(reason, true) then
plot()
finish()
end
else
plot()
Finalize(finish)
end
end
end
DefineOutput(VoidType)
0 Comments
Sign in to leave a comment.
No comments yet. Be the first!