Problem with using ATR multiplier as stoploss and printing CASH.
-
Hello, I am new to backtrader. I have several questions, i will post them down below the original code. This is what I wanna do:
1. Only take long positions.
2. Use donchian channel's 20 day high as open
3. Use 4 multipler ATR (14 day period) as stoploss/to exit long position.
4. RiskHere is the original code:
import backtrader as bt import datetime import math class DonchianChannels(bt.Indicator): alias = ('DCH', 'DonchianChannel',) lines = ('dcm', 'dch', 'dcl',) # dc middle, dc high, dc low params = dict( period= 20, lookback= -1, # (-1) = doesnt current bar ) plotinfo = dict(subplot=False) # plot along with dataa plotlines = dict( dch=dict(color="black"), # use same color as prev line (dcm) #dcl=dict(_samecolor=False), # use same color as prev line (dch) ) def __init__(self): hi, lo = self.data.high, self.data.low if self.p.lookback: # move backwards as needed hi, lo = hi(self.p.lookback), lo(self.p.lookback) self.l.dch = bt.ind.Highest(hi, period=self.p.period) #self.l.dcl = bt.ind.Lowest(lo, period=self.p.period) class MaxRiskSizer(bt.Sizer): ''' Returns the number of shares rounded down that can be purchased for the max rish tolerance ''' params = (('risk', 0.03),) def __init__(self): if self.p.risk > 1 or self.p.risk < 0: raise ValueError('The risk parameter is a percentage which must be' 'entered as a float. e.g. 0.5') def _getsizing(self, comminfo, cash, data, isbuy): if isbuy: size = math.floor((cash * self.p.risk) / data[0]) else: size = math.floor((cash * self.p.risk) / data[0]) * -1 return size class TestStrategy(bt.Strategy): params = dict( pfast=20, pslow=50, ) def __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close #DC self.dc = DonchianChannels() # To keep track of pending orders and buy price/commission self.order = None self.buyprice = None self.buycomm = None # Simple Moving Average sma1 = bt.ind.SMA(period=self.p.pfast) # fast moving average sma2 = bt.ind.SMA(period=self.p.pslow) # slow moving average self.crossover = bt.ind.CrossOver(sma1, sma2) # crossover signal #ATR pureatr = bt.ind.ATR(period = 14) self.my_atr = pureatr # LOG 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)) # EXECUTED ORDER NOTIFICATIONS def notify_order(self,order): if order.status in [order.Submitted, order.Accepted]: return # Check if an order has been completed. Broker could reject if not enough cash if order.status in[order.Completed]: if order.isbuy(): self.log("BUY EXECUTED,Price: %.2f, Cost: %.2f, Comm %.2f" % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm elif order.issell(): self.log("SELL EXECUTED,Price: %.2f, Cost: %.2f, Comm %.2f" % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) self.log("Balance :%.2f" % (cerebro.broker.getvalue())) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log("Order Cancled/Margin/Rejected") self.order = None #Exit Operation Logs def notify_trade(self, trade): if not trade.isclosed: return self.log("[OPERATION PROFIT] GROSS: %.2f NET: %.2f, BALANCE: %.2f" % (trade.pnl, trade.pnlcomm,cerebro.broker.getvalue())) print() def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.2f' % self.dataclose[0]) #Check if an order is pending.. if yes, cant send a 2nd order. if self.order: return #LONG CONDITION if not self.position: if self.data[0] > self.dc.dch[0]: self.log('BUY CREATE, %.2f' % self.dataclose[0]) self.order = self.buy() elif (self.dataclose[1]) > self.dataclose[0]: # in the market & cross to the downside self.log("LONG CLOSED {}".format(self.dataclose[0])) self.close() # close long position #CEREBRO cerebro = bt.Cerebro() data = bt.feeds.YahooFinanceCSVData( dataname="oracle.csv", fromdate=datetime.datetime(2000,1,1), todate=datetime.datetime(2000,12,29), reverse=False) cerebro.adddata(data) cerebro.broker.set_cash(100000) cerebro.broker.setcommission(0.01) cerebro.addstrategy(TestStrategy) cerebro.addsizer(MaxRiskSizer, risk=0.5) print("Starting Portfolio :%.2f" % cerebro.broker.getvalue()) print() cerebro.run() print() print("Final Portfolio Value:%.2f" % cerebro.broker.getvalue()) cerebro.plot(style="candlestick",barup='green', bardown='red')
1. I am trying to make the system print out its 'Balance/Cash' after
"2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23"
so i put "self.log("Balance :%.2f" % (cerebro.broker.getvalue()))" after the buy/sell executed code, but the it printed out :Starting Portfolio :100000.00
2000-03-23, BUY CREATE, 38.64
2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23
2000-03-24, Balance :99604.21The starting portfolio is 100,000. Why is the balance after buy executed 99604?
100,000 - 99604.21 = 395.79. Where did 395.79 come from? the Commission issued is 499.23.2. I am trying to use ATR as my stoploss / exit long position. Can anyone make ATR into trailing stoploss. and I tried using multipler in the ATR, but it doesn't work
#ATR pureatr = bt.ind.ATR(period = 14) self.my_atr = pureatr
then
into
CLOSE LONG POSITION when current close crosses/touches previous day's close - 4*ATR
I modified the elif..... from
elif (self.dataclose[1]) > self.dataclose[0]:
to
elif (self.dataclose[0]) > self.dataclose[1]-(pureatr*4)):
(but it doesnt work)#LONG CONDITION if not self.position: if self.data[0] > self.dc.dch[0]: self.log('BUY CREATE, %.2f' % self.dataclose[0]) self.order = self.buy() elif (self.dataclose[0]) > self.dataclose[1]-(pureatr*4)): self.log("LONG CLOSED {}".format(self.dataclose[0])) self.close() # close long position
"C:\Users\2200214\PycharmProjects\Trade\venv\Scripts\python.exe C:/Users/2200214/PycharmProjects/Trade/Trader.py File "C:/Users/2200214/PycharmProjects/Trade/Trader.py", line 123 elif (self.dataclose[0]) > self.dataclose[1] - (pureatr * 4)): # in the market & cross to the downside ^ SyntaxError: invalid syntax Process finished with exit code 1"
3. Is there anything wrong with my code? if theres anything you can think of improving it please help me
-
@Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:
Where did 395.79 come from?
Evidently, it comes as an output from the code you written. If you expected something else, than please elaborate what did you expect.
@Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:
Is there anything wrong with my code?
Since you are asking, than probably yes. Usually if everything goes well, questions are not raised on this forum. But it is quite hard to understand what is the code which potentially has an error, you may want to repost and make it more clear for other members.
-
1 Balance Printing
Starting Portfolio :100000.00
2000-03-23, BUY CREATE, 38.64
2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23
2000-03-24, Balance :99604.21The starting portfolio is 100,000.
Then I made it print the balance after the "BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23"
The balance prints 99604.21Like I said, I am quite new and im trying to experiment with the tutorial. I am expecting either of these to be printed
- Portfolio - (Cost + Comm), which is 100,000- (49922.73 +499.23) = 49578.04
- Portfolio - Cost, which is 100,000 - 49922.73 = 50077.27
- Portfolio - Cost which is 99500.77
( I don't really expect number 3. to be printed but its the closest with the number printed)
But the balance prints 99604.21 , why?
-
Documentation says the following:
get_value(datas=None, mkt=False, lever=False)
Returns the portfolio value of the given datas (if datas is None, then the total portfolio value will be returned (alias: getvalue)
Evidently, that item 1 and item 2 shows the cash and cash considering no commission. Really not sure why do you expect
cash
to be printed with the call ofcerebro.broker.getvalue()
. Seems it is wrong.Item 3 seems equal item 2 by formula, why do you have different number?
The number
99604.21
from the original post is the value of the broker account, which includes cash and position value. -
Sorry it was typo.
It should be
- Portfolio - (Cost + Comm), which is 100,000- (49922.73 +499.23) = 49578.04
- Portfolio - Cost, which is 100,000 - 49922.73 = 50077.27
- Portfolio - Commission 100,000 - 499.23 which is 99500.77
"The number 99604.21 from the original post is the value of the broker account, which includes cash and position value."
I apologize, but I still do not get it. Then can you show me the calculation on how do you get 99604.21 .
and so,
How do I get the number "49578.04" (CASH - (Cost + Comm)) printed out?
The process goes like this right:- Long Signal
- "BUY CREATE"
- "BUY EXECUTED"
-->>How do I Print Cash Here (Portfolio - (Cost + Comm))<<-- - Long Exit Signal
- "LONG EXIT CREATE" (it's "Long Closed" on the original post)
- "SELL EXECUTED"
-
@Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:
Then can you show me the calculation on how do you get 99604.21
Should be
CASH LEFT + CLOSE x NUMBER OF SHARES = 99604.21
@Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:
How do I get the number "49578.04" (CASH - (Cost + Comm)) printed out?
-
ohhhh, I got it now, getcash() is the thing i was looking for!
thanksss!