Issue
Following is my sample dataset:
Price SL X
14 13.8 100
14.5 13.8 0
15 13.8 0
14.7 13.8 0
13.6 13.8 0
15 13.8 0
I want to create a new column that puts in remarks based on X
. I want it to have BUY
when X
is 100
. Followed by three rows of HOLD
and two rows of SELL
.
I am doing this using the following code:
cond = [
(df['X'] == 100),
(df['X'].shift(1) == 100),
(df['X'].shift(2) == 100),
(df['X'].shift(3) == 100),
(df['X'].shift(4) == 100),
(df['X'].shift(4) == 100),
]
choices = ['BUY', 'HOLD', 'HOLD', 'HOLD', 'SELL','SELL']
df['remarks'] = np.select(cond, choices)
Here is the outcome:
Price SL X remarks
14 13.8 100 BUY
14.5 13.8 0 HOLD
15 13.8 0 HOLD
14.7 13.8 0 HOLD
13.6 13.8 0 SELL
15 13.8 0 SELL
However, I want to add another option of Stopped Out
when Price < SL
like in the fifth row. How do I assign Stopped Out
the highest priority overall?
Desired outcome:
Price SL X remarks
14 13.8 100 BUY
14.5 13.8 0 HOLD
15 13.8 0 HOLD
14.7 13.8 0 HOLD
13.6 13.8 0 Stopped Out
15 13.8 0 Stopped Out
14.5 13.8 0
15 14.7 100 BUY
14.8 14.7 0 HOLD
13 14.7 0 Stopped Out
I would want the remarks
to end once the Stopped Out
shows up. And they should come up only after a BUY
and not sometime before it.
Solution
First add default=''
to your current np.select
:
cond = [
(df['X'] == 100),
(df['X'].shift(1) == 100),
(df['X'].shift(2) == 100),
(df['X'].shift(3) == 100),
(df['X'].shift(4) == 100),
(df['X'].shift(4) == 100),
]
choices = ['BUY', 'HOLD', 'HOLD', 'HOLD', 'SELL','SELL']
df['remarks'] = np.select(cond, choices, default='')
# ^^^^^^^^^^ add this
Then groupby
each BUY
block and create a stop
counter using a double cumsum
:
buy = df['X'].eq(100).cumsum()
df['stop'] = df.groupby(buy, sort=False).apply(lambda g: g['Price'].lt(g['SL']).cumsum().cumsum()).array
# Price SL X remarks stop
# 0 14.0 13.8 100 BUY 0
# 1 14.5 13.8 0 HOLD 0
# 2 15.0 13.8 0 HOLD 0
# 3 14.7 13.8 0 HOLD 0
# 4 13.6 13.8 0 SELL 1
# 5 15.0 13.8 0 2
# 6 14.5 13.8 0 3
# 7 15.0 14.7 100 BUY 0
# 8 14.8 14.7 0 HOLD 0
# 9 13.0 14.7 0 HOLD 1
Now mask
the remarks
wherever stop
is 1 or 2:
df['remarks'] = df['remarks'].mask(df['stop'].isin([1, 2]), 'Stopped Out')
# Price SL X remarks
# 0 14.0 13.8 100 BUY
# 1 14.5 13.8 0 HOLD
# 2 15.0 13.8 0 HOLD
# 3 14.7 13.8 0 HOLD
# 4 13.6 13.8 0 Stopped Out
# 5 15.0 13.8 0 Stopped Out
# 6 14.5 13.8 0
# 7 15.0 14.7 100 BUY
# 8 14.8 14.7 0 HOLD
# 9 13.0 14.7 0 Stopped Out
Answered By - tdy
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.