In our last part of Opening Range, We had used the nsefetch()
function to fetch some NSE URLs directly. Although, You can write functions using the broker’s API but We will stick with NSE APIs for now.
In the last upgrade of NSEPython, We got a function named nse_get_top_gainers()
. So, Lets replace our previous methodology using this function.
Now if You do –
gainers = nse_get_top_gainers()
gainers.drop(gainers.columns.difference(["symbol","high_price","low_price","ltp"]), 1, inplace=True)
gainers=gainers.head(5)
print(gainers)
symbol
0 IBULHSGFIN
1 ADANIENT
2 BHARATFORG
3 LICHSGFIN
4 UBL
It is because of the name of the columns changes in the data we get from this function.
So, just inspect the output of gainers
. You may need to use set the max_columns
attribute to see all the table names as it will be hidden ...
as it is a long output.
Check here – aeron7.github.io/nsepython/documentation/nsefetch.html#parsing-the-data-with-pandas
pd.set_option('display.max_columns', None) # or 1000
gainers = nse_get_top_gainers()
gainers.drop(gainers.columns.difference(["symbol","dayHigh","dayLow","lastPrice"]), 1, inplace=True)
gainers=gainers.head(5)
print(gainers)
symbol dayHigh dayLow lastPrice
0 IBULHSGFIN 272.75 227.75 263.15
1 ADANIENT 1713.55 1585.8 1706
2 BHARATFORG 758.65 695.1 749.85
3 LICHSGFIN 537.95 501 529
4 UBL 1378 1264.5 1340.65
Now the trick (as discussed already) here is –
The high
and low
of the symbols at just the end of the 15th minute of market start is the high and low of the first 15 min candle of the day.
So, We need to run this program at 9:30:01
as our market starts at 9:15:00
Adding the loser’s set of stock is similar. You can code out a method from raw APIs as we did in 1st part.
Or, You can see the functions from here – aeron7.github.io/nsepython/documentation/nsetools.html#top-losers-gainers
The input –
losers = nse_get_top_losers()
losers.drop(losers.columns.difference(["symbol","dayHigh","dayLow","lastPrice"]), 1, inplace=True)
losers=losers.head(5)
print(losers)
symbol dayHigh dayLow lastPrice
155 NESTLEIND 17706.4 17380 17443
154 MARICO 495.5 485 487
152 TORNTPOWER 440.9 430.25 431.6
153 RBLBANK 220.35 211.25 215
151 ICICIGI 1481 1444 1450.2
gainers
and losers
data frames into one to prepare our watchlist.
watchlist = gainers
watchlist = watchlist.append(losers)
print(watchlist)
symbol dayHigh dayLow lastPrice
0 IBULHSGFIN 272.75 227.75 263.15
1 ADANIENT 1713.55 1585.8 1706
2 BHARATFORG 758.65 695.1 749.85
3 LICHSGFIN 537.95 501 529
4 UBL 1378 1264.5 1340.65
155 NESTLEIND 17706.4 17380 17443
154 MARICO 495.5 485 487
152 TORNTPOWER 440.9 430.25 431.6
153 RBLBANK 220.35 211.25 215
151 ICICIGI 1481 1444 1450.2
So, it is taking the index
from the last tables too. It looks weird and it will end as problematic in the code if we extend to more complexities right?
So, Like Thanos’s Plan, We need to start with a blank data frame.
watchlist = pd.DataFrame()
watchlist = pd.DataFrame()
watchlist = watchlist.append(gainers, ignore_index=True)
watchlist = watchlist.append(losers, ignore_index=True)
print(watchlist)
symbol dayHigh dayLow lastPrice
0 IBULHSGFIN 272.75 227.75 263.15
1 ADANIENT 1713.55 1585.8 1706
2 BHARATFORG 758.65 695.1 749.85
3 LICHSGFIN 537.95 501 529
4 UBL 1378 1264.5 1340.65
5 NESTLEIND 17706.4 17380 17443
6 MARICO 495.5 485 487
7 TORNTPOWER 440.9 430.25 431.6
8 RBLBANK 220.35 211.25 215
9 ICICIGI 1481 1444 1450.2 )
The goal is simple now, firing 20 orders. (10 Buy orders + 10 Sell orders)
Now if you do BO
order that allows putting the Stop Loss inside the order itself, It will be done within 20 orders.
But, if you do MIS
order, then it will be quite a headache as We need to fire 40 orders.
Because every order will be –
The eerie thing here is –
MIS
.Remember that the SL in case of the Buy trade’s trigger is “Sell trade’s trigger point”.
So, It will “automagically” do its job within 20 orders itself if you add a new rule in the strategy –
It will either trigger one time i.e. If buy trade is triggered, then it will ignore the sell trade’s trigger afterward and vice-versa.
We shall use get_fno_lot_sizes()
function of NSEPython.
Maximum loss is the difference between the high and low points of the stocks. Correct?
So, calculating the max loss in terms of point by substracting two columns in the Pandas table –
watchlist = pd.DataFrame()
watchlist = watchlist.append(gainers, ignore_index=True)
watchlist = watchlist.append(losers, ignore_index=True)
watchlist["maxLossPt"] = watchlist["dayHigh"].astype(float)-watchlist["dayLow"].astype(float)
print(watchlist)
symbol dayHigh dayLow lastPrice maxLossPt
0 IBULHSGFIN 272.75 227.75 263.15 45.00
1 ADANIENT 1713.55 1585.8 1706 127.75
2 BHARATFORG 758.65 695.1 749.85 63.55
3 LICHSGFIN 537.95 501 529 36.95
4 UBL 1378 1264.5 1340.65 113.50
5 NESTLEIND 17706.4 17380 17443 326.40
6 MARICO 495.5 485 487 10.50
7 TORNTPOWER 440.9 430.25 431.6 10.65
8 RBLBANK 220.35 211.25 215 9.10
9 ICICIGI 1481 1444 1450.2 37.00
The next step is adding the lot size
.
We shall be using np.vectorize()
function.
watchlist["lotsize"] = np.vectorize(nse_get_fno_lot_sizes)(watchlist["symbol"])
It will call the nse_get_fno_lot_sizes()
function to each of the elements of symbol
column of watchlist
.
The output will be –
symbol dayHigh dayLow lastPrice maxLossPt lotsize
0 IBULHSGFIN 272.75 227.75 263.15 45.00 3100
1 ADANIENT 1713.55 1585.8 1706 127.75 1000
2 BHARATFORG 758.65 695.1 749.85 63.55 1500
3 LICHSGFIN 537.95 501 529 36.95 2000
4 UBL 1378 1264.5 1340.65 113.50 700
5 NESTLEIND 17706.4 17380 17443 326.40 50
6 MARICO 495.5 485 487 10.50 2000
7 TORNTPOWER 440.9 430.25 431.6 10.65 1500
8 RBLBANK 220.35 211.25 215 9.10 2900
9 ICICIGI 1481 1444 1450.2 37.00 425
Now, getting the maxLoss
is easy. We just need to multiply the maxLossPt
and lotsize
.
Now, I often tell you to ignore the trade if the stop loss is more than 6000 INR
in our Entropy Setups. You can see how to achieve that.
So, the final code will be –
symbol dayHigh dayLow lastPrice maxLossPt lotsize maxLoss
0 IBULHSGFIN 272.75 227.75 263.15 45.00 3100 139500.0
1 ADANIENT 1713.55 1585.8 1706 127.75 1000 127750.0
2 BHARATFORG 758.65 695.1 749.85 63.55 1500 95325.0
3 LICHSGFIN 537.95 501 529 36.95 2000 73900.0
4 UBL 1378 1264.5 1340.65 113.50 700 79450.0
5 NESTLEIND 17706.4 17380 17443 326.40 50 16320.0
6 MARICO 495.5 485 487 10.50 2000 21000.0
7 TORNTPOWER 440.9 430.25 431.6 10.65 1500 15975.0
8 RBLBANK 220.35 211.25 215 9.10 2900 26390.0
9 ICICIGI 1481 1444 1450.2 37.00 425 15725.0
The next part is Position Sizing.
Suppose, You have allocated exposure of 1,00,000 INR to this strategy and hence 10,000 INR to each of the stocks. (There are 10 stocks right?)
So, We define the variable –
quant = 10000
round down
and gives the output as quantity we will use to buy or sell.
def get_quantity(lastPrice):
return math.floor(quant/float(lastPrice))
lotsize
with quantity and our max loss calculation stays same –
watchlist["lotsize"] = np.vectorize(get_quantity)(watchlist["lastPrice"])
watchlist["maxLoss"] = watchlist["maxLossPt"]*watchlist["lotsize"]
print(watchlist)
symbol dayHigh dayLow lastPrice maxLossPt lotsize maxLoss
0 IBULHSGFIN 272.75 227.75 263.15 45.00 38 1710.00
1 ADANIENT 1713.55 1585.8 1706 127.75 5 638.75
2 BHARATFORG 758.65 695.1 749.85 63.55 13 826.15
3 LICHSGFIN 537.95 501 529 36.95 18 665.10
4 UBL 1378 1264.5 1340.65 113.50 7 794.50
5 NESTLEIND 17706.4 17380 17443 326.40 0 0.00
6 MARICO 495.5 485 487 10.50 20 210.00
7 TORNTPOWER 440.9 430.25 431.6 10.65 23 244.95
8 RBLBANK 220.35 211.25 215 9.10 46 418.60
9 ICICIGI 1481 1444 1450.2 37.00 6 222.00
There is no max loss in Nestle because We are too broke to buy or sell it at all.
You can also fire less than 10 trades based on complex calculations done on this maxLoss
part.
In this case, the maxLoss
will be attended if all the scrips hit their SL after triggering buy and sell.
If You do –
print(round(watchlist["maxLoss"].sum(),2))
5730.05
So, that’s like 5.73% of 1L capital. You may want to take the maximum risk on the notion of your net quant on top of all these. Right?
Like I will not lose more than 3% of 1L capital.
Then you can design to take the first few trades and check if maxLoss
is more than 3000, skip the rest of the trades.
Now all You have to do is to fire the order to the broker using either of the methods discussed above. We will discuss this thoroughly in the next part but here is some content for you so that You can try.
If You have followed Krishna’s AliceAPI code, You can see there are two ways.
MIS Stop Loss Limit Order –
#TransactionType.Buy, OrderType.StopLossLimit, ProductType.Intraday
print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%10%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
print(
alice.place_order(transaction_type = TransactionType.Buy,
instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
quantity = 1,
order_type = OrderType.StopLossLimit,
product_type = ProductType.Intraday,
price = 8.0,
trigger_price = 8.0,
stop_loss = None,
square_off = None,
trailing_sl = None,
is_amo = False)
)
Bracket Order –
# TransactionType.Buy, OrderType.StopLossLimit, ProductType.BracketOrder
print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%11%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
print(
alice.place_order(transaction_type = TransactionType.Buy,
instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
quantity = 1,
order_type = OrderType.StopLossLimit,
product_type = ProductType.BracketOrder,
price = 8.0,
trigger_price = 8.0,
stop_loss = 1.0,
square_off = 1.0,
trailing_sl = 20,
is_amo = False)
)
So, All you have to do is implement an efficient usage of for
loop or np.array()
method of pandas.
In the next part, We shall discuss about the functions provided by the user
and more cases and alternative iterations.
In case, You are following my code snippets and landed in error, You can use this Final Code Snippet which includes the complete block done till now.
from nsepython import *
pd.set_option('display.max_columns', None) # or 1000
pd.set_option('display.max_rows', None) # or 1000
pd.set_option('display.max_colwidth', -1) # or 199
pd.options.mode.chained_assignment = None # default='warn' https://stackoverflow.com/questions/20625582/how-to-deal-with-settingwithcopywarning-in-pandas
gainers = nse_get_top_gainers()
gainers.drop(gainers.columns.difference(["symbol","dayHigh","dayLow","lastPrice"]), 1, inplace=True)
gainers=gainers.head(5)
#print(gainers)
losers = nse_get_top_losers()
losers.drop(losers.columns.difference(["symbol","dayHigh","dayLow","lastPrice"]), 1, inplace=True)
losers=losers.head(5)
#print(losers)
# watchlist = gainers
# watchlist = watchlist.append(losers)
# print(watchlist)
# watchlist = pd.DataFrame()
# watchlist = watchlist.append(gainers, ignore_index=True)
# watchlist = watchlist.append(losers, ignore_index=True)
# print(watchlist)
import numpy as np
watchlist = pd.DataFrame()
watchlist = watchlist.append(gainers, ignore_index=True)
watchlist = watchlist.append(losers, ignore_index=True)
watchlist["maxLossPt"] = watchlist["dayHigh"].astype(float)-watchlist["dayLow"].astype(float)
watchlist["lotsize"] = np.vectorize(nse_get_fno_lot_sizes)(watchlist["symbol"])
watchlist["maxLoss"] = watchlist["maxLossPt"]*watchlist["lotsize"]
#print(watchlist)
import math
quant = 10000
def get_quantity(lastPrice):
return math.floor(quant/float(lastPrice))
watchlist["lotsize"] = np.vectorize(get_quantity)(watchlist["lastPrice"])
watchlist["maxLoss"] = watchlist["maxLossPt"]*watchlist["lotsize"]
print(watchlist)
print(round(watchlist["maxLoss"].sum(),2))