nixos-config/nixos/machines/pepe/home-assistant/stocks.nix

183 lines
5.3 KiB
Nix

{ lib, config, pkgs, ... }:
let
folderPath = config.services.home-assistant.configDir;
# find symbols with
# https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=<keywords>&apikey=<api_key>
# as described here : https://www.alphavantage.co/documentation/#symbolsearch
#
# example:
# --------
# stocks = [
# {
# symbol = "GOOGL";
# name = "google";
# friendly_name = "Google";
# currency = "$";
# # I own 50 and bought at a price of 1000
# own = {
# pieces = 50;
# price = 1000;
# };
# }
# ];
stocks = import <secrets/home-assistant/stocks>;
filePath = name: "${folderPath}/stock_${name}.json";
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
in
{
services.homeAssistantConfig = {
sensor = cleanup_list (map
({ name, currency, own ? { }, ... }: [
{
platform = "file";
name = "stock_${name}";
file_path = filePath name;
value_template = "{{ value_json.price}} ${currency}";
}
{
platform = "file";
name = "stock_${name}_change";
file_path = filePath name;
value_template = "{{ value_json.change}} ${currency}";
}
{
platform = "file";
name = "stock_${name}_change_percent";
file_path = filePath name;
value_template = "{{ value_json.change_percent}} %";
}
(lib.optionalAttrs (own != { }) {
platform = "file";
name = "stock_${name}_profit";
file_path = filePath name;
value_template = ''
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
toString (own.pieces * own.price)
} ) }} ${currency}'';
})
])
stocks);
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize = builtins.listToAttrs (cleanup_list (map
({ name, own ? { }, ... }: [
{
name = "sensor.stock_${name}";
value = {
icon = "mdi:cash-usd-outline";
friendly_name = "Price";
};
}
{
name = "sensor.stock_${name}_change";
value = {
icon = "mdi:radar";
friendly_name = "Difference";
};
}
{
name = "sensor.stock_${name}_change_percent";
value = {
icon = "mdi:radar";
friendly_name = "Percent";
};
}
(lib.optionalAttrs (own != { }) {
name = "sensor.stock_${name}_profit";
value = {
icon = "mdi:radar";
friendly_name = "Profit";
};
})
])
stocks));
};
group = (builtins.listToAttrs (map
({ name, friendly_name, own ? { }, ... }: {
name = "stock_${name}";
value = {
name = "${friendly_name} Aktie";
entities = [
"sensor.stock_${name}"
"sensor.stock_${name}_change"
"sensor.stock_${name}_change_percent"
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
};
})
stocks));
};
systemd.services =
let
pullService = { name, symbol, currency, ... }: {
name = "pull_stock_${name}";
value = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "pull stock_${name} for homeassistant";
script = ''
SYMBOL="${symbol}"
CURRENCY="${currency}"
APIKEY=${
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
}
${pkgs.curl}/bin/curl --location --silent \
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
| ${pkgs.jq}/bin/jq --compact-output \
'.["Global Quote"] |
{
price: .["05. price"] | tonumber,
currency: "'$CURRENCY'",
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
change: .["09. change"] | tonumber,
last_date: .["07. latest trading day"],
}' \
>> ${filePath name}
# old and stupid
#${pkgs.curl}/bin/curl --location --silent \
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
#| ${pkgs.jq}/bin/jq --compact-output \
# '.["Time Series (5min)"] | to_entries | [ .[]
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
# | sort_by(.date) | reverse | .[0]' \
'';
};
};
in
builtins.listToAttrs (map pullService stocks);
systemd.timers =
let
pullTimer = { name, ... }: {
name = "pull_stock_${name}";
value = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "hourly";
Persistent = "true";
};
};
};
in
builtins.listToAttrs (map pullTimer stocks);
}