Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate live feeds from Pyth #2178

Merged
merged 12 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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