gdax_bot - Micro dollar cost averaging for crypto

kdmukai, updated 🕥 2022-12-08 01:17:53

gdax_bot

A basic Coinbase Pro buying bot that completes trades in any of their available market pairings

Relies on gdax-python. Props to danpaquin and thanks!

Trading Philosophy

Coinbase Pro overview

Coinbase Pro is the more professional cryptocurrency exchange that underlies Coinbase. If you have a Coinbase account, you have a Coinbase Pro account (create a Coinbase account). All trades on Coinbase include expensive tiered flat fees ($0.99+/tx) or 1.49%, plus a 0.5% spread on the market price (or up to 2% spread on crypto-to-crypto trades). Ouch.

But some trades on Coinbase Pro can be made at a greatly reduced rate (0.5%) or even free, depending on your transaction tier over the last 30 days. You just have to submit your buy or sell as a limit order. You are the "maker" of an offer and you await a "taker" to accept. The "takers" pay the fees, the "maker" pays a reduced fee (depending on your transaction tier). The tradeoff is that limit orders may or may not be fulfilled; if you're selling X crypto at $Y value and no one likes your price, your sell order won't go anywhere.

Basic investing strategy: Dollar Cost Averaging

You have to be extremely lucky or extremely good to time the market perfectly. Rather than trying to achieve the perfect timing for when to execute a purchase just set up your investment on a regular schedule. Buy X amount every Y days. Sometimes the market will be up, sometimes down. But over time your cache will more closely reflect the average market price with volatile peaks and valleys averaged out.

This approach is common for retirement accounts; you invest a fixed amount into your 401(k) every month and trust that the market trend will be overall up over time.

Micro Dollar Cost Averaging for cryptos

While I believe strongly in dollar cost averaging, the crypto world is so volatile that making a single, regular buy once a month is still leaving too much to chance. The market can swing 30%, 50%, even 100%+ in a single day. I'd rather invest $20 every day for a month than agonize over deciding on just the right time to do a single $600 buy.

And because we can do buy orders on Coinbase Pro with no fees (so long as they're submitted as limit orders), there's no penalty for splitting an order down to smaller intervals.

How far can you push micro dollar cost averaging?

Coinbase Pro sets different minimum order sizes for each crypto.

Current minimums as of 2018-01-11 are: BTC: 0.001 ETH: 0.01 LTC: 0.1 BCH: 0.01 XLM: 1.0

This combined with the current market price gives us the minimum fiat transaction amount.

For example, let's say BTC is at $8,000 USD. So the smallest possible buy order is $8,000*0.001 = $8.00. So if you were looking to invest $100 each month, you could do floor($100/$8) = 12 equal-sized buy orders; you couldn't do 13 equal-sized orders because $100/13 = $7.69 which would only be 0.00096 BTC. An order that small would be rejected by the API. Spreading out your $100 over 12 buys during the month is pretty good dollar cost averaging.

It gets even more fun if you have more money to invest. Let's say you have $900 and the minimum fiat transaction amount is less than $10. You can split your funds into 90 equal parts--that's three equal buy orders per day: $10 every eight hours. At this point your total average cost basis for your crypto should be just about identical to its average cost for the month.

I'm a big believer in this strategy for smoothing out crypto's short-term volatility while continuing to place your bets on its long-term value.

Adjust as prices change

If the crypto price keeps increasing, eventually your schedule will run up against the minimum purchase order size; you can't buy $13.9 of LTC if the price is greater than $139 (LTC's minimum order size is 0.1). In that case you'll have to increase how much you buy in each order, but decrease the frequency of the orders.

Technical Details

Basic approach

gdax_bot pulls the current bid and ask prices, averages the two to set our order's price, then submits it as a limit order.

Making a valid limit order

Buy orders will be rejected if they are at or above the lowest sell order (think: too far right on the order book) (see: https://stackoverflow.com/a/47447663) and vice-versa for sells. When the price is plummeting this is likely to happen. In this case gdax_bot will pause for a minute and then grab the latest price and re-place the order. It will currently attempt this 100 times before it gives up.

*Longer pauses are probably advantageous--if the price is crashing, you don't want to be rushing in.

Setup

Create a Coinbase account

Use my referral code and we'll both get $10 worth of BTC:
https://www.coinbase.com/join/59384a753bfa9c00d764ac76

Create a virtualenv

There's plenty of info elsewhere for the hows and whys.

Install requirements

pip install -r requirements.txt

Create Coinbase Pro API key

Try this out on Coinbase Pro's sandbox first. The sandbox is a test environment that is not connected to your actual fiat or crypto balances.

Log into your Coinbase/Coinbase Pro account in their test sandbox: https://public.sandbox.pro.coinbase.com/

Find and follow existing guides for creating an API key. Only grant the "Trade" permission. Note the passphrase, the new API key, and API key's secret.

While you're in the sandbox UI, fund your fiat account by transferring from the absurd fake balance that sits in the linked Coinbase account (remember, this is all just fake test data; no real money or crypto goes through the sandbox).

(Optional) Create an AWS Simple Notification System topic

This is out of scope for this document, but generate a set of AWS access keys and a new SNS topic to enable the bot to send email reports.

TODO: Make this optional

Customize settings

Update settings.conf with your API key info in the "sandbox" section. I recommend saving your version as settings-local.conf as that is already in the .gitignore so you don't have to worry about committing your sensitive info to your forked repo.

If you have an AWS SNS topic, enter the access keys and SNS topic.

TODO: Add support to read these values from environment vars

Try a basic test run

Run against the Coinbase Pro sandbox by including the -sandbox flag. Remember that the sandbox is just test data. The sandbox only supports BTC trading.

Activate your virtualenv and try a basic buy of $100 USD worth of BTC: python gdax_bot.py BTC-USD BUY 100 USD -sandbox -c ../settings-local.conf

Check the sandbox UI and you'll see your limit order listed. Unfortunately your order probably won't fill unless there's other activity in the sandbox.

Usage

Run python gdax_bot.py -h for usage information:

``` usage: gdax_bot.py [-h] [-sandbox] [-warn_after WARN_AFTER] [-j] [-c CONFIG_FILE] market_name {BUY,SELL} amount amount_currency

    This is a basic Coinbase Pro DCA buying/selling bot.

    ex:
        BTC-USD BUY 14 USD          (buy $14 worth of BTC)
        BTC-USD BUY 0.00125 BTC     (buy 0.00125 BTC)
        ETH-BTC SELL 0.00125 BTC    (sell 0.00125 BTC worth of ETH)
        ETH-BTC SELL 0.1 ETH        (sell 0.1 ETH)

positional arguments: market_name (e.g. BTC-USD, ETH-BTC, etc) {BUY,SELL} amount The quantity to buy or sell in the amount_currency amount_currency The currency the amount is denominated in

optional arguments: -h, --help show this help message and exit -sandbox Run against sandbox, skips user confirmation prompt -warn_after WARN_AFTER secs to wait before sending an alert that an order isn't done -j, --job Suppresses user confirmation prompt -c CONFIG_FILE, --config CONFIG_FILE Override default config file location ```

Scheduling your recurring buys

This is meant to be run as a crontab to make regular purchases on a set schedule. Here are some example cron jobs:

$50 USD of ETH every Monday at 17:23: 23 17 * * 1 /your/virtualenv/path/bin/python -u /your/gdax_bot/path/src/gdax_bot.py -j ETH-USD BUY 50.00 USD -c /your/settings/path/your_settings_file.conf >> /your/cron/log/path/cron.log The -u option makes python output stdout and stderr unbuffered so that you can watch the progress in real time by running tail -f cron.log.

€75 EUR of BTC every other day at 14:00: 00 14 */2 * * /your/virtualenv/path/bin/python -u /your/gdax_bot/path/src/gdax_bot.py -j BTC-EUR BUY 75.00 EUR -c /your/settings/path/your_settings_file.conf >> /your/cron/log/path/cron.log

£5 GBP of LTC every day on every third hour at the 38th minute (i.e. 00:38, 03:38, 06:38, 09:38, 12:38, 15:38, 18:38, 21:38): 38 */3 * * * /your/virtualenv/path/bin/python -u /your/gdax_bot/path/src/gdax_bot.py -j LTC-GBP BUY 5.00 GBP -c /your/settings/path/your_settings_file.conf >> /your/cron/log/path/cron.log

Unfilled orders will happen

The volatility may quickly carry the market away from you. Here we see a bunch of unfilled orders that are well below the current market price of $887.86: alt text

The gdax_bot will keep checking on the status of the order for up to an hour, after which it will report it as OPEN/UNFILLED. Hopefully the market will cool down again and return to your order's price, at which point it will fill (though gdax_bot will not send a notification). You can also manually cancel the order to free up the reserved fiat again.

I would recommend patience and let the unfilled order ride for a few hours or days. With micro dollar cost averaging it doesn't really matter if you miss a few buy orders.

Mac notes

Edit the crontab: env EDITOR=nano crontab -e

View the current crontab: crontab -l

Raspberry Pi notes

Download and flash Raspbian to an SD card using Balena Etcher. You can use a "headless" version (Raspbian Lite) with no monitor, no keyboard, no mouse with the following steps.

Remove and re-insert the SD card into the computer.

Enable ssh: touch /Volumes/boot/ssh

Preload wifi credentials. Begin editing a new file called: nano /Volumes/boot/wpa_supplicant.conf

and customize for your network: country=US ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="your wifi network name" psk="your wifi password" key_mgmt=WPA-PSK }

Insert the SD card into the Raspberry Pi and power up. After about a minute try to ssh into it: ``` ssh [email protected]

default password is: raspberry

```

Once you're in change the default password: passwd

Permanently enable ssh access (seems to revert to closing it off otherwise): sudo systemctl enable ssh

Install automatic updates: sudo apt-get install unattended-upgrades apt-listchanges

Disclaimer

I built this to execute my own micro dollar cost-averaging crypto buys. Use and modify it at your own risk. This is also not investment advice. I am not an investment advisor. You should do your own research and invest in the way that best suits your needs and risk profile. Good luck and HODL strong.

Tips

If you found this useful, send me some digital love - ETH: 0xb581603e2C4eb9a9Ece4476685f0600CeB472241 - BTC: 13u1YbpSzNsvVpPMyzaDAfzP2jRcZUwh96 - LTC: LMtPGHCQ3as6AEC9ueX4tVQw7GvHegv3fA - DASH: XhCnytvKkV44Mn5WeajGfaifgY8vGtamW4

Issues

Bump certifi from 2018.10.15 to 2022.12.7

opened on 2022-12-08 01:17:52 by dependabot[bot]

Bumps certifi from 2018.10.15 to 2022.12.7.

Commits


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/kdmukai/gdax_bot/network/alerts).

Bump ipython from 7.20.0 to 7.31.1

opened on 2022-01-21 19:50:10 by dependabot[bot]

Bumps ipython from 7.20.0 to 7.31.1.

Commits


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/kdmukai/gdax_bot/network/alerts).

Decimal Error

opened on 2021-10-08 14:48:32 by CatchMeIfUCant

Hi there.

I appreciate the great work you put in here, and I understand that you've moved on from Coinbase now but I figured there's no harm in me posting my error. Maybe you or somebody else can still help.

I've setup the bot perfectly as far as I'm aware, however when running it I receive the following error:

Traceback (most recent call last): File "venv-gdax/gdax_bot/gdax_bot.py", line 236, in <module> market_price = (Decimal(order["executed_value"])/Decimal(order["filled_size"])).quantize(quote_increment) decimal.InvalidOperation: [<class 'decimal.DivisionUndefined'>]

I've tried running a buy for both 100 EUR and 100.00 EUR and both times I get the same error. I figured maybe the decimal needed to be included like so, but unfortunately not.

Any ideas?

cbpro import

opened on 2021-06-29 19:42:20 by CaptainDonut

Hello!

I can't seem to run your bot anymore. Getting the following when I try to run:

Traceback (most recent call last): File "/home/lnip/gdax_bot-master/gdax_bot.py", line 13, in <module> import cbpro ModuleNotFoundError: No module named 'cbpro'

Also the pip install -r ./requirements gives the following:

Collecting ipython==7.20.0 (from -r ./gdax_bot-master/requirements.txt (line 14)) Could not find a version that satisfies the requirement ipython==7.20.0 (from -r ./gdax_bot-master/requirements.txt (line 14)) (from versions: 0.10, 0.10.1, 0.10.2, 0.11, 0.12, 0.12.1, 0.13, 0.13.1, 0.13.2, 1.0.0, 1.1.0, 1.2.0, 1.2.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.3.1, 2.4.0, 2.4.1, 3.0.0, 3.1.0, 3.2.0, 3.2.1, 3.2.2, 3.2.3, 4.0.0b1, 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.1.0rc1, 4.1.0rc2, 4.1.0, 4.1.1, 4.1.2, 4.2.0, 4.2.1, 5.0.0b1, 5.0.0b2, 5.0.0b3, 5.0.0b4, 5.0.0rc1, 5.0.0, 5.1.0, 5.2.0, 5.2.1, 5.2.2, 5.3.0, 5.4.0, 5.4.1, 5.5.0, 5.6.0, 5.7.0, 5.8.0, 5.9.0, 5.10.0, 6.0.0rc1, 6.0.0, 6.1.0, 6.2.0, 6.2.1, 6.3.0, 6.3.1, 6.4.0, 6.5.0, 7.0.0b1, 7.0.0rc1, 7.0.0, 7.0.1, 7.1.0, 7.1.1, 7.2.0, 7.3.0, 7.4.0, 7.5.0, 7.6.0, 7.6.1, 7.7.0, 7.8.0, 7.9.0, 7.10.0, 7.10.1, 7.10.2, 7.11.0, 7.11.1, 7.12.0, 7.13.0, 7.14.0, 7.15.0, 7.16.0, 7.16.1) No matching distribution found for ipython==7.20.0 (from -r ./gdax_bot-master/requirements.txt (line 14))

Thank you for the bot, it is very useful! :)

GDAX Fork Due to Lack of Updates

opened on 2021-06-27 04:06:41 by ciordia9

New installs are having a tough time meeting the new (or rather old) requirements for GDAX and GDAX isn't moving forward with Prime or Auth requirements:

https://github.com/danpaquin/coinbasepro-python/issues/443 https://github.com/danpaquin/coinbasepro-python/issues/448

Fork was made: https://github.com/teleprint-me/coinbasepro-python

But then it breaks your work.

If you have time can you look and weigh in on the migration?

Bump urllib3 from 1.25.10 to 1.26.5

opened on 2021-06-01 22:55:15 by dependabot[bot]

Bumps urllib3 from 1.25.10 to 1.26.5.

Release notes

Sourced from urllib3's releases.

1.26.5

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Fixed deprecation warnings emitted in Python 3.10.
  • Updated vendored six library to 1.16.0.
  • Improved performance of URL parser when splitting the authority component.

If you or your organization rely on urllib3 consider supporting us via GitHub Sponsors

1.26.4

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Changed behavior of the default SSLContext when connecting to HTTPS proxy during HTTPS requests. The default SSLContext now sets check_hostname=True.

If you or your organization rely on urllib3 consider supporting us via GitHub Sponsors

1.26.3

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Fixed bytes and string comparison issue with headers (Pull #2141)

  • Changed ProxySchemeUnknown error message to be more actionable if the user supplies a proxy URL without a scheme (Pull #2107)

If you or your organization rely on urllib3 consider supporting us via GitHub Sponsors

1.26.2

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Fixed an issue where wrap_socket and CERT_REQUIRED wouldn't be imported properly on Python 2.7.8 and earlier (Pull #2052)

1.26.1

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Fixed an issue where two User-Agent headers would be sent if a User-Agent header key is passed as bytes (Pull #2047)

1.26.0

:warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

  • Added support for HTTPS proxies contacting HTTPS servers (Pull #1923, Pull #1806)

  • Deprecated negotiating TLSv1 and TLSv1.1 by default. Users that still wish to use TLS earlier than 1.2 without a deprecation warning should opt-in explicitly by setting ssl_version=ssl.PROTOCOL_TLSv1_1 (Pull #2002) Starting in urllib3 v2.0: Connections that receive a DeprecationWarning will fail

  • Deprecated Retry options Retry.DEFAULT_METHOD_WHITELIST, Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST and Retry(method_whitelist=...) in favor of Retry.DEFAULT_ALLOWED_METHODS, Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT, and Retry(allowed_methods=...) (Pull #2000) Starting in urllib3 v2.0: Deprecated options will be removed

... (truncated)

Changelog

Sourced from urllib3's changelog.

1.26.5 (2021-05-26)

  • Fixed deprecation warnings emitted in Python 3.10.
  • Updated vendored six library to 1.16.0.
  • Improved performance of URL parser when splitting the authority component.

1.26.4 (2021-03-15)

  • Changed behavior of the default SSLContext when connecting to HTTPS proxy during HTTPS requests. The default SSLContext now sets check_hostname=True.

1.26.3 (2021-01-26)

  • Fixed bytes and string comparison issue with headers (Pull #2141)

  • Changed ProxySchemeUnknown error message to be more actionable if the user supplies a proxy URL without a scheme. (Pull #2107)

1.26.2 (2020-11-12)

  • Fixed an issue where wrap_socket and CERT_REQUIRED wouldn't be imported properly on Python 2.7.8 and earlier (Pull #2052)

1.26.1 (2020-11-11)

  • Fixed an issue where two User-Agent headers would be sent if a User-Agent header key is passed as bytes (Pull #2047)

1.26.0 (2020-11-10)

  • NOTE: urllib3 v2.0 will drop support for Python 2. Read more in the v2.0 Roadmap <https://urllib3.readthedocs.io/en/latest/v2-roadmap.html>_.

  • Added support for HTTPS proxies contacting HTTPS servers (Pull #1923, Pull #1806)

  • Deprecated negotiating TLSv1 and TLSv1.1 by default. Users that still wish to use TLS earlier than 1.2 without a deprecation warning

... (truncated)

Commits
  • d161647 Release 1.26.5
  • 2d4a3fe Improve performance of sub-authority splitting in URL
  • 2698537 Update vendored six to 1.16.0
  • 07bed79 Fix deprecation warnings for Python 3.10 ssl module
  • d725a9b Add Python 3.10 to GitHub Actions
  • 339ad34 Use pytest==6.2.4 on Python 3.10+
  • f271c9c Apply latest Black formatting
  • 1884878 [1.26] Properly proxy EOF on the SSLTransport test suite
  • a891304 Release 1.26.4
  • 8d65ea1 Merge pull request from GHSA-5phf-pp7p-vc2r
  • Additional commits viewable in compare view


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/kdmukai/gdax_bot/network/alerts).

crypto cryptocurrency gdax trading bot bitcoin ethereum btc eth litecoin ltc bitcoincash bch dollar-cost-averaging crypto-trader trading-bot trading-strategies