Definition of margin param in setcommission unclear
-
Hello everyone, I'm wondering what the definition of the margin parameter in the commission schemes is. It is not really defined well on https://www.backtrader.com/docu/commission-schemes/commission-schemes/ . Shouldn't the margin requirement be a relative parameter depending on the size of the order? Here it appears to be a fixed monetary value (2000) :
cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0)
Thanks,
Cheers -
-
@ab_trader Thanks! On the link you posted they also explain that the futures margin is a fixed amount of cash that needs to be deposited before futures can be traded. Excuse me if this is a really dumb question, but won't this be a) dependent on the position size I intend to open and b) change with time? I'm interested in the case of Binance perpetual futures where the initial margin clearly is given as a fraction of the position value and the applied leverage (https://www.binance.com/de/support/faq/360033162192-Leverage-and-Margin-of-Perpetual-Futures-Contracts). Thanks for helping out a rookie
-
@stonks it depends on the future contract specifications. for sure margin for position of two contracts will be twice more than margin for position of single contract.
-
@ab_trader Is there a way to specify the margin as a percentage of the asset price, rather than as an absolute value, in backtrader? Otherwise, how does the margin requirement change over time as the price of the future changes?
-
@stonks said in Definition of margin param in setcommission unclear:
Is there a way to specify the margin as a percentage of the asset price, rather than as an absolute value, in backtrader?
i don't know, but lets do the first evident thing - check out the docs and parameters available for commissions.
https://www.backtrader.com/docu/commission-schemes/commission-schemes/#reference
automargin (def: False): Used by the method get_margin to automatically calculate the margin/guarantees needed with the following policy
- Use param margin if param automargin evaluates to False
- Use param mult and use mult * price if automargin < 0
- Use param automargin and use automargin * price if automargin > 0
So maybe use of
automargin
parameter > 0 can do what you want.@stonks said in Definition of margin param in setcommission unclear:
Otherwise, how does the margin requirement change over time as the price of the future changes?
It is not a strict requirement. For example, common old-school futures has roughly constant margin.
-
@ab_trader Thanks for your tip! I think I was able to code up a custom commission scheme (CommInfo_BinancePerp) that reproduces Binance perpetual futures where margin = position_value/mult. When I look at a minimal example of buying one contract and selling it a couple of days later, the numbers roughly add up but there is some mismatch between the buy price and the portfoliovalue/cash.
I use this mini-example with (mult = 1), and (commission = 0) and the logs confuse me, If I start with 1000$, then buy one contract @ 396.36$, why do I have pvalue: 973.6$, cash: 590.44$ ? This can't even be explained by the difference between open/close on that day.
My mini-example:
import backtrader as bt from datetime import datetime class MiniExample(bt.Strategy): def __init__(self): # To keep track of pending orders self.orders = None def next(self): if len(self) == 1: #on second candle self.orders = self.buy(size = 1) if len(self) == 5: #on 6th candle self.orders = self.sell(size = 1) dt = self.datas[0].datetime.date(0) print(f"{dt} - getvalue: {round(self.broker.getvalue(),2)}$, getcash: {round(self.broker.getcash(),2)}$, getposition: {self.broker.getposition(self.datas[0]).size}, open: {self.datas[0].open[0]}$, close: {self.datas[0].close[0]}$") def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def notify_order(self, order): if order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') print('Order Canceled/Margin/Rejected') if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log(f"BUY EXECUTED, {order.executed.size} units @ {order.executed.price}$") elif order.issell(): self.log(f"SELL EXECUTED, {order.executed.size} units @ {order.executed.price}$") self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.orders = None def notify_trade(self, trade): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) # define custom commission scheme that reproduces Binance perpetual future trading class CommInfo_BinancePerp(bt.CommInfoBase): params = ( ('stocklike', False), # Futures ('commtype', bt.CommInfoBase.COMM_PERC), # Apply % Commission ) def _getcommission(self, size, price, pseudoexec): return size * price * self.p.commission * self.p.mult def get_margin(self, price): return price / self.p.mult def getsize(self, price, cash): '''Returns fractional size for cash operation @price''' return self.p.mult * (cash / price) # initialize cerebro object cerebro = bt.Cerebro() # add strategy cerebro.addstrategy(MiniExample) # add custom commission scheme to cerebro element binance_leverage = 1 comminfo = CommInfo_BinancePerp( commission=0, # 0.1% mult=binance_leverage ) cerebro.broker.addcommissioninfo(comminfo) cerebro.broker.set_shortcash(False) # set initial cash cerebro.broker.setcash(1000) # add data data = bt.feeds.YahooFinanceData(dataname='ETH-USD', fromdate = datetime(2020,11,1), todate = datetime(2020,11,7)) cerebro.adddata(data) # execute back = cerebro.run()
My logs:
2020-11-01 - pvalue: 1000.0$, cash: 1000.0$, pos: 0, O: 386.59$, C: 396.36$ 2020-11-02, BUY EXECUTED, 1 units @ 396.36$ 2020-11-02 - pvalue: 973.6$, cash: 590.44$, pos: 1, O: 396.36$, C: 383.16$ 2020-11-03 - pvalue: 982.48$, cash: 594.88$, pos: 1, O: 383.16$, C: 387.6$ 2020-11-04 - pvalue: 1011.56$, cash: 609.42$, pos: 1, O: 387.6$, C: 402.14$ 2020-11-05 - pvalue: 1035.42$, cash: 621.35$, pos: 1, O: 402.14$, C: 414.07$ 2020-11-06, SELL EXECUTED, -1 units @ 414.07$ 2020-11-06, OPERATION PROFIT, GROSS 17.71, NET 17.71 2020-11-06 - pvalue: 1017.71$, cash: 1017.71$, pos: 0, O: 414.07$, C: 454.72$
Thanks again for any further help, really struggling with this.
-
I believe you need to set correct
automargin
parameter without modifying the class methods.Check out the links
https://community.backtrader.com/topic/606/percentage-margin-for-futureshttps://community.backtrader.com/topic/577/maintenance-margin