Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F77366
finance.ex
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
finance.ex
View Options
defmodule
Nola.Plugins.Finance
do
require
Logger
@moduledoc
"""
#
finance
Données de [alphavantage.co](https://alphavantage.co).
##
forex / monnaies / crypto-monnaies
* **`!forex <MONNAIE1> [MONNAIE2]`**: taux de change entre deux monnaies.
* **`!forex <MONTANT> <MONNAIE1> <MONNAIE2>`**: converti `montant` entre deux monnaies
* **`?currency <recherche>`**: recherche une monnaie
Utiliser le symbole des monnaies (EUR, USD, ...).
##
bourses
* **`!stocks <SYMBOLE>`**
* **`?stocks <recherche>`** cherche un symbole
Pour les symboles non-US, ajouter le suffixe (RNO Paris: RNO.PAR).
"""
@currency_list
"http://www.alphavantage.co/physical_currency_list/"
@crypto_list
"http://www.alphavantage.co/digital_currency_list/"
HTTPoison
.
start
()
load_currency
=
fn
(
url
)
->
resp
=
HTTPoison
.
get!
(
url
)
resp
.
body
|>
String
.
strip
()
|>
String
.
split
(
"
\n
"
)
|>
Enum
.
drop
(
1
)
|>
Enum
.
map
(
fn
(
line
)
->
[
symbol
,
name
]
=
line
|>
String
.
strip
()
|>
String
.
split
(
","
,
parts
:
2
)
{
symbol
,
name
}
end
)
|>
Enum
.
into
(
Map
.
new
)
end
fiat
=
load_currency
.
(
@currency_list
)
crypto
=
load_currency
.
(
@crypto_list
)
@currencies
Map
.
merge
(
fiat
,
crypto
)
def
irc_doc
,
do
:
@moduledoc
def
start_link
()
do
GenServer
.
start_link
(
__MODULE__
,
[],
name
:
__MODULE__
)
end
def
init
([])
do
regopts
=
[
plugin
:
__MODULE__
]
{
:ok
,
_
}
=
Registry
.
register
(
Nola.PubSub
,
"trigger:forex"
,
regopts
)
{
:ok
,
_
}
=
Registry
.
register
(
Nola.PubSub
,
"trigger:currency"
,
regopts
)
{
:ok
,
_
}
=
Registry
.
register
(
Nola.PubSub
,
"trigger:stocks"
,
regopts
)
{
:ok
,
nil
}
end
def
handle_info
({
:irc
,
:trigger
,
"stocks"
,
message
=
%{
trigger
:
%{
type
:
:query
,
args
:
args
=
search
}}},
state
)
do
search
=
Enum
.
join
(
search
,
"%20"
)
url
=
"https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=
#{
search
}
&apikey=
#{
api_key
()
}
"
case
HTTPoison
.
get
(
url
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
data
}}
->
data
=
Poison
.
decode!
(
data
)
if
error
=
Map
.
get
(
data
,
"Error Message"
)
do
Logger
.
error
(
"AlphaVantage API invalid request
#{
url
}
-
#{
inspect
error
}
"
)
message
.
replyfun
.
(
"stocks: requête invalide"
)
else
items
=
for
item
<-
Map
.
get
(
data
,
"bestMatches"
)
do
symbol
=
Map
.
get
(
item
,
"1. symbol"
)
name
=
Map
.
get
(
item
,
"2. name"
)
type
=
Map
.
get
(
item
,
"3. type"
)
region
=
Map
.
get
(
item
,
"4. region"
)
currency
=
Map
.
get
(
item
,
"8. currency"
)
"
#{
symbol
}
:
#{
name
}
(
#{
region
}
;
#{
currency
}
;
#{
type
}
)"
end
|>
Enum
.
join
(
", "
)
items
=
if
items
==
""
do
"no results!"
else
items
end
message
.
replyfun
.
(
items
)
end
{
:ok
,
resp
=
%
HTTPoison.Response
{
status_code
:
code
}}
->
Logger
.
error
"AlphaVantage API error:
#{
code
}
#{
url
}
-
#{
inspect
resp
}
"
message
.
replyfun
.
(
"forex: erreur (api
#{
code
}
)"
)
{
:error
,
%
HTTPoison.Error
{
reason
:
error
}}
->
Logger
.
error
"AlphaVantage HTTP error:
#{
inspect
error
}
"
message
.
replyfun
.
(
"forex: erreur (http
#{
inspect
error
}
)"
)
end
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
"stocks"
,
message
=
%{
trigger
:
%{
type
:
:bang
,
args
:
args
=
[
symbol
]}}},
state
)
do
url
=
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=
#{
symbol
}
&apikey=
#{
api_key
()
}
"
case
HTTPoison
.
get
(
url
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
data
}}
->
data
=
Poison
.
decode!
(
data
)
if
error
=
Map
.
get
(
data
,
"Error Message"
)
do
Logger
.
error
(
"AlphaVantage API invalid request
#{
url
}
-
#{
inspect
error
}
"
)
message
.
replyfun
.
(
"stocks: requête invalide"
)
else
data
=
Map
.
get
(
data
,
"Global Quote"
)
open
=
Map
.
get
(
data
,
"02. open"
)
high
=
Map
.
get
(
data
,
"03. high"
)
low
=
Map
.
get
(
data
,
"04. low"
)
price
=
Map
.
get
(
data
,
"05. price"
)
volume
=
Map
.
get
(
data
,
"06. volume"
)
prev_close
=
Map
.
get
(
data
,
"08. previous close"
)
change
=
Map
.
get
(
data
,
"09. change"
)
change_pct
=
Map
.
get
(
data
,
"10. change percent"
)
msg
=
"
#{
symbol
}
:
#{
price
}
#{
change
}
[
#{
change_pct
}
] (high:
#{
high
}
, low:
#{
low
}
, open:
#{
open
}
, prev close:
#{
prev_close
}
) (volume:
#{
volume
}
)"
message
.
replyfun
.
(
msg
)
end
{
:ok
,
resp
=
%
HTTPoison.Response
{
status_code
:
code
}}
->
Logger
.
error
"AlphaVantage API error:
#{
code
}
#{
url
}
-
#{
inspect
resp
}
"
message
.
replyfun
.
(
"stocks: erreur (api
#{
code
}
)"
)
{
:error
,
%
HTTPoison.Error
{
reason
:
error
}}
->
Logger
.
error
"AlphaVantage HTTP error:
#{
inspect
error
}
"
message
.
replyfun
.
(
"stocks: erreur (http
#{
inspect
error
}
)"
)
end
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
"forex"
,
message
=
%{
trigger
:
%{
type
:
:bang
,
args
:
args
=
[
_
|
_
]}}},
state
)
do
{
amount
,
from
,
to
}
=
case
args
do
[
amount
,
from
,
to
]
->
{
amount
,
_
}
=
Float
.
parse
(
amount
)
{
amount
,
from
,
to
}
[
from
,
to
]
->
{
1
,
from
,
to
}
[
from
]
->
{
1
,
from
,
"EUR"
}
end
url
=
"https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=
#{
from
}
&to_currency=
#{
to
}
&apikey=
#{
api_key
()
}
"
case
HTTPoison
.
get
(
url
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
data
}}
->
data
=
Poison
.
decode!
(
data
)
if
error
=
Map
.
get
(
data
,
"Error Message"
)
do
Logger
.
error
(
"AlphaVantage API invalid request
#{
url
}
-
#{
inspect
error
}
"
)
message
.
replyfun
.
(
"forex: requête invalide"
)
else
data
=
Map
.
get
(
data
,
"Realtime Currency Exchange Rate"
)
from_name
=
Map
.
get
(
data
,
"2. From_Currency Name"
)
to_name
=
Map
.
get
(
data
,
"4. To_Currency Name"
)
rate
=
Map
.
get
(
data
,
"5. Exchange Rate"
)
{
rate
,
_
}
=
Float
.
parse
(
rate
)
value
=
amount
*
rate
message
.
replyfun
.
(
"
#{
amount
}
#{
from
}
(
#{
from_name
}
) ->
#{
value
}
#{
to
}
(
#{
to_name
}
) (
#{
rate
}
)"
)
end
{
:ok
,
resp
=
%
HTTPoison.Response
{
status_code
:
code
}}
->
Logger
.
error
"AlphaVantage API error:
#{
code
}
#{
url
}
-
#{
inspect
resp
}
"
message
.
replyfun
.
(
"forex: erreur (api
#{
code
}
)"
)
{
:error
,
%
HTTPoison.Error
{
reason
:
error
}}
->
Logger
.
error
"AlphaVantage HTTP error:
#{
inspect
error
}
"
message
.
replyfun
.
(
"forex: erreur (http
#{
inspect
error
}
)"
)
end
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
"currency"
,
message
=
%{
trigger
:
%{
type
:
:query
,
args
:
args
=
search
}}},
state
)
do
search
=
Enum
.
join
(
search
,
" "
)
results
=
Enum
.
filter
(
@currencies
,
fn
({
symbol
,
name
})
->
String
.
contains?
(
String
.
downcase
(
name
),
String
.
downcase
(
search
))
||
String
.
contains?
(
String
.
downcase
(
symbol
),
String
.
downcase
(
search
))
end
)
|>
Enum
.
map
(
fn
({
symbol
,
name
})
->
"
#{
symbol
}
:
#{
name
}
"
end
)
|>
Enum
.
join
(
", "
)
if
results
==
""
do
message
.
replyfun
.
(
"no results!"
)
else
message
.
replyfun
.
(
results
)
end
{
:noreply
,
state
}
end
defp
api_key
()
do
Application
.
get_env
(
:nola
,
:alphavantage
,
[])
|>
Keyword
.
get
(
:api_key
,
"demo"
)
end
end
File Metadata
Details
Attached
Mime Type
text/x-ruby
Expires
Mon, Jul 7, 5:28 AM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
49861
Default Alt Text
finance.ex (7 KB)
Attached To
rNOLA Nola
Event Timeline
Log In to Comment