DEV Community

Pawel Suchanecki
Pawel Suchanecki

Posted on • Updated on

Generate ASCII Graphs of Cryptocurrency Prices in Python

Have you ever wanted to visualize the historical prices of a cryptocurrency in a fun and interactive way? Well, look no further! In this article, we'll explore how to generate an ASCII graph of cryptocurrency prices using Python.

Disclaimer:

The author of this article is not affiliated with Binance in any way. This code was written to retrieve and visualize data, which the author found to be useful and accessible without requiring an API key. The author is not responsible for any errors or issues that may arise from using this code.

Example

$ python3 ascii-currency-graphs.py --pair BTCEUR --start-date 2023-03-14 --end-date 2023-04-01
2023-03-14T01:00:00 ########################################### 22985.84
2023-03-15T01:00:00 ########################################### 23026.80
2023-03-16T01:00:00 ############################################ 23665.73
2023-03-17T01:00:00 ################################################ 25789.77
2023-03-18T01:00:00 ############################################### 25373.59
2023-03-19T01:00:00 ################################################## 26474.44
2023-03-20T01:00:00 ################################################# 26082.53
2023-03-21T01:00:00 ################################################# 26324.74
2023-03-22T01:00:00 ############################################### 25342.45
2023-03-23T01:00:00 ################################################# 26260.20
2023-03-24T01:00:00 ################################################ 25746.57
2023-03-25T01:00:00 ################################################ 25735.12
2023-03-26T01:00:00 ################################################# 26076.46
2023-03-27T02:00:00 ############################################### 25267.76
2023-03-28T02:00:00 ############################################### 25189.56
2023-03-29T02:00:00 ################################################# 26188.76
2023-03-30T02:00:00 ################################################ 25798.34
2023-03-31T02:00:00 ################################################# 26332.77
Enter fullscreen mode Exit fullscreen mode

Raw Data

Here you can check the data that we get from Binance. The below presented script (The Code) receives it for command:

python3 ascii-currency-graphs.py --pair BTCEUR --start-date 2023-04-01 --end-date 2023-04-05
Enter fullscreen mode Exit fullscreen mode
[
  [
    1680307200000,
    "26330.62000000",
    "26633.95000000",
    "26127.13000000",
    "26315.71000000",
    "494.04749000",
    1680393599999,
    "13008528.45896390",
    50549,
    "256.75654000",
    "6762406.03339990",
    "0"
  ],
  [
    1680393600000,
    "26319.67000000",
    "26403.97000000",
    "25828.00000000",
    "26184.72000000",
    "571.36554000",
    1680479999999,
    "14920527.65324270",
    55327,
    "277.62573000",
    "7250885.00425640",
    "0"
  ],
  [
    1680480000000,
    "26187.25000000",
    "26349.00000000",
    "25221.16000000",
    "25662.56000000",
    "1681.40230000",
    1680566399999,
    "43525785.31802880",
    100106,
    "868.39176000",
    "22493356.97115660",
    "0"
  ],
  [
    1680566400000,
    "25662.15000000",
    "26182.85000000",
    "25488.59000000",
    "25795.05000000",
    "1008.78663000",
    1680652799999,
    "26053821.41279880",
    80241,
    "579.95600000",
    "14980595.35159550",
    "0"
  ]
]

Enter fullscreen mode Exit fullscreen mode

The Code

import argparse
import datetime
import requests


def iso_date(date_string):
    """Convert ISO-formatted date string to timestamp."""
    try:
        date = datetime.datetime.strptime(date_string, '%Y-%m-%d')
        timestamp = int(date.timestamp() * 1000)
        return timestamp
    except ValueError:
        raise argparse.ArgumentTypeError(
            f"Invalid date format: {date_string}. Date should be in the format YYYY-MM-DD."
        )


def get_crypto_prices(start_timestamp, end_timestamp, pair):
    """Retrieve historical prices for the specified trading pair and date range."""
    start_date = datetime.date.fromtimestamp(start_timestamp / 1000)
    end_date = datetime.date.fromtimestamp(end_timestamp / 1000)

    symbol = pair.replace(':', '').replace('_', '').upper()
    url = f"https://api.binance.com/api/v3/klines?symbol={symbol}&interval=1d&startTime={start_timestamp}&endTime={end_timestamp}"
    response = requests.get(url)

    if response.status_code == 200:
        prices = response.json()
        return [(datetime.datetime.fromtimestamp(int(price[0]) / 1000).isoformat(), float(price[4])) for price in prices]
    else:
        print(f"Failed to retrieve prices for {pair} from {start_date} - {end_date}")
        return []


def generate_ascii_graph(data):
    """Generate an ASCII graph of cryptocurrency prices."""
    max_price = max(data, key=lambda x: x[1])[1]

    for date, price in data:
        bar = '#' * int(price / max_price * 50)
        print(f"{date} {bar} {price:.2f}")


def list_cryptocurrencies():
    """List all possible cryptocurrencies supported by the Binance API."""
    url = 'https://api.binance.com/api/v3/exchangeInfo'
    response = requests.get(url)

    if response.status_code == 200:
        data = response.json()
        symbols = data['symbols']
        currencies = set()

        for symbol in symbols:
            base_currency = symbol['baseAsset']
            quote_currency = symbol['quoteAsset']
            currencies.add(base_currency)
            currencies.add(quote_currency)

        print("Available cryptocurrencies on Binance:")
        for currency in sorted(currencies):
            print(currency)
    else:
        print("Failed to retrieve list of cryptocurrencies from Binance.")


if __name__ == '__main__':
    # Parse command-line arguments
    parser = argparse.ArgumentParser(description="Generate an ASCII graph of cryptocurrency prices for a given date range")
    parser.add_argument("--pair", help="Trading pair for the historical data in the format 'BTC:USDT' or 'BTCUSDT'", default='BTCUSDT')
    parser.add_argument("--list", help="List all possible cryptocurrencies supported by the Binance API", action='store_true')
    parser.add_argument("--start-date", type=iso_date, help="Start date (in YYYY-MM-DD format) for the historical data", default=int((datetime.datetime.now() - datetime.timedelta(days=1)).timestamp() * 1000))
    parser.add_argument("--end-date", type=iso_date, help="End date (in YYYY-MM-DD format) for the historical data", default=int(datetime.datetime.now().timestamp() * 1000))
    args = parser.parse_args()

    if args.list:
        list_cryptocurrencies()
    else:
        # Retrieve and process cryptocurrency prices
        prices = get_crypto_prices(args.start_date, args.end_date, args.pair)
        if prices:
            generate_ascii_graph(prices)
Enter fullscreen mode Exit fullscreen mode

What does this code do?

This Python code retrieves historical prices for a specified cryptocurrency trading pair from the Binance API and generates an ASCII graph of the prices for the specified date range. It also allows you to list all possible cryptocurrencies supported by the Binance API. You can easily run this code from the command line and get a cool visualization of the cryptocurrency prices.

How can you add it to your .bashrc or MOTD regenerator?

If you're feeling adventurous, you can add this code to your .bashrc or MOTD regenerator for fun and profit! Just call the script to your .bashrc or MOTD regenerator. Now, every time you open your terminal or log in to your server, you'll be greeted with a visualization of the current cryptocurrency prices!

How does the code work?

Parsing Command-Line Arguments

The code uses Python's built-in argparse module to parse command-line arguments. The parser.add_argument() method is used to define the different arguments that the script accepts. For example, the --pair argument is used to specify the trading pair for the historical data, while the --start-date and --end-date arguments are used to specify the date range for the historical data. The --list argument is used to list all possible cryptocurrencies supported by the Binance API.

Retrieving Historical Data

The get_crypto_prices() function retrieves historical prices for a specified cryptocurrency trading pair and date range from the Binance API. It uses the requests module to make an HTTP GET request to the Binance API, and then parses the JSON response to extract the historical prices. The function returns a list of tuples, where each tuple contains a date and a price.

Generating an ASCII Graph

The generate_ascii_graph() function takes a list of tuples containing dates and prices, and generates an ASCII graph of the prices. It first determines the maximum price in the dataset using a lambda function that calls the max function with a key argument of lambda x: x[1]. This specifies that we want to get the maximum price based on the second element of each tuple in the dataset. It then loops through the data and generates a bar chart for each data point, with the length of the bar proportional to the price relative to the maximum price.

Listing All Cryptocurrencies Supported by Binance

The list_cryptocurrencies() function retrieves a list of all possible cryptocurrencies supported by the Binance API. It makes an HTTP GET request to the Binance API and parses the JSON response to extract the list of symbols. It then extracts the base and quote currencies from each symbol and adds them to a set of unique currencies. Finally, it prints out the set of unique currencies in alphabetical order.

Lambda Explained

One interesting part of this code is the use of a lambda function to get the maximum price in the dataset. A lambda function is a small anonymous function that can have any number of arguments, but can only have one expression. In this code, we use a lambda function to get the maximum price in the dataset by calling the max function with a key argument of lambda x: x[1]. This specifies that we want to get the maximum price based on the second element of each tuple in the dataset. If you're interested in learning more about lambda functions, check out the official Python documentation.

Example Usage

Here are some example usage scenarios for this code (written in 2023 ;-)):

  • To get the historical prices for BTCUSDT from the past week and generate an ASCII graph:
python ascii-currency-graphs.py --pair BTCUSDT --start-date 2023-03-26 --end-date 2023-04-02
Enter fullscreen mode Exit fullscreen mode
  • To get the historical prices for ETHBTC from the past year and generate an ASCII graph:
python ascii-currency-graphs.py --pair ETHBTC --start-date 2022-04-02`
Enter fullscreen mode Exit fullscreen mode
  • To list all possible cryptocurrencies supported by the Binance API:
python ascii-currency-graphs.py --list
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we learned how to generate an ASCII graph of cryptocurrency prices using Python. We explored the different parts of the code and how to use it from the command line. We also learned about lambda functions and how they can be used in Python. Now, go forth and visualize those cryptocurrency prices in style!

Next read

Stay tuned for the next article in this series, where we will build upon this code to generate PNG graphs with financial trendlines. This will give us a better understanding of the historical performance of cryptocurrencies and help us make informed decisions about our investments.

Top comments (1)

Collapse
 
xsub profile image
Pawel Suchanecki

Hey folks! ๐Ÿ˜ƒ If you're up for a fun programming challenge, let's see if you can come up with a solution to transform a horizontal bar graph into a vertical one. ๐Ÿš€๐Ÿค”

                                              #                
                                              ### #  #  # ###  
                                            # ### ####  #######
                                            ###################
                                            ###################
                                            ###################
                                           ####################
                ## ###                   ######################
              # #######  ## ##          #######################
              ################          #######################
########      ###################       #######################
########     ######################    ########################
####################################   ########################
####################################   ########################
##################################### #########################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
###############################################################
Enter fullscreen mode Exit fullscreen mode