Mix.install(
[
{:req, "~> 0.4.5"},
{:explorer, "~> 0.7.1"},
{:kino_explorer, "~> 0.1.12"},
{:kino_vega_lite, "~> 0.1.10"},
{:timex, "~> 3.7"}
],
config: [nx: [default_backend: EXLA.Backend]]
)
resp = Req.get!("https://nsearchives.nseindia.com/content/indices/ind_nifty200list.csv")
input = Kino.Input.file("File")
value = Kino.Input.read(input)
path = Kino.Input.file_path(value.file_ref)
data = File.read!(path) |> Jason.decode!()
# ticker = "JIOFIN.NS"
# range = "1mo"
# interval = "15m"
# metrics = "close"
# url =
# "https://query1.finance.yahoo.com/v8/finance/chart/#{ticker}?metrics=#{metrics}&interval=#{interval}&range=#{range}"
# IO.puts(url)
# resp = Req.get!(url)
require Explorer.DataFrame, as: DF
require Explorer.Series, as: S
# quote_data =
# resp.body["chart"]["result"]
# |> List.first()
# |> get_in(["indicators", "quote"])
# |> List.first()
# |> DF.new()
quote_data =
data
|> DF.new()
|> DF.mutate(
price_change:
S.subtract(
close,
S.shift(close, 1)
)
)
|> DF.mutate(
gain: if(S.greater(price_change, 0), do: price_change, else: 0),
loss: if(S.less(price_change, 0), do: -price_change, else: 0)
)
|> DF.mutate(
avg_gain: S.window_mean(gain, 14, min_periods: 1),
avg_loss: S.window_mean(loss, 14, min_periods: 1)
)
indexes = S.from_list(0..(S.size(quote_data["gain"]) - 1) |> Enum.to_list())
quote_data = DF.put(quote_data, :index, indexes)
quote_data_first_13 =
DF.slice(quote_data, 0..12)
quote_data_at_14 =
quote_data
|> DF.mutate(
avg_gain: S.window_mean(gain, 14, min_periods: 14),
avg_loss: S.window_mean(loss, 14, min_periods: 14)
)
|> DF.slice(13..13)
# # 14 : 0.15714285714285633
quote_data_after_14 =
quote_data_at_14
|> DF.concat_rows(quote_data |> DF.slice(14..-1//1))
|> DF.group_by(:index)
|> DF.summarise(prev_avg_gain: S.at(gain, 1))
|> DF.mutate_with(
&[
avg_gain: S.divide(S.add(&1["gain"], S.multiply(13, S.shift(&1["avg_gain"], 1))), 14),
avg_loss: S.divide(S.add(&1["loss"], S.multiply(13, S.shift(&1["avg_loss"], 1))), 14)
]
)
|> DF.slice(1..-1//1)
# quote_data =
# quote_data_first_13
# |> DF.concat_rows(quote_data_at_14)
# |> DF.concat_rows(quote_data_after_14)
# |> DF.mutate(rs: S.divide(avg_gain, avg_loss))
# |> DF.mutate(rs: if(S.is_nan(rs), do: 0, else: rs))
# |> DF.mutate(rsi: S.subtract(100, S.divide(100, S.add(1, rs))))
# timestamp_data =
# resp.body["chart"]["result"]
# |> List.first()
# |> Map.take(["timestamp"])
# |> Enum.reduce(%{"timestamp" => [], "datetime" => []}, fn {_, data}, acc ->
# %{
# acc
# | "timestamp" => data,
# "datetime" =>
# Enum.map(data, fn timestamp ->
# {:ok, datetime} = DateTime.from_unix(timestamp)
# # "#{DateTime.shift_zone!(datetime, "Asia/Kolkata")}"
# "#{datetime}"
# end)
# }
# end)
# |> DF.new()
# data = DF.concat_columns([timestamp_data, quote_data])
VegaLite.new(width: 750, height: 300)
|> VegaLite.data_from_values(data, only: ["price_change", "rsi"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "price_change", type: :nominal)
|> VegaLite.encode_field(:y, "rsi", type: :nominal)