Skip to content

Commit

Permalink
Merge pull request #1 from ahrenstein/addingVars
Browse files Browse the repository at this point in the history
Additional variables
  • Loading branch information
ahrenstein authored Apr 13, 2021
2 parents 546f4fb + 0d67372 commit 028e54b
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 85 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ Crypto Dip Buying Bot: Changelog
================================
A list of all the changes made to this repo, and the bot it contains

Version 0.2.0
-------------

1. **Fixed a critical issue where the last buy date is not updated when buys are made!**
2. Bot functions condensed in to 1 file
3. Averaging time period and purchase cool down period are now both config variables
4. Fixed some incorrect function descriptions

Version 0.1.0
-------------

Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ You will need the following:

The following sections are optional.

1. AWS credentials:
1. Time variables in the bot config
1. Period of days to average (Default: 7)
2. Cool down period before buying again (Default: 7)
2. AWS credentials:
1. AWS API keys
2. SNS topic ARN (us-east-1 only for now)

Expand All @@ -45,7 +48,9 @@ The file should look like this:
"bot": {
"currency": "ETH",
"buy_amount": 75.00,
"dip_percentage": 10
"dip_percentage": 10,
"average_period_days": 3,
"cool_down_period_days": 5
},
"coinbase": {
"api_key": "YOUR_API_KEY",
Expand Down
36 changes: 33 additions & 3 deletions SourceCode/bot_alerts.py → SourceCode/bot_internals.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Alerting Functions"""
"""Internal functions the bot uses"""
#
# Python Script:: bot_alerts.py
# Python Script:: bot_internals.py
#
# Linter:: pylint
#
Expand Down Expand Up @@ -38,7 +38,7 @@ def get_aws_creds_from_file(config_file: str) -> [str, str, str]:

def post_to_sns(aws_access_key: str, aws_secret_key: str, sns_topic_arn: str,
message_subject: str, message_body: str):
"""Read all current price records in the database
"""Post a message and subject to AWS SNS
Args:
aws_access_key: The AWS access key your bot will use
Expand All @@ -50,3 +50,33 @@ def post_to_sns(aws_access_key: str, aws_secret_key: str, sns_topic_arn: str,
sns = boto3.client('sns', region_name="us-east-1",
aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
sns.publish(TopicArn=sns_topic_arn, Subject=message_subject, Message=message_body)


def get_average(list_of_numbers: list) -> float:
"""Get an average of the numbers in a list
Args:
list_of_numbers: A list of floats
Returns:
list_average: A float containing the list average
"""
sum_of_numbers = 0
for number in list_of_numbers:
sum_of_numbers = sum_of_numbers + number
list_average = sum_of_numbers / len(list_of_numbers)
return round(list_average, 2)


def dip_percent_value(price: float, percent: float) -> float:
"""Return the value of the current price if it dips a certain percent
Args:
price: The price to check a dip percentage against
percent: the dip percentage we care about
Returns:
dip_price: A float containing the price if we hit our dip target
"""
dip_price = price * (1 - percent / 100)
return round(dip_price, 2)
44 changes: 0 additions & 44 deletions SourceCode/bot_math.py

This file was deleted.

55 changes: 34 additions & 21 deletions SourceCode/cryptodip_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@
import datetime
import json
import time
import bot_alerts
import bot_math
import bot_internals
import coinbase_pro
import mongo

# Constants that might be useful to adjust for debugging purposes
CYCLE_INTERVAL_MINUTES = 60


def read_bot_config(config_file: str) -> [str, float, int, bool]:
def read_bot_config(config_file: str) -> [str, float, int, int, int, bool]:
"""Open a JSON file and get the bot configuration
Args:
config_file: Path to the JSON file containing credentials and config options
Expand All @@ -36,15 +35,26 @@ def read_bot_config(config_file: str) -> [str, float, int, bool]:
crypto_currency: The cryptocurrency that will be monitored
buy_amount: The price in $USD that will be purchased when a dip is detected
dip_percentage: The percentage of the average price drop that means a dip occurred
average_period_days: The time period in days to average across
cool_down_period_days: The time period in days that you will wait before transacting
aws_loaded: A bool to determine if AWS configuration options exist
"""
with open(config_file) as creds_file:
data = json.load(creds_file)
crypto_currency = data['bot']['currency']
buy_amount = data['bot']['buy_amount']
dip_percentage = data['bot']['dip_percentage']
if 'average_period_days' in data['bot']:
average_period_days = data['bot']['average_period_days']
else:
average_period_days = 7
if 'cool_down_period_days' in data['bot']:
cool_down_period_days = data['bot']['cool_down_period_days']
else:
cool_down_period_days = 7
aws_loaded = bool('aws' in data)
return crypto_currency, buy_amount, dip_percentage, aws_loaded
return crypto_currency, buy_amount, dip_percentage,\
average_period_days, cool_down_period_days, aws_loaded


def main(config_file: str, debug_mode: bool):
Expand All @@ -57,22 +67,22 @@ def main(config_file: str, debug_mode: bool):
"""
# Load the configuration file
config_params = read_bot_config(config_file)
if config_params[3]:
aws_config = bot_alerts.get_aws_creds_from_file(config_file)
if config_params[5]:
aws_config = bot_internals.get_aws_creds_from_file(config_file)
message = "%s-Bot has been started" % config_params[0]
bot_alerts.post_to_sns(aws_config[0], aws_config[1], aws_config[2], message, message)
bot_internals.post_to_sns(aws_config[0], aws_config[1], aws_config[2], message, message)
# Set API URLs
coinbase_pro_api_url = ""
mongo_db_connection = ""
if debug_mode:
coinbase_pro_api_url = "https://api-public.sandbox.pro.coinbase.com/"
mongo_db_connection = "mongodb://bots:buythedip@bots-db:27017/"
mongo_db_connection = "mongodb://localhost:27017/"
else:
coinbase_pro_api_url = "https://api.pro.coinbase.com/"
mongo_db_connection = "mongodb://bots:buythedip@bots-db:27017/"
print("LOG: Starting bot...")
print("LOG: Monitoring %s to buy $%s worth when a %s%% dip occurs."
% (config_params[0], config_params[1], config_params[2]))
print("LOG: Dips are checked against a %s day price"
" average with a %s day cool down period" % (config_params[3], config_params[4]))
# Execute the bot every 10 seconds
for cycle in count():
now = datetime.datetime.now().strftime("%m/%d/%Y-%H:%M:%S")
Expand All @@ -82,9 +92,9 @@ def main(config_file: str, debug_mode: bool):
message = "LOG: Not enough account balance" \
" to buy $%s worth of %s" % (config_params[1], config_params[0])
subject = "%s-Bot Funding Issue" % config_params[0]
if config_params[3]:
bot_alerts.post_to_sns(aws_config[0], aws_config[1], aws_config[2],
subject, message)
if config_params[5]:
bot_internals.post_to_sns(aws_config[0], aws_config[1], aws_config[2],
subject, message)
print("LOG: %s" % message)
# Sleep for the specified cycle interval then end the cycle
time.sleep(CYCLE_INTERVAL_MINUTES * 60)
Expand All @@ -94,11 +104,13 @@ def main(config_file: str, debug_mode: bool):
# Add the current price to the price database
mongo.add_price(mongo_db_connection, config_params[0], coin_current_price)
# Check if the a week has passed since the last dip buy
clear_to_proceed = mongo.check_last_buy_date(mongo_db_connection, config_params[0])
clear_to_proceed = mongo.check_last_buy_date(mongo_db_connection,
config_params[0], config_params[4])
if clear_to_proceed is True:
print("LOG: Last buy date over a week ago. Checking if a dip is occurring.")
average_price = mongo.average_pricing(mongo_db_connection, config_params[0])
dip_price = bot_math.dip_percent_value(average_price, config_params[2])
print("LOG: Last buy date outside cool down period. Checking if a dip is occurring.")
average_price = mongo.average_pricing(mongo_db_connection,
config_params[0], config_params[3])
dip_price = bot_internals.dip_percent_value(average_price, config_params[2])
print("LOG: A %s%% dip at the average price of %s would be %s"
%(config_params[2], average_price, dip_price))
if coin_current_price <= dip_price:
Expand All @@ -109,15 +121,16 @@ def main(config_file: str, debug_mode: bool):
message = "Buy success status is %s for %s worth of %s"\
% (did_buy, config_params[1], config_params[0])
subject = "%s-Bot Buy Status Alert" % config_params[0]
mongo.set_last_buy_date(mongo_db_connection, config_params[0])
print("LOG: %s" % message)
if config_params[3]:
bot_alerts.post_to_sns(aws_config[0], aws_config[1], aws_config[2],
subject, message)
if config_params[5]:
bot_internals.post_to_sns(aws_config[0], aws_config[1], aws_config[2],
subject, message)
else:
print("LOG: The current price of %s is > %s. We are not in a dip!"
% (coin_current_price, dip_price))
else:
print("LOG: Last buy date under a week ago. No buys will be attempted.")
print("LOG: Last buy date inside cool down period. No buys will be attempted.")

# Run a price history cleanup daily otherwise sleep the interval
if (cycle * CYCLE_INTERVAL_MINUTES) % 1440 == 0:
Expand Down
19 changes: 10 additions & 9 deletions SourceCode/mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@

import datetime
import pymongo
import bot_math
import bot_internals

# Constants that might be useful to adjust for debugging purposes
AVERAGE_PERIOD_DAYS = 7
PURGE_OLDER_THAN_DAYS = 30


Expand Down Expand Up @@ -58,12 +57,13 @@ def read_all_prices(db_server: str, currency: str):
print(record)


def average_pricing(db_server: str, currency: str) -> float:
def average_pricing(db_server: str, currency: str, average_period: int) -> float:
"""Check the last week of prices and return the average
Args:
db_server: The MongoDB server to connect to
currency: The cryptocurrency the bot is monitoring
average_period: The time period in days to average across
Returns:
average_price: The average price of the last week
Expand All @@ -76,14 +76,14 @@ def average_pricing(db_server: str, currency: str) -> float:
records = prices_collection.find({})
for record in records:
record_age = datetime.datetime.utcnow() - record['time']
if record_age.days <= AVERAGE_PERIOD_DAYS:
if record_age.days <= average_period:
price_history.append(record['price'])
average_price = bot_math.get_average(price_history)
average_price = bot_internals.get_average(price_history)
return average_price


def cleanup_old_records(db_server: str, currency: str):
"""Remove all price history older than 30 days
"""Remove all price history older than X days
Args:
db_server: The MongoDB server to connect to
Expand Down Expand Up @@ -119,13 +119,14 @@ def set_last_buy_date(db_server: str, currency: str):
print("Error updating buy date record: %s" % err)


def check_last_buy_date(db_server: str, currency: str) -> bool:
def check_last_buy_date(db_server: str, currency: str, cool_down_period: int) -> bool:
"""Get the date of the last time the currency was bought
and returns true if it was at least a week ago
and returns true if it >= cool down period
Args:
db_server: The MongoDB server to connect to
currency: The cryptocurrency the bot is monitoring
cool_down_period: The time period in days that you will wait before transacting
Returns:
clear_to_buy: A bool that is true if we are clear to buy
Expand All @@ -147,4 +148,4 @@ def check_last_buy_date(db_server: str, currency: str) -> bool:
print("Error getting buy date record: %s" % err)
return False
time_difference = datetime.datetime.utcnow() - last_buy_date
return time_difference.days >= 7
return time_difference.days >= cool_down_period
6 changes: 0 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ Crypto Dip Buying Bot: To Do List
=================================
The versions below are future versions that will be released once those features have been completed.

Version 0.2.0
-------------

1. Make cool down period and check period variables
1. Assume defaults if not specified

Version 0.3.0
-------------

Expand Down

0 comments on commit 028e54b

Please sign in to comment.