Skip to content

Commit

Permalink
Integrate live feeds from Pyth (#2178)
Browse files Browse the repository at this point in the history
* added dependency

* added pyth models

* dependencies

* docs

* some improvements to this pyth command (#2433)

* some improvements to this pyth command

* minor improv

* dependencies

* tests

Co-authored-by: DidierRLopes <dro.lopes@campus.fct.unl.pt>; COlin
  • Loading branch information
jose-donato authored Sep 21, 2022
1 parent 8216e85 commit 1661ddd
Show file tree
Hide file tree
Showing 9 changed files with 621 additions and 2,176 deletions.
1 change: 1 addition & 0 deletions i18n/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ en:
stocks/pred/mc: Monte-Carlo simulations
crypto/load: load a specific cryptocurrency for analysis
crypto/find: find coins
crypto/price: real-time price and interval of confidence
crypto/_symbol: Coin
crypto/_interval: Interval (min)
crypto/_source: Source
Expand Down
37 changes: 36 additions & 1 deletion openbb_terminal/cryptocurrency/crypto_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import List
from prompt_toolkit.completion import NestedCompleter

from openbb_terminal.cryptocurrency import cryptocurrency_helpers
from openbb_terminal.cryptocurrency import cryptocurrency_helpers, pyth_model, pyth_view
from openbb_terminal import feature_flags as obbff
from openbb_terminal.cryptocurrency.cryptocurrency_helpers import (
FIND_KEYS,
Expand Down Expand Up @@ -56,6 +56,7 @@ class CryptoController(CryptoBaseController):
"find",
"prt",
"resources",
"price",
]
CHOICES_MENUS = [
"ta",
Expand Down Expand Up @@ -94,6 +95,7 @@ def __init__(self, queue: List[str] = None):
}
choices["load"]["--vs"] = {c: {} for c in ["usd", "eur"]}
choices["find"]["-k"] = {c: {} for c in FIND_KEYS}
choices["price"] = {c: {} for c in pyth_model.ASSETS.keys()}
choices["headlines"] = {c: {} for c in finbrain_crypto_view.COINS}
# choices["prt"]["--vs"] = {c: {} for c in coingecko_coin_ids} # list is huge. makes typing buggy

Expand All @@ -107,6 +109,7 @@ def print_help(self):
mt = MenuText("crypto/")
mt.add_cmd("load")
mt.add_cmd("find")
mt.add_cmd("price", "Pyth")
mt.add_raw("\n")
mt.add_param(
"_symbol", f"{self.symbol.upper()}/{self.vs.upper()}" if self.symbol else ""
Expand Down Expand Up @@ -199,6 +202,38 @@ def call_prt(self, other_args):
"No coin selected. Use 'load' to load the coin you want to look at.\n"
)

@log_start_end(log=logger)
def call_price(self, other_args):
"""Process price command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="price",
description="""Display price and interval of confidence in real-time. [Source: Pyth]""",
)
parser.add_argument(
"-s",
"--symbol",
required="-h" not in other_args,
type=str,
dest="symbol",
help="Symbol of coin to load data for, ~100 symbols are available",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-s")

ns_parser = self.parse_known_args_and_warn(parser, other_args)

if ns_parser:

if ns_parser.symbol in pyth_model.ASSETS.keys():
console.print(
"[param]If it takes too long, you can use 'Ctrl + C' to cancel.\n[/param]"
)
pyth_view.display_price(ns_parser.symbol)
else:
console.print("[red]The symbol selected does not exist.[/red]\n")

@log_start_end(log=logger)
def call_candle(self, other_args):
"""Process candle command"""
Expand Down
113 changes: 113 additions & 0 deletions openbb_terminal/cryptocurrency/pyth_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import logging

from pythclient.pythaccounts import PythPriceAccount, PythPriceStatus
from pythclient.solana import (
SolanaClient,
SolanaPublicKey,
SOLANA_DEVNET_HTTP_ENDPOINT,
SOLANA_DEVNET_WS_ENDPOINT,
)

from openbb_terminal.decorators import log_start_end

logger = logging.getLogger(__name__)

ASSETS = {
"AAVE-USD": {"feedID": "FT7Cup6ZiFDF14uhFD3kYS3URMCf2RZ4iwfNEVUgndHW"},
"ADA-USD": {"feedID": "8oGTURNmSQkrBS1AQ5NjB2p8qY34UVmMA9ojrw8vnHus"},
"ALGO-USD": {"feedID": "c1A946dY5NHuVda77C8XXtXytyR3wK1SCP3eA9VRfC3"},
"ANC-USD": {"feedID": "5Si2Pdm7B87ojYvkegg7ct8Y446RHJyEjeREAyZEZcAV"},
"APE-USD": {"feedID": "EfnLcrwxCgwALc5vXr4cwPZMVcmotZAuqmHa8afG8zJe"},
"ATLAS-USD": {"feedID": "Dzs6SE1cssUqBpWCKzE4jeS5PrmRK1Fp2Kw1WMaDCiVR"},
"ATOM-USD": {"feedID": "7YAze8qFUMkBnyLVdKT4TFUUFui99EwS5gfRArMcrvFk"},
"AUST-UST": {"feedID": "9g8mGLKcDiKSrWahbjKGtpGCcrLkC5kbwmpFFGRs6euf"},
"AVAX-USD": {"feedID": "FVb5h1VmHPfVb1RfqZckchq18GxRv4iKt8T4eVTQAqdz"},
"BCH-USD": {"feedID": "4EQrNZYk5KR1RnjyzbaaRbHsv8VqZWzSUtvx58wLsZbj"},
"BETH-USD": {"feedID": "HyShqBUTtwAaCas9Dnib3ut6GmEDk9hTdKsrNfRffX8E"},
"BNB-USD": {"feedID": "GwzBgrXb4PG59zjce24SF2b9JXbLEjJJTBkmytuEZj1b"},
"BRZ-USD": {"feedID": "5g4XtpqLynP6YUSQwncw6CrdAEoy5a7QNDevgAgLsfyC"},
"BTC-USD": {"feedID": "HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J"},
"BUSD-USD": {"feedID": "TRrB75VTpiojCy99S5BHmYkjARgtfBqZKk5JbeouUkV"},
"C98-USD": {"feedID": "Dxp7vob2NTGhmodyWyeEkqtNEpSfvSMoGKMYjmaY6pg1"},
"COPE-USD": {"feedID": "BAXDJUXtz6P5ARhHH1aPwgv4WENzHwzyhmLYK4daFwiM"},
"CUSD-USD": {"feedID": "DDwzo3aAjgYk8Vn8D3Zbxo62rTmBVdJv1WjaKQseiHKk"},
"DOGE-USD": {"feedID": "4L6YhY8VvUgmqG5MvJkUJATtzB2rFqdrJwQCmFLv4Jzy"},
"DOT-USD": {"feedID": "4dqq5VBpN4EwYb7wyywjjfknvMKu7m78j9mKZRXTj462"},
"ETH-USD": {"feedID": "EdVCmQ9FSPcVe5YySXDPCRmc8aDQLKJ9xvYBMZPie1Vw"},
"FIDA-USD": {"feedID": "7teETxN9Y8VK6uJxsctHEwST75mKLLwPH1jaFdvTQCpD"},
"FTM-USD": {"feedID": "BTwrLU4so1oJMViWA3BTzh8YmFwiLZ6CL4U3JryG7Q5S"},
"FTT-USD": {"feedID": "6vivTRs5ZPeeXbjo7dfburfaYDWoXjBtdtuYgQRuGfu"},
"GMT-USD": {"feedID": "EZy99wkoqohyyNxT1QCwW3epQtMQ1Dfqx4sXKqkHiSox"},
"GOFX-USD": {"feedID": "A9r7BHsXJQ2w9B7cdJV8BkfRoBWkxRichVGm72vVS1s5"},
"HXRO-USD": {"feedID": "6VrSw4Vxg5zs9shfdCxLqfUy2qSD3NCS9AsdBQUgbjnt"},
"INJ-USD": {"feedID": "44uRsNnT35kjkscSu59MxRr9CfkLZWf6gny8bWqUbVxE"},
"JET-USD": {"feedID": "3JnVPNY878pRH6TQ9f4wuwfNqGh6okyshmqmKsyvewMs"},
"LTC-USD": {"feedID": "BLArYBCUYhdWiY8PCUTpvFE21iaJq85dvxLk9bYMobcU"},
"LUNA-USD": {"feedID": "7xzCBiE2d9UwV9CYLV9vrbJPipJzMEaycPBoZg2LjhUf"},
"LUNC-USD": {"feedID": "8PugCXTAHLM9kfLSQWe2njE5pzAgUdpPk3Nx5zSm7BD3"},
"MATIC-USD": {"feedID": "FBirwuDFuRAu4iSGc7RGxN5koHB7EJM1wbCmyPuQoGur"},
"MER-USD": {"feedID": "6Z3ejn8DCWQFBuAcw29d3A5jgahEpmycn7YDMX7yRNrn"},
"MIR-USD": {"feedID": "4BDvhA5emySfqyyTHPHofTJqRw1cwDabK1yiEshetPv9"},
"MNGO-USD": {"feedID": "DCNw5mwZgjfTcoNsSZWUiXqU61ushNvr3JRQJRi1Nf95"},
"MSOL-USD": {"feedID": "9a6RNx3tCu1TSs6TBSfV2XRXEPEZXQ6WB7jRojZRvyeZ"},
"NEAR-USD": {"feedID": "3gnSbT7bhoTdGkFVZc1dW1PvjreWzpUNUD5ppXwv1N59"},
"ONE-USD": {"feedID": "BScN1mER6QJ2nFKpnP4PcqffQp97NXAvzAbVPjLKyRaF"},
"ORCA-USD": {"feedID": "A1WttWF7X3Rg6ZRpB2YQUFHCRh1kiXV8sKKLV3S9neJV"},
"PAI-USD": {"feedID": "8EjmYPrH9oHxLqk2oFG1qwY6ert7M9cv5WpXyWHxKiMb"},
"PORT-USD": {"feedID": "33ugpDWbC2mLrYSQvu1BHfykR8bt3MVc4S3YuuXMVRH3"},
"RAY-USD": {"feedID": "EhgAdTrgxi4ZoVZLQx1n93vULucPpiFi2BQtz9RJr1y6"},
"SBR-USD": {"feedID": "4WSN3XDSTfBX9A1YXGg8HJ7n2GtWMDNbtz1ab6aGGXfG"},
"SCNSOL-USD": {"feedID": "HoDAYYYhFvCNQNFPui51H8qvpcdz6KuVtq77ZGtHND2T"},
"SLND-USD": {"feedID": "FtwKARNAnZK2Nx1W4KVXzbyDzuRJqmApHRBtQpZ49HDv"},
"SNY-USD": {"feedID": "DEmEX28EgrdQEBwNXdfMsDoJWZXCHRS5pbgmJiTkjCRH"},
"SOL-USD": {"feedID": "J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix"},
"SRM-USD": {"feedID": "992moaMQKs32GKZ9dxi8keyM2bUmbrwBZpK4p2K6X5Vs"},
"STEP-USD": {"feedID": "DKjdYzkPEZLBsfRzUaCjze5jjgCYu5kFCB19wVa9sy6j"},
"STSOL-USD": {"feedID": "2LwhbcswZekofMNRtDRMukZJNSRUiKYMFbqtBwqjDfke"},
"TUSD-USD": {"feedID": "2sbXow64dSbktGM6gG9FpszwVu7GNhr6Qi2WHRCP9ULn"},
"USDC-USD": {"feedID": "5SSkXsEKQepHHAewytPVwdej4epN1nxgLVM84L4KXgy7"},
"USDT-USD": {"feedID": "38xoQ4oeJCBrcVvca2cGk7iV1dAfrmTR1kmhSCJQ8Jto"},
"USTC-USD": {"feedID": "AUKjh1oVPZyudi3nzYSsdZxSjq42afUCvsdbKFc5CbD"},
"VAI-USD": {"feedID": "Gvm85Pbjq4Tv7qyaS4y9ZMqCdY3nynGDBFYAu7mjPoGM"},
"XVS-USD": {"feedID": "8Y4jhVcQvQZWjMarM855NMkVuua78FS8Uwy58TjcnUWs"},
"ZBC-USD": {"feedID": "7myonvBWD5zfh6qfScRP5E4anEue4Bqnu8XS8cdtJTQx"},
}


@log_start_end(log=logger)
async def get_price(symbol: str):
"""Returns price and confidence interval from pyth live feed. [Source: Pyth]
Parameters
----------
symbol : str
Symbol of the asset to get price and confidence interval from
Returns
-------
float
Price of the asset
float
Confidence level
float
Previous price of the asset
"""

account_key = SolanaPublicKey(ASSETS[symbol]["feedID"])
solana_client = SolanaClient(
endpoint=SOLANA_DEVNET_HTTP_ENDPOINT, ws_endpoint=SOLANA_DEVNET_WS_ENDPOINT
)
price: PythPriceAccount = PythPriceAccount(account_key, solana_client)

await price.update()

price_status = price.aggregate_price_status
aggregate_price = -1
confidence = -1
if price_status == PythPriceStatus.TRADING:
aggregate_price = price.aggregate_price
previous_price = price.prev_price
confidence = price.aggregate_price_confidence_interval

await solana_client.close()
return aggregate_price, confidence, previous_price
31 changes: 31 additions & 0 deletions openbb_terminal/cryptocurrency/pyth_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# pylint: disable= C0301

import asyncio
import logging

from openbb_terminal.cryptocurrency.pyth_model import get_price
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console

logger = logging.getLogger(__name__)


@log_start_end(log=logger)
def display_price(symbol: str) -> None:
"""Displays live price from pyth live feed [Source: https://pyth.network/]
Parameters
----------
symbol : str
Symbol of the asset to get price for
"""
try:
while True:
price, confidence, previous_price = asyncio.run(get_price(symbol))
console.print(
f"{symbol} = {'[red]' if previous_price >= price else '[green]'}"
f"{price}{'[/red]' if previous_price >= price else '[/green]'} ± {confidence}",
end="\r",
)
except KeyboardInterrupt:
print(f"\n\nStopped watching {symbol} price and confidence interval\n")
Loading

0 comments on commit 1661ddd

Please sign in to comment.