-
-
Notifications
You must be signed in to change notification settings - Fork 778
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
adds proper sell rounding to avoid LOT errors #79
base: main
Are you sure you want to change the base?
Changes from 5 commits
31f3028
6628558
3d1d0d6
9e4d2f3
706d591
4c73770
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,4 @@ __*__ | |
|
||
# IDE settings | ||
.vscode | ||
.idea |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,12 +28,16 @@ | |
|
||
# Needed for colorful console output Install with: python3 -m pip install colorama (Mac/Linux) or pip install colorama (PC) | ||
from colorama import init | ||
|
||
init() | ||
|
||
# needed for the binance API / websockets / Exception handling | ||
from binance.client import Client | ||
from binance.exceptions import BinanceAPIException | ||
|
||
# needed to round to step size | ||
from binance.helpers import round_step_size | ||
|
||
# used for dates | ||
from datetime import date, datetime, timedelta | ||
import time | ||
|
@@ -54,7 +58,6 @@ | |
load_correct_creds | ||
) | ||
|
||
|
||
# for colourful logging to the console | ||
class txcolors: | ||
BUY = '\033[92m' | ||
|
@@ -64,7 +67,6 @@ class txcolors: | |
DIM = '\033[2m\033[35m' | ||
DEFAULT = '\033[39m' | ||
|
||
|
||
# tracks profit/loss each session | ||
global session_profit | ||
session_profit = 0 | ||
|
@@ -103,11 +105,12 @@ def get_price(add_to_historical=True): | |
for coin in prices: | ||
|
||
if CUSTOM_LIST: | ||
if any(item + PAIR_WITH == coin['symbol'] for item in tickers) and all(item not in coin['symbol'] for item in FIATS): | ||
initial_price[coin['symbol']] = { 'price': coin['price'], 'time': datetime.now()} | ||
if any(item + PAIR_WITH == coin['symbol'] for item in tickers) and all( | ||
item not in coin['symbol'] for item in FIATS): | ||
initial_price[coin['symbol']] = {'price': coin['price'], 'time': datetime.now()} | ||
else: | ||
if PAIR_WITH in coin['symbol'] and all(item not in coin['symbol'] for item in FIATS): | ||
initial_price[coin['symbol']] = { 'price': coin['price'], 'time': datetime.now()} | ||
initial_price[coin['symbol']] = {'price': coin['price'], 'time': datetime.now()} | ||
|
||
if add_to_historical: | ||
hsp_head += 1 | ||
|
@@ -134,7 +137,7 @@ def wait_for_price(): | |
coins_unchanged = 0 | ||
|
||
pause_bot() | ||
|
||
if historical_prices[hsp_head]['BNB' + PAIR_WITH]['time'] > datetime.now() - timedelta(minutes=float(TIME_DIFFERENCE / RECHECK_INTERVAL)): | ||
|
||
# sleep for exactly the amount of time required | ||
|
@@ -297,7 +300,6 @@ def buy(): | |
# only buy if the there are no active trades on the coin | ||
if coin not in coins_bought: | ||
print(f"{txcolors.BUY}Preparing to buy {volume[coin]} {coin}{txcolors.DEFAULT}") | ||
|
||
if TEST_MODE: | ||
orders[coin] = [{ | ||
'symbol': coin, | ||
|
@@ -314,10 +316,10 @@ def buy(): | |
# try to create a real order if the test orders did not raise an exception | ||
try: | ||
buy_limit = client.create_order( | ||
symbol = coin, | ||
side = 'BUY', | ||
type = 'MARKET', | ||
quantity = volume[coin] | ||
symbol=coin, | ||
side='BUY', | ||
type='MARKET', | ||
quantity=volume[coin] | ||
) | ||
|
||
# error handling here in case position cannot be placed | ||
|
@@ -360,9 +362,15 @@ def sell_coins(): | |
|
||
for coin in list(coins_bought): | ||
# define stop loss and take profit | ||
TP = float(coins_bought[coin]['bought_at']) + (float(coins_bought[coin]['bought_at']) * coins_bought[coin]['take_profit']) / 100 | ||
SL = float(coins_bought[coin]['bought_at']) + (float(coins_bought[coin]['bought_at']) * coins_bought[coin]['stop_loss']) / 100 | ||
|
||
try: | ||
TP = float(coins_bought[coin]['bought_at']) + ( | ||
float(coins_bought[coin]['bought_at']) * coins_bought[coin]['take_profit']) / 100 | ||
SL = float(coins_bought[coin]['bought_at']) + ( | ||
float(coins_bought[coin]['bought_at']) * coins_bought[coin]['stop_loss']) / 100 | ||
# When an older version of the script is being executed | ||
except KeyError: | ||
TP = float(coins_bought[coin]['bought_at']) + (float(coins_bought[coin]['bought_at'])) / 100 | ||
SL = float(coins_bought[coin]['bought_at']) + (float(coins_bought[coin]['bought_at'])) / 100 | ||
|
||
LastPrice = float(last_price[coin]['price']) | ||
BuyPrice = float(coins_bought[coin]['bought_at']) | ||
|
@@ -383,14 +391,20 @@ def sell_coins(): | |
|
||
# try to create a real order | ||
try: | ||
try: | ||
rounded_amount = round_step_size(coins_bought[coin]['volume'], coins_bought[coin]['step_size']) | ||
except Exception: | ||
tick_size = float(next( | ||
filter(lambda f: f['filterType'] == 'LOT_SIZE', client.get_symbol_info(coin)['filters']) | ||
)['stepSize']) | ||
Comment on lines
+395
to
+397
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line seems to be too long. Is there any way to make it more readable? (I really don't know) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haven't tested this yet, will it leave crypto dust for people using BNB for fees? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, it will leave crypto dust which can be changed into BNB afterward. |
||
rounded_amount = round_step_size(coins_bought[coin]['volume'], tick_size) | ||
|
||
if not TEST_MODE: | ||
sell_coins_limit = client.create_order( | ||
symbol = coin, | ||
side = 'SELL', | ||
type = 'MARKET', | ||
quantity = coins_bought[coin]['volume'] | ||
|
||
quantity = rounded_amount | ||
) | ||
|
||
# error handling here in case position cannot be placed | ||
|
@@ -425,7 +439,9 @@ def update_portfolio(orders, last_price, volume): | |
'''add every coin bought to our portfolio for tracking/selling later''' | ||
if DEBUG: print(orders) | ||
for coin in orders: | ||
|
||
coin_step_size = float(next( | ||
filter(lambda f: f['filterType'] == 'LOT_SIZE', client.get_symbol_info(orders[coin][0]['symbol'])['filters']) | ||
)['stepSize']) | ||
coins_bought[coin] = { | ||
'symbol': orders[coin][0]['symbol'], | ||
'orderid': orders[coin][0]['orderId'], | ||
|
@@ -434,7 +450,8 @@ def update_portfolio(orders, last_price, volume): | |
'volume': volume[coin], | ||
'stop_loss': -STOP_LOSS, | ||
'take_profit': TAKE_PROFIT, | ||
} | ||
'step_size': coin_step_size, | ||
} | ||
|
||
# save the coins in a json file in the same directory | ||
with open(coins_bought_file_path, 'w') as file: | ||
|
@@ -454,7 +471,7 @@ def remove_from_portfolio(coins_sold): | |
|
||
def write_log(logline): | ||
timestamp = datetime.now().strftime("%d/%m %H:%M:%S") | ||
with open(LOG_FILE,'a+') as f: | ||
with open(LOG_FILE, 'a+') as f: | ||
f.write(timestamp + ' ' + logline + '\n') | ||
|
||
if __name__ == '__main__': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
python-binance==0.7.9 | ||
python-binance==1.0.10 | ||
colorama==0.4.4 | ||
PyYAML==5.4.1 | ||
tradingview-ta==3.2.3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't be a good idea to put
coins_bought[coin]['bought_at']
into a variable to avoid repeating it too much?Code might be cleaner