Open upsuper opened 1 year ago
A workaround, for now, is to create a custom price source like
from beancount.prices.source import SourcePrice
from beancount.prices.sources import yahoo
def div_100(sp: SourcePrice) -> SourcePrice:
return SourcePrice(sp.price / 100, sp.time, sp.quote_currency)
class Source(yahoo.Source):
def get_latest_price(self, ticker):
source_price = super().get_latest_price(ticker)
return div_100(source_price)
def get_historical_price(self, ticker, time):
source_price = super().get_historical_price(ticker, time)
return div_100(source_price)
(Change the import module from beancount.prices
to beanprice
for the beanprice
package.)
can be archived by a plugin:
__copyright__ = "Copyright (C) 2023-2023 iLeoDo"
__license__ = "GNU GPLv2"
from typing import Dict
import collections
from decimal import Decimal
from beancount.core.data import Commodity, Currency, Price
import beancount.core.amount
__plugins__ = ("price_multiplier",)
import logging
logger = logging.getLogger("price_multiplier")
OverrideError = collections.namedtuple("CommodityError", "source message entry")
def price_multiplier(entries, unused_options_map, config_str=None):
multiplier_map :Dict[Currency, Decimal] = {}
for entry in entries:
if isinstance(entry, Commodity):
multiplier = entry.meta.get("multiplier", None)
if multiplier:
multiplier_map[entry.currency] = Decimal(multiplier)
def transform(entry):
if isinstance(entry, Price):
if entry.currency in multiplier_map:
override_entry = Price(entry.meta, entry.date, entry.currency, beancount.core.amount.mul(entry.amount, multiplier_map[entry.currency]))
return override_entry
return entry
ret_entries = [
transform(entry)
for entry in entries
]
errors = []
return ret_entries, errors
in your bean file
plugin "plugins.price_multiplier"
1970-01-01 commodity ABCDEFG
price: "GBP:yahoo/ABCDEFG"
multiplier: 0.01
For some of the commodities, quotes may not be on 1 unit of a currency. For example, this ETF on Yahoo is quoted in 0.01 GBP. If I put
price: "GBP:yahoo/XSDR.L"
in beancount file, the price fetched would be 100x larger than the actual price.I've also considered to introduce a separate unit for it, e.g.
CGBP
, and assume it is 0.01 GBP, but the problem then becomes that there is no easy way to fetch the exchange rate for this artificial currency.It would probably be better to extend the syntax and support non-unit currency price, for example,
price: "0.01GBP:yahoo/XSDR.L"
, and convert the price accordingly.