Easy way to calculate Profit per trade in python

I’m requesting some help with being able to calculate the profit per trade in Python. I’m trying to do it with the info in get_activities() but it seems to be more complicated than I was expecting. Anybody have some code?

try php its less of a headach

Do you mean like — the avg trade ? Or simply the profit? I would look at portfolio / position object, I have a trailstop class that tracks unrealized PNL using the api.list_positions() object, and looping through the positions.
Ex:
avgTrade = sum([pos.realized_pl for pos in api.list_positions()]) / len(api.list_positions())
Written out —
totalPNL = 0
for pos in api.list_positions():
realPNL = pos.realized_pl
totalPNL += realPNL

n_positions = len(api.list_positions)
avg = totalPNL/n_positions

Could also take portfolio realized pl, divide it by orders that match the time period your measuring, etc. Lots of ways to do this.

Thank you. That’s not quite what I was looking for. I was looking for an easy way to list how much profit was made on each individual trade . For example:

I bought MSFT for $100 6/1, sold MSFT for $105 6/5 for $5.00 profit.
I bought AAPL for $90 6/1, sold AAPL for $100 6/5 for $10.00 profit. etc

It seems you have to loop through the api.get_activities() in order to first figure out how much you had sold it for, then loop through again to see what the initial investment was and return the difference. I’ll post what I came up with so far.

This is what I came up with so far.

def get_profit_per_stock():
    activities = api.get_activities()
    buys = []
    sells = []
    pnl_list = []

    for each in activities:
        symbol = each.symbol

        # Create list of all the buys
        if each.symbol == symbol and each.side == 'buy':
            cash_spent = float(each.price) * float(each.qty)
            buys.append((each.symbol, cash_spent))

        # Create list of sells
        if each.symbol == symbol and each.side == 'sell':
            cash_taken = float(each.price) * float(each.qty)
            sells.append((each.symbol, cash_taken))

        # In case there are partial fills in the buys list this will merge them
        d = {x: 0 for x, _ in buys}
        for name, num in buys: d[name] += num
        merged_buys = list(map(tuple, d.items()))

        # In case there are partial fills in the sells list this will merge them
        e = {x: 0 for x, _ in sells}
        for name, num in sells: e[name] += num
        merged_sells = list(map(tuple, e.items()))

        # This is a list of tuples listing (symbol, total money spent on the buys, total money spent on the sells)
        transaction_list = [x + y[1:] for x in merged_sells for y in merged_buys if x[0] == y[0]]

        # This simply gives you the Profit/Loss for each symbol in the transaction list
        for each in transaction_list:
            symbol = each[0]
            pnl = round(float(each[1]) - float(each[2]), 2)
            pnl_list.append([symbol, pnl])

        return pnl_list

Oh — didn’t realize you meant like — past orders.
Sorry about that.
I still think you could loop through orders, and match symbols / orders that way — or still possibly use the unrealized_pl tags.
It’s not something I’ve done tho – I’ll give it a quick try.

Your method looks like it would work, (don’t quite follow the partials aspect ? Why would they be different, wouldn’t it just be the position qty same as others?) —
It just seems like there’s got to be an easier way to do this using the orders or positions objects.
Problem is the positions clear after their closed — so my thoughts were may be easier to approximate this while they are open and easy to calculate.

I can’t find much on the get_activities() call / return looking through documentation, happy to take a look if you send a link though.

Another option would be to just basically save the unrealized_pl right before closing it, that’s something I’ve done in the past (not in Alpaca) — either by subtracting mid from avgPrice or calling a sort of pnl builtin. I think I would likely just loop through the positions and mark down last pnl before closing it…
like if you close at end of day, just run it at 2:58 or 2:59 and save them in a dictionary.

My example was from a trailing stop, so right when it triggered, I would just save the last PNL value as realized – but this is more of an approximation.

now = dt.datetime.now()
if now.hour == 14 and now.minute >= 55:
    pnl_by_symbol = defaultdict(float)
    for pos in api.list_positions():
        pnl_by_symbol[pos.symbol] = pos.unrealized_pl
        #close position logic...

or could use the order object, and get a bit messy with matching orders hopefully by time, qty, opp sides, etc. Would be easier if all exits were stop orders, btw – don’t know if that’s an option.

`#Confirm status is what you want + date is restrictive to relevant orders
 orders = self.api.list_orders(status='filled')`

 for ord in orders:
     sym = ord.symbol
     qty = ord.qty
     avgPrice = ord.filled_avg_price
     match = [order for order if order.symbol == sym and order.qty = qty and order.side != ord.side]
     #Match is closing order
     if match.filled_at > ord.filled_at:
          pnl = (match.filled_avg_price - ord.filled_avg_price) * qty
     else:
         pnl = (ord.filled_avg_price - match.filled_avg_price) * qty
     pnl_dict[ord.symbol] = pnl
     #Hoping you only have 1 position per symbol per day -- if not would sort by time, match qty.

Sorry – don’t know if this is helpful, but this is how I would approach it – just seems easier to me than what you are attempting, but maybe I’m missing the point.