How To Track Crypto in Home Assistant

Full guide: https://smarthomepursuits.com/how-to-track-crypto-prices-in-home-assistant/ Note that I have colored sections of code in my blog post, but that didn’t translate over this forum post.

Over the past few years, I’ve been intrigued by cryptocurrencies. I find the ups, downs, and various forums or news articles very interesting. I’ve even bought, sold, and held several coins myself.

To find the prices, I typically would open the Coinbase app, authenticate with 2FA, and then switch to the correct tab to view prices. While not very difficult, I did find this process somewhat cumbersome, as I was simply looking for a quick and easy way to view prices. That’s when it hit me: I should add a crypto price tracker into Home Assistant! I’ve already integrated just about everything else into HA, so this just made sense.

Before I get started with this step by step guide, I wanted to point out that their are already several ways to do this. However, most of the methods I’ve came across had API limits or weren’t free, so I’m going to show you how to track and view cryptocurrency prices within Home Assistant in 2021.

I did not create this, I found this in this Home Assistant Community forum post. So, kudos to Craig_McGowan for creating this. While he had a pretty detailed post, there were several things I had to figure out myself so I decided to write a step-by-step guide as I set it up.

Let’s get started!

Step 1: Sign Up for Nomics API

First, navigate to the Nomics API URL and click “Send me my free API key”.

It will redirect you to a registration page, where you will need to enter an email address. Fill out the remaining fields on the next page.

Within a few seconds, you should receive your API key to your registered email account.

Step 2: Create Restful Sensor in Configuration.yaml

Next, log into Home Assistant > File Editor > Configuration.yaml.

Scroll to the bottom and add the following code. The code below will track Bitcoin & Ethereum. You can change these out with any coins or add new ones if you’d like.

  • Red: Replace APIKEY with the API key you received in Step 1.
  • Green: Replace with any other crypto or add additional ones. Must be comma-separated.
  • Orange & Purple: These will become Home Assistant entities, so make sure to change the names to reflect the currency you plan on tracking. If you want to track more than 2, just copy and paste an existing block of code starting with - name:
    • Blue: You will also need to increment the number in brackets [0]. For example, Bitcoin is [0], Ethereum is [1], and if you add a third crypto it will be [2]

If you already have a rest sensor in your configuration.yaml, just add everything below into your current rest sensor starting with - resource: If you don’t already have a rest sensor, copy everything below exactly as is.

Note: you must track AT LEAST 2 cryptocurrencies, otherwise this won’t work.

rest:
  - resource: https://api.nomics.com/v1/currencies/ticker?key=APIKEY&ids=BTC,ETH,LTC&interval=1h,1d,7d,30d&per-page=100&page=1&sort=first_priced_at
    scan_interval: 10
    sensor:
   ### BTC
      - name: "Crypto - BTC"
        json_attributes_path: "$.[0]"
        value_template: '{{ value_json[0].price | round(4) }}'
        unit_of_measurement: "USD"
        json_attributes:
          - name
          - symbol
          - price
          - logo_url
          - rank
          - high
          - high_timestamp
          - market_cap
          - first_trade
      - name: "Crypto - BTC - 1 Hr"
        json_attributes_path: "$.[0].1h"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[0]["1h"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - BTC - 1 D"
        json_attributes_path: "$.[0].1d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[0]["1d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - BTC - 7 D"
        json_attributes_path: "$.[0].7d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[0]["7d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - BTC - 30 D"
        json_attributes_path: "$.[0].30d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[0]["30d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
       ### ETH
      - name: "Crypto - ETH"
        json_attributes_path: "$.[1]"
        value_template: '{{ value_json[1].price | round(4) }}'
        unit_of_measurement: "USD"
        json_attributes:
          - name
          - symbol
          - price
          - logo_url
          - rank
          - high
          - high_timestamp
          - market_cap
          - first_trade
      - name: "Crypto - ETH - 1 Hr"
        json_attributes_path: "$.[1].1h"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[1]["1h"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - ETH - 1 D"
        json_attributes_path: "$.[1].1d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[1]["1d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - ETH - 7 D"
        json_attributes_path: "$.[1].7d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[1]["7d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct
      - name: "Crypto - ETH - 30 D"
        json_attributes_path: "$.[1].30d"
        unit_of_measurement: "USD"
        value_template: '{{ value_json[1]["30d"]["price_change"] | round(4) }}'
        json_attributes:
          - price_change_pct

Save the configuration. Then go to Configuration > Server Management > Check configuration. If valid, restart Home Assistant.

Step 4: Basic Entity Test

As a very basic test, you can now go to your Lovelace dashboard and add an “Entities” card. Add your two entities by searching for “crypto”.

If everything is working well so far, and both cyptocurrencies show different prices, go ahead and move onto the next step. This test card is mainly used just to make sure everything is setup correctly before you go through the trouble of adding the additional frontend integrations via HACS.

Step 3: Install Lovelace Card Mods

If you want to make your crypto price tracker a little prettier, you will need to install 4 integrations via HACS.

Here’s an example of what it will end up looking after adding those:

You can add these to Home Assistant manually, but I highly recommend using HACS as it simplifies things a ton, making these installs as easy as 1-click.

Step 4: Create Lovelace Crypto Cards

On your Lovelace dashboard, add a card > scroll to the bottom > Manual. Paste each block of code into their own manual card. If you’ve been following my guide exactly (as far as using the same coins and naming conventions) you can just paste this in with no changes needed.

If you’ve added your own crypto’s, then you’ll need to change the sensor.crypto_ names to whatever your entities are called. You can view the names under Configurations > Entities.

Bitcoin:

type: custom:vertical-stack-in-card
cards:
  - type: entities
    entities:
      - type: custom:template-entity-row
        entity: sensor.crypto_btc
        name: '{{ state_attr(config.entity, ''name'') }}'
        secondary: '{{ state_attr(config.entity, ''symbol'') }}'
        image: '{{ state_attr(config.entity, ''logo_url'') }}'
        state: ${{ state_attr(config.entity, 'price') | round(2) }}
      - type: custom:template-entity-row
        entity: sensor.crypto_btc
        name: High
        icon: mdi:currency-usd
        state: ${{ state_attr(config.entity, 'high') | round (2)}}
        secondary: >-
          {{ as_timestamp(state_attr(config.entity, 'high_timestamp')) |
          timestamp_custom('%d-%m-%Y %H:%M ') }}
      - type: custom:template-entity-row
        entity: sensor.crypto_btc
        name: Crypto Rank
        icon: mdi:chart-line
        state: '{{ state_attr(config.entity, ''rank'') }}'
        secondary: ${{"{:,}".format(state_attr(config.entity, 'market_cap')|int)}}
  - type: custom:mini-graph-card
    hours_to_show: 3
    points_per_hour: 60
    show:
      icon: false
      name: false
    entities:
      - entity: sensor.crypto_btc
  - type: entities
    entities:
      - entity: sensor.crypto_btc_1_hr
        name: 1 Hour
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct')  | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_btc_1_d
        name: 1 Day
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_btc_7_d
        name: 7 Days
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_btc_30_d
        name: 30 Days
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}

Ethereum:

type: custom:vertical-stack-in-card
cards:
  - type: entities
    entities:
      - type: custom:template-entity-row
        entity: sensor.crypto_eth
        name: '{{ state_attr(config.entity, ''name'') }}'
        secondary: '{{ state_attr(config.entity, ''symbol'') }}'
        image: '{{ state_attr(config.entity, ''logo_url'') }}'
        state: ${{ state_attr(config.entity, 'price') | round(2) }}
      - type: custom:template-entity-row
        entity: sensor.crypto_eth
        name: High
        icon: mdi:currency-usd
        state: ${{ state_attr(config.entity, 'high') | round (2)}}
        secondary: >-
          {{ as_timestamp(state_attr(config.entity, 'high_timestamp')) |
          timestamp_custom('%d-%m-%Y %H:%M ') }}
      - type: custom:template-entity-row
        entity: sensor.crypto_eth
        name: Crypto Rank
        icon: mdi:chart-line
        state: '{{ state_attr(config.entity, ''rank'') }}'
        secondary: ${{"{:,}".format(state_attr(config.entity, 'market_cap')|int)}}
  - type: custom:mini-graph-card
    hours_to_show: 3
    points_per_hour: 60
    show:
      icon: false
      name: false
    entities:
      - entity: sensor.crypto_eth
  - type: entities
    entities:
      - entity: sensor.crypto_eth_1_hr
        name: 1 Hour
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct')  | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_eth_1_d
        name: 1 Day
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_eth_7_d
        name: 7 Days
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}
      - entity: sensor.crypto_eth_30_d
        name: 30 Days
        type: custom:template-entity-row
        state: ${{ states(config.entity) | round(2) }}
        secondary: >-
          {{ state_attr(config.entity, 'price_change_pct') | multiply(100) |
          round(4) }}%
        icon: |
          {% if states(config.entity) | float > 0 %}
             mdi:arrow-up-bold
          {% elif states(config.entity) | float < 0 %}
             mdi:arrow-down-bold
          {% else %}
             mdi:arrow-right-bold
          {% endif %}
        card_mod:
          style: |
            {% if states(config.entity) | float > 0 %}
               :host {
                 --paper-item-icon-color: green;
                 color: green
               }
            {% elif states(config.entity) | float < 0 %}
               :host {
                 --paper-item-icon-color: red;
                 color: red
               }
            {% else %}
               :host {
                 --paper-item-icon-color: black;
                 color: black
               }
            {% endif %}

Wrapping Up

Hopefully this guide helps you add all your favorite crypto’s to Home Assistant! I’ve only been using this for a few hours, but I wanted to document how I set this up as I went. So, I can’t comment on how well this works over a longer period of time. So far though, this seems to be working pretty well and I’m really happy with it.

I will note that the prices seem to be slightly off (when compared to Coinbase), but that is probably due to the polling intervals, even though when I view the sensor it looks like it polls every 5 seconds. I’m not someone who cares about the EXACT price of each coin, but I do like to check the rough price of each coin randomly so this is fine with me.

Also, you may notice that the Ethereum graph seems a little off. For some reason the graph initially showed the Bitcoin price which is skewing the results. What I mean by that is that the upper price is showing 33k, and the actual ETH price is 2.6k, so the graph isn’t accurately showing the small $10-$20 changes because the range is so high. I would expect this graph to level out a bit and show actual fluctuations once the upper limit of the Ethereum graph falls off.

UPDATE: Yep, I just wait a couple hours for the graph to update. All is good now, however I’m leaving that note above in case anyone else runs into the same issue.

Anyway, if you run into any issues or want to let me know if this guide worked for you, let me know in the comments below! I’ll do what I can to help.

5 Likes

Looks a good thorough guide. Will have a look at installing at the weekend.

Thanks! Let me know how it goes.

Thanks this works perfect

1 Like

You’re welcome! I’m glad you got it working.

If anyone is using Dwain’s Dashboard, I’ve made a more-page addon for this. Nothing fancy and mainly copy pasta, but here it is regardless.

edit: I guess it would help if I included a link to the addon! LOL

2 Likes

I have made a custom component for this, if somebody want to try my component. Please let it know.

2 Likes

I want, pls-.


Custom element doesn’t exist: vertical-stack-in-card. help me, thnaks

This is great - thanks for the walkthrough. It all worked perfectly and I managed to get BTC prices in GBP but it seems that the value reported by nomics is way under what Coinbase reports it as. The sensor is currently showing it as £31111.268 where Coinbase says it’s closer to £31,339.

Any ideas why this is?

The free API is on a hold for 2 months:

Dear Nomics Free API User:

After much thought, Nomics will be pausing our free API program for 60 days, starting this Friday, September 30th.

Our free API is heavily used and consumes considerable resources. We therefore need time to refactor our free API offering.

If you are a customer of our paid API, rest assured that we are as committed as ever to meeting your needs (indeed, the Nomics API is our primary source of revenue).

If you have any questions, please contact [email protected]

–Clay

I came here to check what has changed and now i have my answer - i didnt receive the email. What a shame.

are there free alternatives?

@djbrooks022

Now that Nomics is dead, what have you done with your card?

2 Likes