Cash, value, size, target orders, HELP T_T
-
Hello everyone, the post is long but the questions very simple!
In trying to understand what cash, portfolio value, data value and position size were, I've cooked up a simple strategy : buy at this date, sale at this date.
The problem I don't understand at all what's happening.The way I understand it, correct me If I am wrong:
-Cash: is the money I have to buy shares or contracts or whatever.
-Portfolio value: is the cash plus the value of the assets I've bought or that I am shorting, in this regard portfolio value can be smaller than cash amount
-Data value: is the value of the specific asset I am trading when I only have one asset, it can be negative if I am shorting the asset
-Position : Am I involved with the market or not ? Am I buying or selling or whatever .
-Position size : the number of shares, cryptocoins, contracts I am trading.The strategy :
import backtrader as bt from datetime import datetime class shortStrat(bt.Strategy): # Moving average parameters params = (('pfast',20),('pslow',50),) def __init__(self): self.dataclose = self.datas[0].close self.datahigh = self.datas[0].high self.datalow = self.datas[0].low # Order variable will contain ongoing order details/status self.order = None def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.date(0) print(f'{dt.isoformat()} {txt}') def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # An active Buy/Sell order has been submitted/accepted - 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.price:.2f}') elif order.issell(): self.log(f'SELL EXECUTED, {order.executed.price:.2f}') self.bar_executed = len(self) #the bar at which the order is completd I guess elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Reset orders self.order = None def next(self): if self.order: return print('posistion : {}'.format(self.position.size)) print('portvalue : {}'.format(self.broker.get_value())) print('cash : {}'.format(self.broker.get_cash())) print('dataval : {}'.format(self.broker.get_value([self.data]))) # Check if we are in the market if not self.position: # We are not in the market, look for a signal to OPEN trades if self.datas[0].datetime.date()==datetime(2018,1,1).date() : self.order = self.order_target_percent(target=1) # we are in the market elif self.datas[0].datetime.date()==datetime(2018,1,10).date() : self.order = self.order_target_percent(target=-1) elif self.datas[0].datetime.date()==datetime(2018,1,1).date() : self.order = self.order_target_percent(target=1)
The bot:
from strategies.crossOver import MAcrossover import backtrader as bt import datetime import numpy as np from strategies.strat import barycentreStrat import csv from strategies.ShortStrat import shortStrat import pandas as pd dateOne="1 Jan, 2017" dateTwo="1 Jun, 2021" symbol="BNBUSDT" interval="1d" cerebro = bt.Cerebro(stdstats=True,optreturn=False,maxcpus=1)#optreturn=False data = bt.feeds.GenericCSVData( timeframe=bt.TimeFrame.Days, compression=1, dataname='data\crypto\ShortData.csv', nullvalue=0.0, dtformat=('%m/%d/%Y'), datetime=0, open=1, high=2, low=3, close=4, time=-1, volume=-1, openinterest=-1 ) dayData=cerebro.adddata(data) cerebro.addstrategy(shortStrat) if __name__ == '__main__': cerebro.broker.set_cash(90000) start_portfolio_value = cerebro.broker.getvalue() game=cerebro.run() end_portfolio_value = cerebro.broker.getvalue() pnl = end_portfolio_value - start_portfolio_value print(f'Starting Portfolio Value: {start_portfolio_value:2f}') print(f'Final Portfolio Value: {end_portfolio_value:2f}') print(f'PnL: {pnl:.2f}') cerebro.plot(style="candlestick", volume=False) exit()
the log :
posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 2018-01-02 BUY EXECUTED, 100.00 posistion : 473 portvalue : 90000.0 cash : 42700.0 dataval : 47300.0 posistion : 473 portvalue : 142030.0 cash : 42700.0 dataval : 99330.0 posistion : 473 portvalue : 146760.0 cash : 42700.0 dataval : 104060.0 posistion : 473 portvalue : 151490.0 cash : 42700.0 dataval : 108790.0 posistion : 473 portvalue : 156220.0 cash : 42700.0 dataval : 113520.0 posistion : 473 portvalue : 160950.0 cash : 42700.0 dataval : 118250.0 posistion : 473 portvalue : 165680.0 cash : 42700.0 dataval : 122980.0 posistion : 473 portvalue : 170410.0 cash : 42700.0 dataval : 127710.0 posistion : 473 portvalue : 175140.0 cash : 42700.0 dataval : 132440.0 2018-01-11 SELL EXECUTED, 190.00 posistion : -625 portvalue : 76320.0 cash : 251320.0 dataval : -175000.0 posistion : -625 portvalue : 82570.0 cash : 251320.0 dataval : -168750.0 posistion : -625 portvalue : 88820.0 cash : 251320.0 dataval : -162500.0 posistion : -625 portvalue : 95070.0 cash : 251320.0 dataval : -156250.0 posistion : -625 portvalue : 101320.0 cash : 251320.0 dataval : -150000.0 posistion : -625 portvalue : 107570.0 cash : 251320.0 dataval : -143750.0 posistion : -625 portvalue : 113820.0 cash : 251320.0 dataval : -137500.0 posistion : -625 portvalue : 120070.0 cash : 251320.0 dataval : -131250.0 posistion : -625 portvalue : 126320.0 cash : 251320.0 dataval : -125000.0 posistion : -625 portvalue : 132570.0 cash : 251320.0 dataval : -118750.0 posistion : -625 portvalue : 132570.0 cash : 251320.0 dataval : -118750.0 2018-01-02 BUY EXECUTED, 110.00 posistion : 697 portvalue : 245300.0 cash : 105900.0 dataval : 139400.0 posistion : 697 portvalue : 252270.0 cash : 105900.0 dataval : 146370.0 posistion : 697 portvalue : 259240.0 cash : 105900.0 dataval : 153340.0 posistion : 697 portvalue : 266210.0 cash : 105900.0 dataval : 160310.0 posistion : 697 portvalue : 273180.0 cash : 105900.0 dataval : 167280.0 posistion : 697 portvalue : 280150.0 cash : 105900.0 dataval : 174250.0 posistion : 697 portvalue : 287120.0 cash : 105900.0 dataval : 181220.0 posistion : 697 portvalue : 294090.0 cash : 105900.0 dataval : 188190.0 posistion : 697 portvalue : 301060.0 cash : 105900.0 dataval : 195160.0 2018-01-11 SELL EXECUTED, 190.00 posistion : -1075 portvalue : 141580.0 cash : 442580.0 dataval : -301000.0 posistion : -1075 portvalue : 152330.0 cash : 442580.0 dataval : -290250.0 posistion : -1075 portvalue : 163080.0 cash : 442580.0 dataval : -279500.0 posistion : -1075 portvalue : 173830.0 cash : 442580.0 dataval : -268750.0 posistion : -1075 portvalue : 184580.0 cash : 442580.0 dataval : -258000.0 posistion : -1075 portvalue : 195330.0 cash : 442580.0 dataval : -247250.0 posistion : -1075 portvalue : 206080.0 cash : 442580.0 dataval : -236500.0 posistion : -1075 portvalue : 216830.0 cash : 442580.0 dataval : -225750.0 posistion : -1075 portvalue : 227580.0 cash : 442580.0 dataval : -215000.0 posistion : -1075 portvalue : 238330.0 cash : 442580.0 dataval : -204250.0 Starting Portfolio Value: 90000.000000 Final Portfolio Value: 238330.000000 PnL: 148330.00
the test data (notice the dates are bogus and repeat themeselves):
1/2/2018,110,210,100,200 1/3/2018,120,220,110,210 1/4/2018,130,230,120,220 1/5/2018,140,240,130,230 1/6/2018,150,250,140,240 1/7/2018,160,260,150,250 1/8/2018,170,270,160,260 1/9/2018,180,280,170,270 1/10/2018,190,290,180,280 1/11/2018,190,290,180,280 1/12/2018,180,280,170,270 1/13/2018,170,270,160,260 1/14/2018,160,260,150,250 1/15/2018,150,250,140,240 1/16/2018,140,240,130,230 1/17/2018,130,230,120,220 1/18/2018,120,220,110,210 1/19/2018,110,210,100,200 1/20/2018,100,200,90,190 1/1/2018,100,200,90,190 1/2/2018,100,300,0,100 1/3/2018,120,220,110,210 1/4/2018,130,230,120,220 1/5/2018,140,240,130,230 1/6/2018,150,250,140,240 1/7/2018,160,260,150,250 1/8/2018,170,270,160,260 1/9/2018,180,280,170,270 1/10/2018,190,290,180,280 1/11/2018,190,290,180,280 1/12/2018,180,280,170,270 1/13/2018,170,270,160,260 1/14/2018,160,260,150,250 1/15/2018,150,250,140,240 1/16/2018,140,240,130,230 1/17/2018,130,230,120,220 1/18/2018,120,220,110,210 1/19/2018,110,210,100,200 1/20/2018,100,200,90,190 1/1/2018,100,200,90,190 1/2/2018,110,210,100,200 1/3/2018,120,220,110,210 1/4/2018,130,230,120,220 1/5/2018,140,240,130,230 1/6/2018,150,250,140,240 1/7/2018,160,260,150,250 1/8/2018,170,270,160,260 1/9/2018,180,280,170,270 1/10/2018,190,290,180,280 1/11/2018,190,290,180,280 1/12/2018,180,280,170,270 1/13/2018,170,270,160,260 1/14/2018,160,260,150,250 1/15/2018,150,250,140,240 1/16/2018,140,240,130,230 1/17/2018,130,230,120,220 1/18/2018,120,220,110,210 1/19/2018,110,210,100,200 1/20/2018,100,200,90,190
I understand nothing :
if we focus on the first buy order :# Check if we are in the market if not self.position: # We are not in the market, look for a signal to OPEN trades if self.datas[0].datetime.date()==datetime(2018,1,1).date() : self.order = self.order_target_percent(target=1)
the log :
posistion : 0 portvalue : 90000.0 cash : 90000.0 dataval : 0.0 2018-01-02 BUY EXECUTED, 100.00 posistion : 473 portvalue : 90000.0 cash : 42700.0 dataval : 47300.0
why is it buying only 473 SHARES and not using all my cash when I specified 1 in the target percent order ?
next the second order :
here, I am trying to reverse my position, obviously doing a bad job...
# we are in the market elif self.datas[0].datetime.date()==datetime(2018,1,10).date() : self.order = self.order_target_percent(target=-1)
posistion : 473 portvalue : 175140.0 cash : 42700.0 dataval : 132440.0 2018-01-11 SELL EXECUTED, 190.00 posistion : -625 portvalue : 76320.0 cash : 251320.0 dataval : -175000.0
What I understand is that before the sell, the size is 473, this is valued to 132440 which is approximately 0.75 * portvalue, so since I want my position to become -1, cerebro does something like -1/0.75*473 =630 to compute the new position. Once calculated it sells my 423 shares at the close price of the current bar ( since I did not use a limit order ?) which is 280 and not 190 as specified by order.executed.price ??? and it shorts approximately 630 SHARES, the best it can which gives a -625 size???
What is this 251320 cash value ?? why do I have so much cash after closing my position ? shouldn't i be 132440+42700 ?As you understood, I am a newbie trader/ programmer, but I really tried reading the docs..
Please help me !!!
-
@youssef-0 I have a similar problem. The cash become very big, and I don't unerstand why.
I add this notification into my strategydef notify_trade(self, trade): self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f, size %.2f, price %.2f, value %.2f' % (trade.pnl, trade.pnlcomm, trade.size, trade.price, trade.value)) def notify_cashvalue(self,cash, value): self.log('cash %.2f, portfolio %.2f' % (cash, value)) def order_log(self,order): return ('EXECUTED ref :%.2f, Price: %.2f, Value: %.2f, Comm %.2f, pnl: %.2f, size: %.2f' % (order.ref, order.executed.price, order.executed.value, order.executed.comm, order.executed.pnl, order.executed.size )) def notify_order(self, order): 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('BUY' + self.order_log(order)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL' + self.order_log(order)) 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.order = None
2021-08-13 cash 1676.61, portfolio 30263.15 2021-08-16 BUYEXECUTED ref :5.00, Price: 114.90, Value: 114.90, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 BUYEXECUTED ref :6.00, Price: 22.87, Value: 22.87, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 BUYEXECUTED ref :7.00, Price: 114.90, Value: 114.90, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 BUYEXECUTED ref :8.00, Price: 22.87, Value: 22.87, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 BUYEXECUTED ref :9.00, Price: 114.90, Value: 114.90, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 BUYEXECUTED ref :10.00, Price: 114.90, Value: 114.90, Comm 0.00, pnl: 0.00, size: 1.00 2021-08-16 SELLEXECUTED ref :11.00, Price: 22.87, Value: 22.44, Comm 0.00, pnl: 0.43, size: -1.00 2021-08-16 BUYEXECUTED ref :12.00, Price: 114.90, Value: 229.80, Comm 0.00, pnl: 0.00, size: 2.00 2021-08-16 SELLEXECUTED ref :13.00, Price: 22.87, Value: 67.32, Comm 0.00, pnl: 1.29, size: -3.00 2021-08-16 BUYEXECUTED ref :14.00, Price: 114.90, Value: 229.80, Comm 0.00, pnl: 0.00, size: 2.00 2021-08-16 SELLEXECUTED ref :15.00, Price: 22.87, Value: 67.32, Comm 0.00, pnl: 1.29, size: -3.00 2021-08-16 cash 871.76, portfolio 30256.88
I can observe some relation between the numbres:
tmp@ val sell_1 = 7662.03 * 2 + 5683.00 + 3 * -7659.00 // from the Value of SELLEXECUTED above sell_1: Double = -1969.9400000000023 tmp@ val sell_2 = 7662.03 * 2 + 5683.00 + 3 * 7659.00 // from the Value of SELLEXECUTED above sell_2: Double = 43984.06 tmp@ val cash_init = 4837.12 cash_init: Double = 4837.12 tmp@ val cash_final = 50746.72 cash_final: Double = 50746.72 tmp@ val change = cash_final - cash_init change: Double = 45909.6
size = 45 // from size of trade above
sell_2 - sell_1
= (7662.03 * 2 + 5683.00 + 3 * 7659.00) - (7662.03 * 2 + 5683.00 + 3 * -7659.00)
= 3 * 7659 - 3 * -7659
= 3 * 7659 + (3 * 7659)
= 6 * 7659
= 45954
= change + sizeBut I can't understand the logic
-
@dev590t I have use the wrong output in my message above. This is the right ouput:
2021-08-23 cash 4837.12, portfolio 30015.36 .. 2021-08-24 SELLEXECUTED ref :75.00, Price: 22.20, Value: 7662.03, Comm 0.00, pnl: -25.23, size: -344.00 2021-08-24 SELLEXECUTED ref :77.00, Price: 22.20, Value: 7662.03, Comm 0.00, pnl: -25.23, size: -344.00 2021-08-24 SELLEXECUTED ref :79.00, Price: 22.20, Value: 5683.00, Comm 0.00, pnl: -22.00, size: -345.00 2021-08-24 SELLEXECUTED ref :81.00, Price: 22.20, Value: -7659.00, Comm 0.00, pnl: 0.00, size: -345.00 2021-08-24 SELLEXECUTED ref :83.00, Price: 22.20, Value: -7659.00, Comm 0.00, pnl: 0.00, size: -345.00 2021-08-24 SELLEXECUTED ref :85.00, Price: 22.20, Value: -7659.00, Comm 0.00, pnl: 0.00, size: -345.00 2021-08-24 OPERATION PROFIT, GROSS -105.16, NET -105.16, size 0.00, price 22.27, value 0.00 2021-08-24 OPERATION PROFIT, GROSS 0.00, NET 0.00, size -45.00, price 22.20, value -999.00 2021-08-24 cash 50746.72, portfolio 30017.04
-
@youssef-0 If I add
cerebro.broker.set_shortcash(False)
the cash will not become very big : https://www.backtrader.com/blog/posts/2016-12-06-shorting-cash/shorting-cash/#in-action.I still don't know why, but it seems this instructions solve my problem:
- without
cerebro.broker.set_shortcash(False)
:
2021-08-17 SELLEXECUTED ref :18.00, Price: 22.82, Value: 57152.13, Comm 0.00, pnl: -124.95, size: -2499.00 2021-08-17 SELLEXECUTED ref :22.00, Price: 22.82, Value: -462.86, Comm 0.00, pnl: -62.00, size: -2503.00 2021-08-17 SELLEXECUTED ref :26.00, Price: 22.82, Value: -57141.28, Comm 0.00, pnl: 0.00, size: -2504.00 2021-08-17 SELLEXECUTED ref :30.00, Price: 22.82, Value: -57186.92, Comm 0.00, pnl: 0.00, size: -2506.00 2021-08-17 SELLEXECUTED ref :34.00, Price: 22.82, Value: -85323.98, Comm 0.00, pnl: 0.00, size: -3739.00 2021-08-17 BUYEXECUTED ref :35.00, Price: 127.52, Value: 28181.92, Comm 0.00, pnl: 0.00, size: 221.00 2021-08-17 SELLEXECUTED ref :39.00, Price: 22.82, Value: -57209.74, Comm 0.00, pnl: 0.00, size: -2507.00 2021-08-17 OPERATION PROFIT, GROSS -186.95, NET -186.95, size 0.00, price 22.87, value 0.00 2021-08-17 OPERATION PROFIT, GROSS 0.00, NET 0.00, size -1263.00, price 22.82, value -28821.66 2021-08-17 OPERATION PROFIT, GROSS 0.00, NET 0.00, size 221.00, price 127.52, value 28181.92 2021-08-17 cash 343864.16, portfolio 29343.80
- with
cerebro.broker.set_shortcash(False)
:
2021-08-17 SELLEXECUTED ref :15.00, Price: 120.63, Value: 28468.68, Comm 0.00, pnl: 0.00, size: -236.00 2021-08-17 BUYEXECUTED ref :16.00, Price: 22.82, Value: 28433.72, Comm 0.00, pnl: 0.00, size: 1246.00 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 Order Canceled/Margin/Rejected 2021-08-17 OPERATION PROFIT, GROSS 0.00, NET 0.00, size 0.00, price 120.63, value 0.00 2021-08-17 OPERATION PROFIT, GROSS 0.00, NET 0.00, size 1246.00, price 22.82, value 28433.72 2021-08-17 cash 1548.99, portfolio 29995.17
- without