2
\$\begingroup\$

I'm trying to capture profits and set a stop loss in my trading strategy. I want the stop loss to be set daily based on the past data and if the current price, i.e., price for the date falls below the stop_loss levels, sell the stock.

Below is the implementation for the same:

def logging_stop_loss(dict_dfs, result_df, stop_loss_levels):
 trades = []
 positions = {}
 for date_idx, date in enumerate(result_df.index):
 for stock in result_df.columns[result_df.iloc[date_idx]]:
 if (stock, date) not in positions:
 entry_price = dict_dfs['close'].at[date, stock]
 stop_loss_level = stop_loss_levels.at[date, stock]
 positions[(stock, date)] = {
 'entry_date': date,
 'entry_price': entry_price,
 'stop_loss': entry_price * (1 - stop_loss_level),
 'count': 0 # Initialize count to track days since entry
 }
 closed_positions = []
 for (stock, entry_date), pos in list(positions.items()):
 pos['count'] += 1
 future_date = result_df.index[min(date_idx + pos['count'], len(result_df) - 1)]
 current_price = dict_dfs['close'].at[future_date, stock]
 stop_loss_level = stop_loss_levels.at[future_date, stock]
 pos['stop_loss'] = current_price * (1 - stop_loss_level)
 if current_price < pos['stop_loss']:
 trades.append({
 'stock': stock,
 'entry_date': pos['entry_date'],
 'entry_price': pos['entry_price'],
 'exit_date': future_date,
 'exit_price': current_price,
 'return': (current_price - pos['entry_price']) / pos['entry_price']
 })
 closed_positions.append((stock, entry_date))
 for stock_entry in closed_positions:
 del positions[stock_entry]
 return pd.DataFrame(trades)

I have included my code which takes in stop loss calculated using certain logic for all the days. Another dataframe tells me about the trading dates, with TRUE value indicating I enter the trade, and FALSE value indicating I exit the trade. With this logic, I enter the trade and see if stop loss is met. If not, get going to the next date, if it is met, then sell else continue the loop till the end of the closing price dataframe is met. I will then log the entry and exit prices in a dataframe and save it.

This code returns empty logging_stop_loss dataframe, and it has no entry in the dataframe. This being the case, I want to understand what is causing the issue and rectify it. Can someone lead me to the direction which is causing this error and I can modify my logic accordingly.

toolic
14.5k5 gold badges29 silver badges203 bronze badges
asked Jun 15, 2024 at 5:22
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

wrong parameter name

def logging_stop_loss( ... , result_df, ... ):
 trades = []
 ...
 return pd.DataFrame(trades)

It's pretty clear we use trades to compose a result df.

Now, there may be some other function which carefully composed a result_df of whatever it was tasked with computing. But by the time it arrives here, it is definitely a gazinta, and not a gozouta; it's not like caller expects it to be mutated.

Please choose a more appropriate name, perhaps portfolio.

It wouldn't hurt to type annotate the signature. For example if I see portfolio: pd.DataFrame then there's no need for a three-character portfolio_df suffix.

.iloc[ ]

You're processing several fields of a row. Using .iloc on an index is less convenient than simply asking for a whole row at a time:

 for _, row in result_df.iterrows():

Then you can refer to row.date and so on.

scanning, merging

Your current approach works well enough. It makes a linear scan over the result_df portfolio, crossing that against positions, taking advantage of a bunch \$O(1)\$ constant time probe operations.

Now imagine you were going to solve this problem using SQL. You'd need at least one JOIN, right? Consider applying such a .merge() approach in the context of this pandas problem. By processing similarly sorted tables we can bring matching records together automatically, without need of a nested loop that goes looking for matches.

answered Jun 15, 2024 at 13:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.