收益
根據執行的交易計算頭寸的平均價格、成本、(未)實現盈虧
我們已經建構了一個算法交易軟體,需要為我們投資組合中的每個頭寸計算以下參數。
- 平均價格
- 成本
- 已實現盈虧
- 未實現損益
這些值可以通過對該證券的所有先前填充來計算。但是在一個交易系統中,一個證券可能有數千筆交易,這可能需要很長時間,特別是如果每次需要這些值時都必須進行計算。所以我假設根據先前的值和為該證券收到的最後一次填充來計算這些值要快得多。
任何幫助表示讚賞!
實際上,我們自己設法想出了這個問題的答案,但想分享答案,因為它也可能與其他人相關。
計算取決於使用什麼方法來計算成本。有先進先出法、後進先出法和平均成本法,見:http ://www.accounting-basics-for-students.com/fifo-method.html
如果使用 FIFO 或 LIFO,則除了每次都通過每個填充之外別無他法。
然而,對於平均成本法,只需要頭寸的先驗值(數量、成本和已實現盈虧)和最新成交(數量和價格)。
這些是計算(在縮短的 Java 程式碼中):
closingQty = sign(oldQty) != sign(fillQty) ? min(Math.abs(oldQty), abs(fillQty)) * sign(fillQty) : 0 openingQty = sign(oldQty) == sign(fillQty) ? fillQty : fillQty - closingQty newQty = oldQty + fillQty newCost = oldCost + openingQty * fillPrice + closingQty * oldCost / oldQty newRealizedPL = oldRealizedPL + closingQty * (oldCost / oldQty - fillPrice)
現在可以導出其他值:
averagePrice = cost / qty marketValue = qty * currentPrice unrealizedPL = cost - marketValue
謝謝大家。任何回饋?
使用 Andy Flury 的答案和位拋光,它為 PnL 計算器提供了以下 Python 類:
class PnLCalculator: def __init__(self): self.quantity = 0 self.cost = 0.0 self.market_value = 0.0 self.r_pnl = 0.0 self.average_price = 0.0 def fill(self, n_pos, exec_price): pos_change = n_pos - self.quantity direction = np.sign(pos_change) prev_direction = np.sign(self.quantity) qty_closing = min(abs(self.quantity), abs(pos_change)) * direction if prev_direction != direction else 0 qty_opening = pos_change if prev_direction == direction else pos_change - qty_closing new_cost = self.cost + qty_opening * exec_price if self.quantity != 0: new_cost += qty_closing * self.cost / self.quantity self.r_pnl += qty_closing * (self.cost / self.quantity - exec_price) self.quantity = n_pos self.cost = new_cost def update(self, price): if self.quantity != 0: self.average_price = self.cost / self.quantity else: self.average_price = 0 self.market_value = self.quantity * price return self.market_value - self.cost
並使用它:
positions = np.array([200, 100, -100, 150, 50, 0]) exec_prices = np.array([50.0, 51.0, 49.0, 51.0, 53.0, 52.0]) pnls = [] print('Pos\t|\tR.P&L\t|\tU P&L\t|\tAvgPrc') print('-' * 55) pos = PnLCalculator() pnls = [] for (p,e) in zip(positions, exec_prices): pos.fill(p, e) u_pnl = pos.update(e) print('%+d\t|\t%.1f\t|\t%.1f\t|\t[%.1f]' % (pos.quantity, pos.r_pnl, u_pnl, pos.average_price)) pnls.append(u_pnl + pos.r_pnl) print('-' * 55) print(pnls)
輸出:
Pos | R.P&L | U P&L | AvgPrc ------------------------------------------------------- +200 | 0.0 | 0.0 | [50.0] +100 | 100.0 | 100.0 | [50.0] -100 | 0.0 | 0.0 | [49.0] +150 | -200.0 | 0.0 | [51.0] +50 | 0.0 | 100.0 | [51.0] +0 | 50.0 | 0.0 | [0.0] ------------------------------------------------------- [0.0, 200.0, 0.0, -200.0, 100.0, 50.0]