Skip to content

Instantly share code, notes, and snippets.

@robmcelhinney
Last active May 6, 2022 18:22
Show Gist options
  • Select an option

  • Save robmcelhinney/505bc0dcb08d3cdd0ce16f4ce787152c to your computer and use it in GitHub Desktop.

Select an option

Save robmcelhinney/505bc0dcb08d3cdd0ce16f4ce787152c to your computer and use it in GitHub Desktop.

Revisions

  1. robmcelhinney revised this gist May 6, 2022. 1 changed file with 1 addition and 4 deletions.
    5 changes: 1 addition & 4 deletions ticker.yaml
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,6 @@
    watchlist:
    - ETH-USD
    - BTC-USD
    - NANO-USD
    - XLM-USD
    - XMR-USD
    - EGLD-USD
    - MIOTA-USD
    - AAPL
    - XM
  2. robmcelhinney revised this gist May 6, 2022. 1 changed file with 10 additions and 11 deletions.
    21 changes: 10 additions & 11 deletions TickerTok.py
    Original file line number Diff line number Diff line change
    @@ -126,18 +126,7 @@ def createTable(data, holdings=None):
    holdingRow,
    emoji,
    )

    totalChange += change * holding
    totalChangePercent = (totalChange / (totalHoldings - totalChange)) * 100

    if totalChange >= 0:
    console.print("Daily Change: [green3]~${:.2f}[green3]".format(totalChange))
    console.print("Daily % Change: [green3]~{:.2f}%[green3]".format(totalChangePercent))
    else:
    console.print("Daily Change: [red1]~${:.2f}[red1]".format(totalChange))
    console.print("Daily % Change: [red1]~{:.2f}%[red1]".format(totalChangePercent))
    console.print("Daily Change Percent: ~${:.2f}".format(totalChangePercent))
    console.print("Total Holdings: [bold dodger_blue1]~${:.2f}[bold dodger_blue1]".format(totalHoldings))
    else:
    table.add_row(
    ticker["symbol"],
    @@ -149,6 +138,16 @@ def createTable(data, holdings=None):
    emoji,
    )
    console.print(table)
    if holdings:
    totalChangePercent = (totalChange / (totalHoldings - totalChange)) * 100
    if totalChange >= 0:
    console.print("Daily Change: [green3]~${:.2f}[green3]".format(totalChange))
    console.print("Daily % Change: [green3]~{:.2f}%[green3]".format(totalChangePercent))
    else:
    console.print("Daily Change: [red1]~${:.2f}[red1]".format(totalChange))
    console.print("Daily % Change: [red1]~{:.2f}%[red1]".format(totalChangePercent))
    console.print("Daily Change Percent: ~${:.2f}".format(totalChangePercent))
    console.print("Total Holdings: [bold dodger_blue1]~${:.2f}[bold dodger_blue1]".format(totalHoldings))

    def refreshDataTable(watchlist, holdings):
    data = apiCall(watchlist)
  3. robmcelhinney revised this gist May 6, 2022. 3 changed files with 97 additions and 33 deletions.
    120 changes: 88 additions & 32 deletions TickerTok.py
    Original file line number Diff line number Diff line change
    @@ -3,13 +3,10 @@
    from rich.console import Console
    from rich.table import Table
    from rich import box

    import sys, argparse, logging

    import requests
    import json
    import math

    import time
    import yaml


    @@ -26,8 +23,9 @@ def millify(n):
    API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"
    fields = ["symbol", "marketState", "regularMarketPrice", "regularMarketChange", "regularMarketChangePercent", "displayName", "marketCap"]

    # eg: "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata: "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"
    # ex = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata = "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"


    def apiCall(symbols):
    fieldParameters = ""
    @@ -52,8 +50,9 @@ def apiCall(symbols):
    )

    url = "{}&fields={}&symbols={}".format(API_ENDPOINT, fieldParameters, symbolParameters)
    logging.debug("url: %s" % url)
    logging.debug("url: {}".format(url))
    r = requests.get(url, headers=headers)
    logging.debug("status_code: {}".format(r.status_code))

    quoteResponse = r.json()["quoteResponse"]
    error = quoteResponse["error"]
    @@ -64,7 +63,7 @@ def apiCall(symbols):
    return results


    def createTable(data):
    def createTable(data, holdings=None):
    console = Console()

    table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
    @@ -74,22 +73,27 @@ def createTable(data):
    table.add_column("Percent", justify="right")
    table.add_column("Change", justify="right")
    table.add_column("Market Cap", justify="right")
    if holdings:
    table.add_column("Holdings", justify="right")
    table.add_column(":thumbs_up:/:thumbs_down:")

    totalHoldings = 0
    totalChange = 0
    totalChangePercent = 0

    for ticker in data:
    changePercent = ticker["regularMarketChangePercent"]
    change = ticker["regularMarketChange"]

    changePercentStr = "{:.2f}".format(changePercent)
    changeStr = "{:.2f}".format(change)
    changeStr = "{:,.2f}".format(change)
    if changePercent > 0:
    changePercentStr = "[green3]{}%[green3]".format(changePercentStr)
    changeStr = "[green3]{}[green3]".format(changeStr)
    elif changePercent < 0:
    changePercentStr = "[red1]{}%[red1]".format(changePercentStr.replace("-", ""))
    changeStr = "[red1]{}[red1]".format(changeStr.replace("-", ""))

    emoji = ""
    if changePercent > 10:
    emoji = ":rocket:"
    elif changePercent < -10:
    @@ -99,26 +103,61 @@ def createTable(data):

    marketCap = millify(ticker["marketCap"])

    logging.debug("ticker: %s" % ticker)
    logging.debug("ticker: {}".format(ticker))
    displayNameStr = ticker["symbol"]
    if "displayName" in ticker:
    displayNameStr = str(ticker["displayName"])

    table.add_row(
    ticker["symbol"],
    displayNameStr,
    str(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    emoji
    )


    if holdings:
    logging.debug("holdings: {}".format(holdings))
    holding = float(holdings[ticker["symbol"]])
    holdingValue = holding * float(ticker["regularMarketPrice"])
    totalHoldings += holdingValue
    logging.debug("holdingValue: {}".format(holdingValue))
    holdingRow = "{:,.2f}".format(holdingValue)

    table.add_row(
    ticker["symbol"],
    displayNameStr,
    "{:.2f}".format(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    holdingRow,
    emoji,
    )

    totalChange += change * holding
    totalChangePercent = (totalChange / (totalHoldings - totalChange)) * 100

    if totalChange >= 0:
    console.print("Daily Change: [green3]~${:.2f}[green3]".format(totalChange))
    console.print("Daily % Change: [green3]~{:.2f}%[green3]".format(totalChangePercent))
    else:
    console.print("Daily Change: [red1]~${:.2f}[red1]".format(totalChange))
    console.print("Daily % Change: [red1]~{:.2f}%[red1]".format(totalChangePercent))
    console.print("Daily Change Percent: ~${:.2f}".format(totalChangePercent))
    console.print("Total Holdings: [bold dodger_blue1]~${:.2f}[bold dodger_blue1]".format(totalHoldings))
    else:
    table.add_row(
    ticker["symbol"],
    displayNameStr,
    "{:.2f}".format(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    emoji,
    )
    console.print(table)

    def refreshDataTable(watchlist, holdings):
    data = apiCall(watchlist)
    logging.debug("data: {}".format(data))
    createTable(data, holdings)

    # Gather our code in a main() function
    def main(args):
    logging.debug("Your Argument: %s" % args)
    logging.debug("Your Argument: {}".format(args))

    if not args.watchlist and not args.file:
    logging.error("Must give watchlists as parameter or file")
    @@ -127,28 +166,37 @@ def main(args):
    watchlist = []
    if args.watchlist:
    watchlist = (args.watchlist).split(",")
    logging.debug("watchlist: %s" % watchlist)
    logging.debug("watchlist: {}".format(watchlist))

    holdings = None
    file = (args.file)
    if file:
    try:
    yamlFile = open(file)
    yamlFile = yaml.load(yamlFile, Loader=yaml.FullLoader)
    yamlWatchlist = yamlFile["watchlist"]

    watchlist = list(set(watchlist + yamlWatchlist))

    if "watchlist" in yamlFile:
    yamlWatchlist = yamlFile["watchlist"]
    watchlist = list(set(watchlist + yamlWatchlist))
    elif "holdings" in yamlFile:
    holdings = yamlFile["holdings"]
    watchlist = set(holdings.keys())
    except IOError as err:
    logging.error("Could not open file {}. Error: {}".format(file, err))
    sys.exit()
    except yaml.YAMLError as err:
    logging.error("Could not load yaml from file {}. Error: {}".format(file, err))
    sys.exit()

    watchlist = sorted(watchlist)
    data = apiCall(watchlist)
    logging.debug("data: %s" % data)
    createTable(data)

    if (args.interval):
    while True:
    data = apiCall(watchlist)
    logging.debug("data: {}".format(data))
    print(chr(27) + "[2J")
    createTable(data, holdings)
    time.sleep(args.interval)
    refreshDataTable(watchlist, holdings)


    if __name__ == '__main__':
    @@ -170,6 +218,14 @@ def main(args):
    action="store",
    help="file storing watchlist (yaml)",
    default=None)
    parser.add_argument(
    "-i",
    "--interval",
    dest="interval",
    action="store",
    type=int,
    help="interval to refresh table",
    default=None)
    parser.add_argument(
    "-v",
    "--verbose",
    4 changes: 4 additions & 0 deletions holdings.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,4 @@
    holdings:
    ETH-USD: 32
    ENS-USD: 10000
    XM: 10000
    6 changes: 5 additions & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -14,11 +14,15 @@ Python script that returns table with stocks/cryptos

    ```sh
    > python3 tickerTok.py -f ticker.yaml
    > python3 tickerTok.py -w ETH-USD,XM,AAPL
    ```

    To auto update use `watch`
    ```sh
    > watch -n 60 python3 tickerTok.py -f ticker.yaml
    > watch -t -c python3 tickerTok.py -f ticker.yaml
    ```
    ```sh
    > watch -t -c python3 tickerTok.py -f holdings.yaml
    ```

    ## Help
  4. robmcelhinney revised this gist May 6, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,7 @@ To auto update use `watch`

    Any advise for common problems or issues.
    ```
    command to run if program contains helper info
    > python3 tickerTok.py -h
    ```

    ## License
  5. robmcelhinney revised this gist May 3, 2022. 1 changed file with 38 additions and 0 deletions.
    38 changes: 38 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    # TickerTok

    Simple command line portfolio tracker

    ## Description

    Python script that returns table with stocks/cryptos

    ## Getting Started


    ### Executing program


    ```sh
    > python3 tickerTok.py -f ticker.yaml
    ```

    To auto update use `watch`
    ```sh
    > watch -n 60 python3 tickerTok.py -f ticker.yaml
    ```

    ## Help

    Any advise for common problems or issues.
    ```
    command to run if program contains helper info
    ```

    ## License

    This project is licensed under the GNU Lesser General Public License v3.0


    ## Acknowledgments

    Using the Yahoo Finance API
  6. robmcelhinney revised this gist May 3, 2022. No changes.
  7. robmcelhinney revised this gist May 3, 2022. No changes.
  8. robmcelhinney revised this gist May 3, 2022. No changes.
  9. robmcelhinney revised this gist May 3, 2022. No changes.
  10. robmcelhinney revised this gist May 3, 2022. No changes.
  11. robmcelhinney revised this gist May 3, 2022. 2 changed files with 188 additions and 188 deletions.
    188 changes: 188 additions & 0 deletions TickerTok.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,188 @@
    #!/usr/bin/env python

    from rich.console import Console
    from rich.table import Table
    from rich import box

    import sys, argparse, logging

    import requests
    import json
    import math

    import yaml


    millnames = ['', ' thousand',' m',' b',' t']

    def millify(n):
    n = float(n)
    millidx = max(0, min(len(millnames) - 1,
    int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))

    return '{:.2f}{}'.format(n / 10**(3 * millidx), millnames[millidx])


    API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"
    fields = ["symbol", "marketState", "regularMarketPrice", "regularMarketChange", "regularMarketChangePercent", "displayName", "marketCap"]

    # eg: "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata: "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"

    def apiCall(symbols):
    fieldParameters = ""
    for i in range(0, len(fields)):
    fieldParameters += fields[i]
    if i != len(fields) - 1:
    fieldParameters += ","

    symbolParameters = ""
    for i in range(0, len(symbols)):
    symbolParameters += symbols[i]
    if i != len(symbols) - 1:
    symbolParameters += ","

    # Get a copy of the default headers that requests would use
    headers = requests.utils.default_headers()
    headers.update(
    {
    'User-agent': 'Mozilla/5.0',
    'From': '[email protected]' # This is another valid field
    }
    )

    url = "{}&fields={}&symbols={}".format(API_ENDPOINT, fieldParameters, symbolParameters)
    logging.debug("url: %s" % url)
    r = requests.get(url, headers=headers)

    quoteResponse = r.json()["quoteResponse"]
    error = quoteResponse["error"]
    if error:
    logging.error("WARNING ERROR!!!!")

    results = quoteResponse["result"]
    return results


    def createTable(data):
    console = Console()

    table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
    table.add_column("Ticker", width=10)
    table.add_column("Name")
    table.add_column("Price", justify="right")
    table.add_column("Percent", justify="right")
    table.add_column("Change", justify="right")
    table.add_column("Market Cap", justify="right")
    table.add_column(":thumbs_up:/:thumbs_down:")

    for ticker in data:
    changePercent = ticker["regularMarketChangePercent"]
    change = ticker["regularMarketChange"]

    changePercentStr = "{:.2f}".format(changePercent)
    changeStr = "{:.2f}".format(change)
    if changePercent > 0:
    changePercentStr = "[green3]{}%[green3]".format(changePercentStr)
    changeStr = "[green3]{}[green3]".format(changeStr)
    elif changePercent < 0:
    changePercentStr = "[red1]{}%[red1]".format(changePercentStr.replace("-", ""))
    changeStr = "[red1]{}[red1]".format(changeStr.replace("-", ""))

    emoji = ""
    if changePercent > 10:
    emoji = ":rocket:"
    elif changePercent < -10:
    emoji = ":pile_of_poo:"
    else:
    emoji = ":neutral_face:"

    marketCap = millify(ticker["marketCap"])

    logging.debug("ticker: %s" % ticker)
    displayNameStr = ticker["symbol"]
    if "displayName" in ticker:
    displayNameStr = str(ticker["displayName"])

    table.add_row(
    ticker["symbol"],
    displayNameStr,
    str(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    emoji
    )

    console.print(table)

    # Gather our code in a main() function
    def main(args):
    logging.debug("Your Argument: %s" % args)

    if not args.watchlist and not args.file:
    logging.error("Must give watchlists as parameter or file")
    sys.exit()

    watchlist = []
    if args.watchlist:
    watchlist = (args.watchlist).split(",")
    logging.debug("watchlist: %s" % watchlist)

    file = (args.file)
    if file:
    try:
    yamlFile = open(file)
    yamlFile = yaml.load(yamlFile, Loader=yaml.FullLoader)
    yamlWatchlist = yamlFile["watchlist"]

    watchlist = list(set(watchlist + yamlWatchlist))

    except IOError as err:
    logging.error("Could not open file {}. Error: {}".format(file, err))
    sys.exit()
    except yaml.YAMLError as err:
    logging.error("Could not load yaml from file {}. Error: {}".format(file, err))
    sys.exit()

    watchlist = sorted(watchlist)
    data = apiCall(watchlist)
    logging.debug("data: %s" % data)
    createTable(data)


    if __name__ == '__main__':
    parser = argparse.ArgumentParser(
    description = "Tracks stocks using yahoo finance api.",
    epilog = "As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.",
    fromfile_prefix_chars = '@' )
    parser.add_argument(
    "-w"
    "--watchlist",
    dest="watchlist",
    action="store",
    help = "pass watchlist to the program. Comma separated",
    default=None)
    parser.add_argument(
    "-f",
    "--file",
    dest="file",
    action="store",
    help="file storing watchlist (yaml)",
    default=None)
    parser.add_argument(
    "-v",
    "--verbose",
    help="increase output verbosity",
    action="store_true")
    args = parser.parse_args()

    # Setup logging
    if args.verbose:
    loglevel = logging.DEBUG
    else:
    loglevel = logging.INFO

    logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel)

    main(args)
    188 changes: 0 additions & 188 deletions tickerTok.py
    Original file line number Diff line number Diff line change
    @@ -1,188 +0,0 @@
    #!/usr/bin/env python

    from rich.console import Console
    from rich.table import Table
    from rich import box

    import sys, argparse, logging

    import requests
    import json
    import math

    import yaml


    millnames = ['', ' thousand',' m',' b',' t']

    def millify(n):
    n = float(n)
    millidx = max(0, min(len(millnames) - 1,
    int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))

    return '{:.2f}{}'.format(n / 10**(3 * millidx), millnames[millidx])


    API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"
    fields = ["symbol", "marketState", "regularMarketPrice", "regularMarketChange", "regularMarketChangePercent", "displayName", "marketCap"]

    # eg: "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata: "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"

    def apiCall(symbols):
    fieldParameters = ""
    for i in range(0, len(fields)):
    fieldParameters += fields[i]
    if i != len(fields) - 1:
    fieldParameters += ","

    symbolParameters = ""
    for i in range(0, len(symbols)):
    symbolParameters += symbols[i]
    if i != len(symbols) - 1:
    symbolParameters += ","

    # Get a copy of the default headers that requests would use
    headers = requests.utils.default_headers()
    headers.update(
    {
    'User-agent': 'Mozilla/5.0',
    'From': '[email protected]' # This is another valid field
    }
    )

    url = "{}&fields={}&symbols={}".format(API_ENDPOINT, fieldParameters, symbolParameters)
    logging.debug("url: %s" % url)
    r = requests.get(url, headers=headers)

    quoteResponse = r.json()["quoteResponse"]
    error = quoteResponse["error"]
    if error:
    logging.error("WARNING ERROR!!!!")

    results = quoteResponse["result"]
    return results


    def createTable(data):
    console = Console()

    table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
    table.add_column("Ticker", width=10)
    table.add_column("Name")
    table.add_column("Price", justify="right")
    table.add_column("Percent", justify="right")
    table.add_column("Change", justify="right")
    table.add_column("Market Cap", justify="right")
    table.add_column(":thumbs_up:/:thumbs_down:")

    for ticker in data:
    changePercent = ticker["regularMarketChangePercent"]
    change = ticker["regularMarketChange"]

    changePercentStr = "{:.2f}".format(changePercent)
    changeStr = "{:.2f}".format(change)
    if changePercent > 0:
    changePercentStr = "[green3]{}%[green3]".format(changePercentStr)
    changeStr = "[green3]{}[green3]".format(changeStr)
    elif changePercent < 0:
    changePercentStr = "[red1]{}%[red1]".format(changePercentStr.replace("-", ""))
    changeStr = "[red1]{}[red1]".format(changeStr.replace("-", ""))

    emoji = ""
    if changePercent > 10:
    emoji = ":rocket:"
    elif changePercent < -10:
    emoji = ":pile_of_poo:"
    else:
    emoji = ":neutral_face:"

    marketCap = millify(ticker["marketCap"])

    logging.debug("ticker: %s" % ticker)
    displayNameStr = ticker["symbol"]
    if "displayName" in ticker:
    displayNameStr = str(ticker["displayName"])

    table.add_row(
    ticker["symbol"],
    displayNameStr,
    str(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    emoji
    )

    console.print(table)

    # Gather our code in a main() function
    def main(args):
    logging.debug("Your Argument: %s" % args)

    if not args.watchlist and not args.file:
    logging.error("Must give watchlists as parameter or file")
    sys.exit()

    watchlist = []
    if args.watchlist:
    watchlist = (args.watchlist).split(",")
    logging.debug("watchlist: %s" % watchlist)

    file = (args.file)
    if file:
    try:
    yamlFile = open(file)
    yamlFile = yaml.load(yamlFile, Loader=yaml.FullLoader)
    yamlWatchlist = yamlFile["watchlist"]

    watchlist = list(set(watchlist + yamlWatchlist))

    except IOError as err:
    logging.error("Could not open file {}. Error: {}".format(file, err))
    sys.exit()
    except yaml.YAMLError as err:
    logging.error("Could not load yaml from file {}. Error: {}".format(file, err))
    sys.exit()

    watchlist = sorted(watchlist)
    data = apiCall(watchlist)
    logging.debug("data: %s" % data)
    createTable(data)


    if __name__ == '__main__':
    parser = argparse.ArgumentParser(
    description = "Tracks stocks using yahoo finance api.",
    epilog = "As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.",
    fromfile_prefix_chars = '@' )
    parser.add_argument(
    "-w"
    "--watchlist",
    dest="watchlist",
    action="store",
    help = "pass watchlist to the program. Comma separated",
    default=None)
    parser.add_argument(
    "-f",
    "--file",
    dest="file",
    action="store",
    help="file storing watchlist (yaml)",
    default=None)
    parser.add_argument(
    "-v",
    "--verbose",
    help="increase output verbosity",
    action="store_true")
    args = parser.parse_args()

    # Setup logging
    if args.verbose:
    loglevel = logging.DEBUG
    else:
    loglevel = logging.INFO

    logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel)

    main(args)
  12. robmcelhinney renamed this gist May 3, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  13. robmcelhinney revised this gist May 3, 2022. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions ticker.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    watchlist:
    - ETH-USD
    - BTC-USD
    - NANO-USD
    - XLM-USD
    - XMR-USD
    - EGLD-USD
    - MIOTA-USD
    - AAPL
  14. robmcelhinney revised this gist May 3, 2022. 1 changed file with 0 additions and 8 deletions.
    8 changes: 0 additions & 8 deletions ticket.yaml
    Original file line number Diff line number Diff line change
    @@ -1,8 +0,0 @@
    watchlist:
    - ETH-USD
    - BTC-USD
    - NANO-USD
    - XMR-USD
    - EGLD-USD
    - MIOTA-USD
    - AAPL
  15. robmcelhinney revised this gist May 2, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion ticketTok.py
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ def apiCall(symbols):
    headers.update(
    {
    'User-agent': 'Mozilla/5.0',
    'From': 'yahoofinanceapi@robmcelhinney.com' # This is another valid field
    'From': 'yahoofinanceapi@example.com' # This is another valid field
    }
    )

  16. robmcelhinney revised this gist May 2, 2022. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions ticketTok.py
    Original file line number Diff line number Diff line change
    @@ -26,9 +26,8 @@ def millify(n):
    API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"
    fields = ["symbol", "marketState", "regularMarketPrice", "regularMarketChange", "regularMarketChangePercent", "displayName", "marketCap"]

    # ex = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata = "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"

    # eg: "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata: "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"

    def apiCall(symbols):
    fieldParameters = ""
    @@ -48,7 +47,7 @@ def apiCall(symbols):
    headers.update(
    {
    'User-agent': 'Mozilla/5.0',
    'From': 'yahoofinanceapi@example.com' # This is another valid field
    'From': 'yahoofinanceapi@robmcelhinney.com' # This is another valid field
    }
    )

  17. robmcelhinney created this gist May 2, 2022.
    8 changes: 8 additions & 0 deletions ticket.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    watchlist:
    - ETH-USD
    - BTC-USD
    - NANO-USD
    - XMR-USD
    - EGLD-USD
    - MIOTA-USD
    - AAPL
    189 changes: 189 additions & 0 deletions ticketTok.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,189 @@
    #!/usr/bin/env python

    from rich.console import Console
    from rich.table import Table
    from rich import box

    import sys, argparse, logging

    import requests
    import json
    import math

    import yaml


    millnames = ['', ' thousand',' m',' b',' t']

    def millify(n):
    n = float(n)
    millidx = max(0, min(len(millnames) - 1,
    int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))

    return '{:.2f}{}'.format(n / 10**(3 * millidx), millnames[millidx])


    API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"
    fields = ["symbol", "marketState", "regularMarketPrice", "regularMarketChange", "regularMarketChangePercent", "displayName", "marketCap"]

    # ex = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL,NFLX"
    # fulldata = "https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com&symbols=BBBY,GME"


    def apiCall(symbols):
    fieldParameters = ""
    for i in range(0, len(fields)):
    fieldParameters += fields[i]
    if i != len(fields) - 1:
    fieldParameters += ","

    symbolParameters = ""
    for i in range(0, len(symbols)):
    symbolParameters += symbols[i]
    if i != len(symbols) - 1:
    symbolParameters += ","

    # Get a copy of the default headers that requests would use
    headers = requests.utils.default_headers()
    headers.update(
    {
    'User-agent': 'Mozilla/5.0',
    'From': '[email protected]' # This is another valid field
    }
    )

    url = "{}&fields={}&symbols={}".format(API_ENDPOINT, fieldParameters, symbolParameters)
    logging.debug("url: %s" % url)
    r = requests.get(url, headers=headers)

    quoteResponse = r.json()["quoteResponse"]
    error = quoteResponse["error"]
    if error:
    logging.error("WARNING ERROR!!!!")

    results = quoteResponse["result"]
    return results


    def createTable(data):
    console = Console()

    table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
    table.add_column("Ticker", width=10)
    table.add_column("Name")
    table.add_column("Price", justify="right")
    table.add_column("Percent", justify="right")
    table.add_column("Change", justify="right")
    table.add_column("Market Cap", justify="right")
    table.add_column(":thumbs_up:/:thumbs_down:")

    for ticker in data:
    changePercent = ticker["regularMarketChangePercent"]
    change = ticker["regularMarketChange"]

    changePercentStr = "{:.2f}".format(changePercent)
    changeStr = "{:.2f}".format(change)
    if changePercent > 0:
    changePercentStr = "[green3]{}%[green3]".format(changePercentStr)
    changeStr = "[green3]{}[green3]".format(changeStr)
    elif changePercent < 0:
    changePercentStr = "[red1]{}%[red1]".format(changePercentStr.replace("-", ""))
    changeStr = "[red1]{}[red1]".format(changeStr.replace("-", ""))

    emoji = ""
    if changePercent > 10:
    emoji = ":rocket:"
    elif changePercent < -10:
    emoji = ":pile_of_poo:"
    else:
    emoji = ":neutral_face:"

    marketCap = millify(ticker["marketCap"])

    logging.debug("ticker: %s" % ticker)
    displayNameStr = ticker["symbol"]
    if "displayName" in ticker:
    displayNameStr = str(ticker["displayName"])

    table.add_row(
    ticker["symbol"],
    displayNameStr,
    str(ticker["regularMarketPrice"]),
    changePercentStr,
    changeStr,
    marketCap,
    emoji
    )

    console.print(table)

    # Gather our code in a main() function
    def main(args):
    logging.debug("Your Argument: %s" % args)

    if not args.watchlist and not args.file:
    logging.error("Must give watchlists as parameter or file")
    sys.exit()

    watchlist = []
    if args.watchlist:
    watchlist = (args.watchlist).split(",")
    logging.debug("watchlist: %s" % watchlist)

    file = (args.file)
    if file:
    try:
    yamlFile = open(file)
    yamlFile = yaml.load(yamlFile, Loader=yaml.FullLoader)
    yamlWatchlist = yamlFile["watchlist"]

    watchlist = list(set(watchlist + yamlWatchlist))

    except IOError as err:
    logging.error("Could not open file {}. Error: {}".format(file, err))
    sys.exit()
    except yaml.YAMLError as err:
    logging.error("Could not load yaml from file {}. Error: {}".format(file, err))
    sys.exit()

    watchlist = sorted(watchlist)
    data = apiCall(watchlist)
    logging.debug("data: %s" % data)
    createTable(data)


    if __name__ == '__main__':
    parser = argparse.ArgumentParser(
    description = "Tracks stocks using yahoo finance api.",
    epilog = "As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.",
    fromfile_prefix_chars = '@' )
    parser.add_argument(
    "-w"
    "--watchlist",
    dest="watchlist",
    action="store",
    help = "pass watchlist to the program. Comma separated",
    default=None)
    parser.add_argument(
    "-f",
    "--file",
    dest="file",
    action="store",
    help="file storing watchlist (yaml)",
    default=None)
    parser.add_argument(
    "-v",
    "--verbose",
    help="increase output verbosity",
    action="store_true")
    args = parser.parse_args()

    # Setup logging
    if args.verbose:
    loglevel = logging.DEBUG
    else:
    loglevel = logging.INFO

    logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel)

    main(args)