Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion coin2086/pnl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


def add_portfolio_purchase_price(trades, initial_purchase_price):
trades["portfolio_purchase_price"] = 0
trades["portfolio_purchase_price"] = 0.0
trades.loc[trades["trade_side"] == "BUY", "portfolio_purchase_price"] = (
trades["amount"] + trades["fee"]
)
Expand Down
3 changes: 2 additions & 1 deletion coin2086/pricedownload.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class PriceDownloader(abc.ABC):
def download_price(self, crypto, dtime):
pass

@abc.abstractproperty
@property
@abc.abstractmethod
def supported_crypto_list(self):
pass

Expand Down
11 changes: 9 additions & 2 deletions coin2086/valuation.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ def unstack_portfolio_composition(trades, sales, initial_portfolio):
portfolio = portfolio.drop(columns=["sign", "trade_side"])
# Unstack the composition of the portofolio after each transaction
portfolio = portfolio.set_index("cryptocurrency", append=True).unstack().fillna(0)
# Ensure column names are preserved for pandas 2.x compatibility
portfolio.columns.names = [None, 'cryptocurrency']
# We need the valuation of the portoflio *before* each transaction
# so shift by one
portfolio["quantity"] = portfolio["quantity"].cumsum().shift(1, fill_value=0)
Expand All @@ -105,10 +107,13 @@ def unstack_portfolio_composition(trades, sales, initial_portfolio):


def merge_rates_and_valuate(portfolio):
portfolio = portfolio.stack()
# Stack the second level (cryptocurrency) into the index
portfolio = portfolio.stack(level=1, future_stack=True)
portfolio["ref_price"] = portfolio["sell_price"].fillna(portfolio["public_price"])
portfolio["value"] = portfolio["ref_price"] * portfolio["quantity"]
portfolio = portfolio.unstack()
# Unstack back and explicitly set the column names
portfolio = portfolio.unstack(level=-1)
portfolio.columns.names = [None, 'cryptocurrency']
portfolio["value", "TOTAL"] = portfolio["value"].sum(axis=1)
return portfolio

Expand All @@ -117,6 +122,8 @@ def add_sell_prices(portfolio, sales):
sell_prices = sales[["cryptocurrency", "price"]]
sell_prices = sell_prices.rename(columns={"price": "sell_price"})
sell_prices = sell_prices.set_index("cryptocurrency", append=True).unstack()
# Ensure column names are preserved for pandas 2.x compatibility
sell_prices.columns.names = [None, 'cryptocurrency']
return portfolio.join(sell_prices, how="outer")


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ classifiers = [

[tool.poetry.dependencies]
python = ">=3.6.2,<4.0"
pandas = "^1.1"
pandas = ">=1.1,<3.0"
requests = "^2.10"

[tool.poetry.dev-dependencies]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
,datetime,trade_side,cryptocurrency,quantity,amount,fee,amount_net,portfolio_value,portfolio_purchase_price,purchase_price_fraction,purchase_price_fraction_sum,portfolio_purchase_price_net,pnl
1,2019-11-14 19:50:00,SELL,BTC,0.5,3922.44,19.6122,3902.8278,7844.88,7185.1269,3592.56345,0.0,7185.1269,310.2643499999999
4,2020-09-05 16:50:00,SELL,BTC,1.0,8722.7,43.6135,8679.086500000001,23310.95,27780.330599999998,9050.795292311339,3592.56345,24187.767149999996,-371.7087923113377
5,2020-09-08 12:40:00,SELL,ETH,5.0,1425.35,7.12675,1418.22325,14189.210000000001,27780.330599999998,1520.5556079130922,12643.358742311339,15136.971857688659,-102.33235791309221
5,2020-09-08 12:40:00,SELL,ETH,5.0,1425.35,7.1267499999999995,1418.22325,14189.210000000001,27780.330599999998,1520.5556079130922,12643.358742311339,15136.971857688659,-102.33235791309221
6,2020-12-20 09:10:00,SELL,BTC,0.25,4805.975,24.029875000000004,4781.945125,28835.850000000002,27780.330599999998,2269.4027082959274,14163.914350224431,13616.416249775566,2512.542416704073
7,2021-03-13 23:40:00,SELL,BTC,0.25,12506.2925,62.5314625,12443.7610375,62531.462499999994,27780.330599999998,2269.402708295928,16433.31705852036,11347.013541479639,10174.358329204073
2 changes: 1 addition & 1 deletion tests/reference_data/interleaved_trades_detailed_pnl.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
,datetime,trade_side,cryptocurrency,quantity,amount,fee,amount_net,portfolio_value,portfolio_purchase_price,purchase_price_fraction,purchase_price_fraction_sum,portfolio_purchase_price_net,pnl
2,2020-09-05 16:50:00,SELL,BTC,0.5,4361.35,21.80675,4339.543250000001,10226.900000000001,11286.471599999999,4813.213477462378,0.0,11286.471599999999,-473.6702274623776
3,2020-09-08 12:40:00,SELL,ETH,5.0,1425.35,7.12675,1418.22325,5679.969999999999,11286.471599999999,1624.4202812618723,4813.213477462378,6473.258122537621,-206.19703126187233
3,2020-09-08 12:40:00,SELL,ETH,5.0,1425.35,7.1267499999999995,1418.22325,5679.969999999999,11286.471599999999,1624.4202812618723,4813.213477462378,6473.258122537621,-206.19703126187233
6,2020-12-21 09:30:00,SELL,BTC,1.0,19531.69,97.65845,19434.03155,31934.784999999996,22507.658399999997,9828.616024368384,6437.633758724251,16070.024641275746,9605.415525631615
4 changes: 3 additions & 1 deletion tests/test_non_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ def test_compute_pnl():
)
pnl_declare_ref = pd.read_csv(pnl_declare_path, index_col=0)
# Convert 2nd columns (Date de la cession to datetime64s)
pnl_declare_ref.iloc[:, 1] = pd.to_datetime(pnl_declare_ref.iloc[:, 1])
# Use column name instead of iloc for pandas 2.x compatibility
date_col_name = pnl_declare_ref.columns[1]
pnl_declare_ref[date_col_name] = pd.to_datetime(pnl_declare_ref[date_col_name])
pnl_declare, total_pnl = coin2086.compute_taxable_pnls(trades, 2020)
print(pnl_declare)
pd.testing.assert_frame_equal(pnl_declare, pnl_declare_ref)