HowMuch demo
Application.put_all_env(
handsontable: [
license_key: "non-commercial-and-evaluation",
working_dir: __DIR__
],
ex_money: [
open_exchange_rates_app_id: System.fetch_env!("LB_OPEN_EXCHANGE_RATES_APP_ID"),
exchange_rates_cache_module: HowMuch.MoneyExchangeRatesDets,
default_cldr_backend: HowMuch.Cldr
],
how_much: [
money_exchange_rate_dets: Path.join(__DIR__, "priv/money_exchange_rate.dets"),
pricing_dets: Path.join(__DIR__, "priv/pricing.dets")
]
)
IO.inspect(__DIR__)
|> Path.join("priv")
|> File.mkdir_p!()
Mix.install([
{:handsontable_kino_smartcell,
git: "https://github.com/pastleo/handsontable_kino_smartcell.git", tag: "0.1.9"},
{:how_much, git: "https://github.com/pastleo/how_much.git", tag: "0.1.9"},
{:kino_explorer, "~> 0.1.11"},
{:vega_lite, "~> 0.1.6"},
{:kino_vega_lite, "~> 0.1.7"}
])
[project]
name = "project"
version = "0.0.0"
requires-python = "==3.13.*"
dependencies = [
"yfinance"
]
Readme
add OPEN_EXCHANGE_RATES_APP_ID to secret, visit https://openexchangerates.org/ to get one
See:
1. Define asset records
twse_stocks_data = [
["", "TWSE.0050", "TWSE.2330", "", "", "", "", "", "", ""],
["2023-09-18", "1000", "2000", "", "", "", "", "", "", ""],
["2023-10-01", "1000", "3000", "", "", "", "", "", "", ""],
["2023-10-05", "1500", "3000", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""]
]
twse_assets_records = HowMuch.Record.from_table_data(twse_stocks_data)
IO.puts("twse_assets_records: #{length(twse_assets_records)}, latest: #{Enum.at(twse_assets_records, -1).date}")
fiat_assets_data = [
[
"",
"bank1:TWD",
"bank2:USD #fixed-deposit",
"bank3:JPY #fixed-deposit",
"",
"",
"",
"",
"",
""
],
["2023-09-18", "10,000", "1,000.5", "25,000", "", "", "", "", "", ""],
["2023-10-01", "12,000", "2,000.0", "20,000", "", "", "", "", "", ""],
["2023-10-05", "10000", "2,000.0", "20,000", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""]
]
fiat_assets_records = HowMuch.Record.from_table_data(fiat_assets_data)
IO.puts("fiat_assets_records: #{length(fiat_assets_records)}, latest: #{Enum.at(fiat_assets_records, -1).date}")
firstrade_data = [
["", "YH.VOO", "", "", "", "", "", "", "", ""],
["2023-09-18", "1", "", "", "", "", "", "", "", ""],
["2023-10-01", "2", "", "", "", "", "", "", "", ""],
["2023-10-05", "2", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", ""]
]
firstrade_records = HowMuch.Record.from_table_data(firstrade_data, tags: ["#firstrade"])
IO.puts("firstrade_records: #{length(firstrade_records)}, latest: #{Enum.at(firstrade_records, -1).date}")
2. Calculate & Serialize
require Explorer.DataFrame
alias Explorer.DataFrame, as: DF
alias Explorer.Series, as: DS
alias VegaLite, as: Vl
target_currency = :TWD
# today = Date.utc_today()
today = ~D[2023-10-10]
calculate_until = HowMuch.Utils.unix_timestamp(today)
all_assets_values_serialized =
(twse_assets_records ++ fiat_assets_records ++ firstrade_records)
|> HowMuch.Value.calculate(target_currency, calculate_until)
|> HowMuch.Value.serialize(target_currency)
all_assets_values_data_frame = DF.new(all_assets_values_serialized)
IO.puts("length of all_assets_values_serialized: #{length(all_assets_values_serialized)}")
two_weeks_ago = today |> Date.add(-2 * 7)
start_time_input = Kino.Input.date("Select chart start time:", default: two_weeks_ago)
start_time = Kino.Input.read(start_time_input)
3. Summarizing & Charts
all_recorded_data_frame =
HowMuch.Explorer.DataFrame.summarize(all_assets_values_data_frame, "name")
|> HowMuch.Explorer.DataFrame.filter_summarized_has_record()
HowMuch.Explorer.DataFrame.current(all_assets_values_data_frame, "name", Date.add(today, -1))
|> HowMuch.VegaLite.current_pie_chart(
"name",
"Assets Value Distribution"
)
HowMuch.VegaLite.summarized_recorded_bar_line_chart(
DF.filter(all_assets_values_data_frame, date > ^start_time),
DF.filter(all_recorded_data_frame, date > ^start_time),
"name",
"Assets Value Summary since #{start_time}"
)
HowMuch.VegaLite.summarized_recorded_bar_line_chart(
all_assets_values_data_frame,
all_recorded_data_frame,
"name",
"Assets Value Summary (all time)"
)