-
Notifications
You must be signed in to change notification settings - Fork 1
Dockerized, added post-only limit orders to get maker fees instead of taker. #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
claytondukes
wants to merge
65
commits into
kurt213:main
Choose a base branch
from
claytondukes:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 41 commits
Commits
Show all changes
65 commits
Select commit
Hold shift + click to select a range
81de478
Dockerized
claytondukes 20d8236
always restart container
5b71555
updated coinbase api
claytondukes 1aa7cbb
.
80bb941
feat: implement limit order support to reduce fees
claytondukes 12be3e3
feat: implement limit order support to reduce fees
claytondukes 6a6e65d
fix: use limit_order_gtc with end_time to prevent stuck orders
claytondukes a70c7aa
fix: use limit_order_gtd with end_time to prevent stuck orders
claytondukes 7e9a3ed
fix: use limit_order_gtd with end_time to prevent stuck orders
claytondukes c08e8f8
fix: round prices to 2 decimal places to fix precision error
claytondukes 8e131e4
refactor: switch from order_timeout_hours to order_timeout_seconds wi…
claytondukes 9007bcf
update: configure schedule template with limit orders using 0.01% dis…
claytondukes cc7f955
docs: update README with correct default limit price percentage
claytondukes 7024aa8
feat: post-only limit orders with fallback; docs and env updates
claytondukes 94ce222
Merge pull request #1 from claytondukes/feat/limit-orders
claytondukes 8c7e3f0
Updating per copilot pr feedback
claytondukes c2cfe26
Merge pull request #2 from claytondukes/feat/limit-orders
claytondukes f8a4c39
fix: address copilot feedback - order message, logging config, cleanup
claytondukes 3ece2d4
Merge branch 'feat/limit-orders'
claytondukes 0cf26ef
fix: preserve Decimal precision for price/size calculations, use keyw…
claytondukes f31bbab
Merge branch 'feat/limit-orders'
claytondukes 5b5b087
refactor: optimize product fetching, extract rounding helper, update …
claytondukes ad239e6
Merge branch 'feat/limit-orders'
claytondukes f1b062d
fix: handle SDK typed responses, ensure logs dir, improve docs
claytondukes d2a5e8e
Merge branch 'feat/limit-orders'
claytondukes da40648
refactor: logging, Decimal precision, and scheduler cleanup
claytondukes e03b4e9
Merge branch 'feat/limit-orders'
claytondukes f190d4c
build(docker): noninteractive tzdata and layer-caching; add .dockerig…
claytondukes 2e58f6f
Merge branch 'feat/limit-orders'
claytondukes 7b69c65
fix(orders): log fallback market order id and improve Decimal quantiz…
claytondukes cf5d2ce
Merge branch 'feat/limit-orders'
claytondukes db0c6c7
fix(auth): remove duplicate dotenv load; update example usage; log fa…
claytondukes 0c2b089
Merge branch 'feat/limit-orders'
claytondukes 499b436
docs: Advanced Trade branding and frequencies; chore: robust dotenv i…
claytondukes 1d90813
Merge branch 'feat/limit-orders'
claytondukes 8939b06
refactor(runtime): TZ-aware startup & Docker logs; fix(auth): market …
claytondukes fe9580e
Merge branch 'feat/limit-orders'
claytondukes 48d4125
refactor(runtime): TZ-aware startup; unify logging; improve order val…
claytondukes ed4bae6
Merge branch 'feat/limit-orders'
claytondukes a8149f1
feat(runtime): env-configurable schedule file; remove scheduler runner
claytondukes a22c1b5
Merge branch 'feat/limit-orders'
claytondukes 173c7a3
fix(orders): poll to terminal after cancel and recompute remaining be…
claytondukes cd8c881
Merge branch 'feat/limit-orders'
claytondukes c8339ad
feat(repricing): add maker repricing before fallback; wire schedule o…
claytondukes f5d2e6b
refactor: use RepriceConfig; add safe_float;
claytondukes c4094e2
fix(repricing): use RepriceConfig at all call sites; harden None fall…
claytondukes 75a34a4
fix(repricing): wait before first reprice; post-only nudge; success-o…
claytondukes 4f227cf
refactor(repricing): log refresh only on success; add error extractor…
claytondukes baa25b1
pr fix for decimal
claytondukes e7c22e0
pr fix for decimal
claytondukes 5ec0c44
style(repricing): use REPRICE_POLL_SLEEP for polling; clamp repricer …
claytondukes 6bfef7e
pr fix for decimal
claytondukes c461235
Merge pull request #3 from claytondukes/feat/reprice-before-fallback
claytondukes 1a59e0a
feat(orders,scheduler), add 'once', GTC limit price
claytondukes 536fed3
fix(scheduler,orders): improve 'once' behavior and add absolute price…
claytondukes c7d4d10
fix: improve exception handling and logging
claytondukes 76f3cff
refactor: simplify code and improve documentation
claytondukes 98c0555
fix: improve time_in_force handling and documentation
claytondukes 8b0c085
fix: prevent duplicate execution and improve error visibility
claytondukes 4e155e5
fix: correct time comparison and log message placement
claytondukes aaabb3e
fix: validate post_only absolute price and improve logging
claytondukes dbaf57f
Merge pull request #4 from claytondukes/feat/add-gtc-orders
claytondukes e499b36
fix: clarify 'once' schedule log message
claytondukes e9ce608
Merge pull request #5 from claytondukes/feat/add-gtc-orders
claytondukes 8ff105d
updated gitignore
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| venv/ | ||
| __pycache__/ | ||
| *.pyc | ||
| .env | ||
| .git | ||
| .gitignore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Coinbase Advanced Trade credentials | ||
| COINBASE_API_KEY="organizations/<org-id>/apiKeys/<key-id>" | ||
| # Paste the EC private key exactly as provided by Coinbase Advanced Trade. | ||
| # Both multiline PEM and \n-escaped formats are supported. | ||
| COINBASE_API_SECRET="-----BEGIN EC PRIVATE KEY-----\n...your-private-key...\n-----END EC PRIVATE KEY-----\n" | ||
|
|
||
| # Timezone used by the scheduler (container/local process) | ||
| # Example: America/New_York (Eastern Time) | ||
| TZ=America/New_York | ||
|
|
||
| # Verbose SDK logging (optional). Accepted truthy values: | ||
| # 1, true, yes, on, debug (case-insensitive) | ||
| COINBASE_VERBOSE=false | ||
|
|
||
| # Schedule file to load (default: schedule.json) | ||
| SCHEDULE_FILE=schedule.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| FROM python:3.11-slim | ||
|
|
||
| ENV DEBIAN_FRONTEND=noninteractive | ||
|
|
||
| # Install tzdata non-interactively and clean apt lists | ||
| RUN apt-get update -yqq \ | ||
| && apt-get install -yqq --no-install-recommends tzdata \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| WORKDIR /usr/src/app | ||
|
|
||
| # Leverage layer caching for dependencies | ||
| COPY requirements.txt . | ||
| RUN pip install --no-cache-dir -r requirements.txt | ||
|
|
||
| # Copy the rest of the source | ||
| COPY . . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,58 +1,215 @@ | ||
| # crypto-dca-bot | ||
| # Crypto DCA Bot | ||
|
|
||
| Tool to automate scheduled cryptocurrency purchases on Coinbase Advanced Trader (Previously branded as Coinbase Pro). | ||
| A tool to automate scheduled cryptocurrency purchases on Coinbase Advanced | ||
| Trade (previously branded as Coinbase Pro). | ||
|
|
||
| Frequently used for DCA (Dollar-Cost Averaging) investment strategies. | ||
| Frequently used for DCA (Dollar-Cost Averaging) investment strategies to reduce | ||
| market volatility impact by making regular, fixed-amount purchases regardless of | ||
| price. | ||
|
|
||
| I used to buy crypto on a weekly basis, but I found the mainstream providers charged a lot of fees for this service. I wanted to automate this process and reduce the fees I was paying by executing these trades through their trade platforms instead which have much lower fees. | ||
| ## Features | ||
|
|
||
| ## Notes | ||
| - Schedule cryptocurrency purchases on a seconds, hourly, daily, weekly, or monthly basis | ||
| - Configure purchases for multiple currency pairs | ||
| - Specify the exact time and day for transactions | ||
| - Supports post-only limit (maker) and market (taker) orders; optional | ||
| maker-first with fallback | ||
| - Lower fees compared to standard Coinbase purchases | ||
| - Flexible deployment options (local Python or Docker) | ||
|
|
||
| - Originally started working on Binance and connecting to their APIs, but due to some personal consumer issues I've had with them, will be switching focus to Coinbase Advanced Trader. | ||
| ## Background | ||
|
|
||
| ## Guide | ||
| Using the Coinbase Advanced Trade API automates time-based cryptocurrency | ||
| purchases and helps minimize fees. Executing trades directly through Advanced | ||
| Trade reduces transaction costs compared to recurring buys on the standard | ||
| Coinbase platform. | ||
|
|
||
| This guide assumes you have some knowledge of setting up a Python environment and running Python scripts. | ||
| ## Installation | ||
|
|
||
| 1. Create a Coinbase account and generate an API key & secret with the following permissions: | ||
| ``` | ||
| wallet:accounts:read | ||
| wallet:buys:create | ||
| wallet:orders:read | ||
| wallet:transactions:read | ||
| wallet:user:read | ||
| ``` | ||
| ### Prerequisites | ||
|
|
||
| 2. Create a `.env` file in the root directory of the project and add the following variables with these API details: | ||
| - Python 3.11+ | ||
| - Coinbase account with API access | ||
| - The required Python packages: | ||
|
|
||
| ```text | ||
| python-dotenv | ||
| requests | ||
| schedule | ||
| coinbase-advanced-py | ||
| ``` | ||
| COINBASE_API_KEY= | ||
| COINBASE_API_SECRET= | ||
|
|
||
| ### Setup | ||
|
|
||
| 1. Clone the repository or download the source code | ||
| 2. Install dependencies: | ||
|
|
||
| ```bash | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 3. Rename or copy the `schedule_template.json` to `schedule.json` and add your schedule details. | ||
| ## Configuration Guide | ||
|
|
||
| The time set is in 24 hour format and is based on the local time of the machine running the script. | ||
| Basic familiarity with Python environments and script execution is assumed. | ||
|
|
||
| **NOTE:** Currently, you can only schedule market order BUY side transactions e.g. `BTC/GBP` means you are buying `BTC` with the `quote_currency_amount` of `GBP`. | ||
| 1. Create a Coinbase account and generate an API key & secret with the following | ||
| permissions: | ||
|
|
||
| ``` | ||
| ```text | ||
| View permissions | ||
| Trade permissions | ||
| ``` | ||
|
|
||
| Select both View and Trade permissions when creating the API key in Coinbase | ||
| Advanced. | ||
|
|
||
| 2. Create a `.env` file in the project root and add the following variables with | ||
| API details from Coinbase Advanced Trade: | ||
|
|
||
| ```text | ||
| COINBASE_API_KEY="organizations/your-org-id/apiKeys/your-key-id" | ||
| COINBASE_API_SECRET="-----BEGIN EC PRIVATE KEY-----\n...your private key...\n-----END EC PRIVATE KEY-----\n" | ||
| ``` | ||
|
|
||
| **Note:** The Coinbase Advanced Trade API uses a different format for API | ||
| keys than the previous version. Use the full | ||
| `organizations/<org-id>/apiKeys/<key-id>` format as shown above. | ||
|
|
||
| 3. Create `schedule.json` from `schedule-sample.json` and define the schedule. | ||
|
|
||
| Times are in 24‑hour format and interpreted in the process timezone. | ||
|
|
||
| Each transaction can be configured as a limit (maker) or market (taker) order. | ||
| Limit orders help reduce fees and eliminate price slippage. By default, the bot | ||
| uses limit orders with a price set slightly below market price to prefer maker | ||
| execution. For example, `BTC/USDC` indicates buying BTC with the specified USDC | ||
| amount. | ||
|
|
||
| ```json | ||
| [ | ||
| { | ||
| "frequency": "daily", | ||
| "day_of_week": null, | ||
| "time": "10:30", | ||
| "currency_pair": "ETH/GBP", | ||
| "quote_currency_amount": 1 | ||
| "currency_pair": "ETH/USDC", | ||
| "quote_currency_amount": 1, | ||
| "order_type": "limit", | ||
| "limit_price_pct": 0.01, | ||
| "order_timeout_seconds": 600 | ||
| }, | ||
| { | ||
| "frequency": "weekly", | ||
| "day_of_week": "wednesday", | ||
| "time": "15:45", | ||
| "currency_pair": "BTC/GBP", | ||
| "quote_currency_amount": 1 | ||
| "currency_pair": "BTC/USDC", | ||
| "quote_currency_amount": 1, | ||
| "order_type": "market" | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| 3. Run `main.py` script. | ||
| ## Running the Bot | ||
|
|
||
| ### Method 1: Python Script | ||
|
|
||
| Start the bot: | ||
|
|
||
| ```bash | ||
| python main.py | ||
| ``` | ||
|
|
||
| The bot starts and executes trades according to the defined schedule. | ||
|
|
||
| ### Method 2: Docker Deployment | ||
|
|
||
| The project includes Docker configuration for easy deployment and automated | ||
| restarts. | ||
|
|
||
| 1. Docker and Docker Compose must be installed. | ||
| 2. Start the container: | ||
|
|
||
| ```bash | ||
| docker compose build | ||
| docker compose up -d | ||
| ``` | ||
|
|
||
| The container runs the bot in the background with automatic restarts. View | ||
| logs with: | ||
|
|
||
| ```bash | ||
| docker compose logs -f --tail=100 | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - The bot runs indefinitely, executing trades based on the schedule | ||
| configuration. | ||
| - All transactions are logged for reference and troubleshooting. | ||
| - For limit orders, the price is set at a percentage (`limit_price_pct`) of the | ||
| current market price (default: 0.01%) to ensure orders execute as maker orders | ||
| with lower fees. | ||
| - Limit orders can be configured with an auto-cancellation time using | ||
| `order_timeout_seconds`. This setting determines how long (in seconds) a limit | ||
| order remains active before being auto-cancelled if not filled. Default is 600 | ||
| seconds (10 minutes). This prevents stuck orders. | ||
| - If `order_type` is not specified, limit orders are used by default. To use | ||
| market orders, set `order_type` to "market". | ||
|
|
||
| ## Environment (.env) | ||
|
|
||
| A `.env` file in the project root is loaded by Docker Compose via `env_file: | ||
| .env`. | ||
|
|
||
| ```env | ||
| # Coinbase Advanced Trade credentials | ||
| COINBASE_API_KEY="organizations/<org-id>/apiKeys/<key-id>" | ||
| # Paste the EC private key exactly as provided by Coinbase Advanced Trade. | ||
| # Both multiline PEM and \n-escaped formats are supported. | ||
| COINBASE_API_SECRET="-----BEGIN EC PRIVATE KEY-----\n...your-key...\n-----END EC PRIVATE KEY-----\n" | ||
|
|
||
| # Timezone used by the scheduler (container/local process) | ||
| # Example: America/New_York (Eastern Time) | ||
| TZ=America/New_York | ||
|
|
||
| # Verbose SDK logging (optional). Accepted truthy values: | ||
| # 1, true, yes, on, debug (case-insensitive) | ||
| COINBASE_VERBOSE=false | ||
| ``` | ||
|
|
||
| ## Maker-first with quick fallback | ||
|
|
||
| - **Post-only limit orders** keep fees low by resting on the book. | ||
| - Set a small discount using `limit_price_pct` (percent-of-100), e.g. `0.01` | ||
| (0.01%), `0.3` (0.3%), `0.4` (0.4%). | ||
| - A short `order_timeout_seconds` (for example, `300–600`) guarantees completion | ||
| via fallback-to-market after expiry. | ||
|
|
||
| Example schedule entry (maker-first): | ||
|
|
||
| ```json | ||
| { | ||
| "frequency": "daily", | ||
| "time": "15:45", | ||
| "currency_pair": "BTC/USDC", | ||
| "quote_currency_amount": 20, | ||
| "order_type": "limit", | ||
| "limit_price_pct": 0.01, | ||
| "post_only": true, | ||
| "order_timeout_seconds": 600 | ||
| } | ||
| ``` | ||
|
|
||
| ## Timezone behavior | ||
|
|
||
| - The scheduler interprets `time` in the process timezone. | ||
| - In Docker, set `TZ` in `.env` (for example, `TZ=America/New_York`) so jobs run | ||
| in that timezone. | ||
| - On bare Python, the host system timezone determines interpretation; configure | ||
| as needed. | ||
|
|
||
| ## Schedule files | ||
|
|
||
| - The bot loads `schedule.json` by default in `main.py`. | ||
| - Keep your full plan in `schedule-full.json` if desired, then copy to | ||
| `schedule.json` for deployment, or change the loader in `main.py` to point to | ||
| your preferred file. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.