Created
January 23, 2020 12:33
-
-
Save Dereek69/c585de7903dc13bbec2691124872096b to your computer and use it in GitHub Desktop.
Python Script for Risk Management and Order Placement through Bitmex API
This file contains 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
#If you enjoy using this script, I'd appreciate if you could use my | |
#Bitmex Referral here https://www.bitmex.com/register/x51NKV | |
#You save on fees and I get a little incentive to expand this tool further | |
#Thank you | |
#!/usr/bin/env python | |
# coding: utf-8 | |
# In[ ]: | |
from sympy import symbols, Eq, solve | |
import numpy as np | |
from bitmex import bitmex | |
from functools import reduce # forward compatibility for Python 3 | |
import operator | |
import json | |
from decimal import Decimal | |
def getFromDict(dataDict, mapList): | |
return reduce(operator.getitem, mapList, dataDict) | |
bitmex_api_key = 'XXX' #Enter your own API-key here | |
bitmex_api_secret = 'YYY' #Enter your own API-secret here | |
bitmex_client = bitmex(test=False, api_key=bitmex_api_key, api_secret=bitmex_api_secret) | |
# In[ ]: | |
while True: | |
try: | |
current_contracts = bitmex_client.Instrument.Instrument_getActive().result()[0] | |
current_contracts = [sub['symbol'] for sub in current_contracts] | |
contractsDict = {k: v for k, v in enumerate(current_contracts)} | |
contract = input('Choose contract index to trade based on the following list' + '\n' + str(contractsDict) + '\n') | |
contract = contractsDict[int(contract)] | |
print('Contract selected: ' + str(contract)) | |
except (IndexError, ValueError): | |
print('Contract selection must be a number. Try again') | |
continue | |
else: | |
break | |
while True: | |
try: | |
order_types = {0:'Market', 1:'Limit'} | |
order_type = int(input('Choose order_type index for entry' + '\n' + str(order_types) + '\n')) | |
order_type = order_types[order_type] | |
print('Entry Order Type: ' + str(order_type)) | |
except (IndexError, ValueError): | |
print('Entry Order Type selection must be a number 0-1. Try Again') | |
continue | |
else: | |
break | |
while True: | |
try: | |
stop = float(input('Stop Market Price: ')) | |
except ValueError: | |
print('Stop must be a number. Try Again') | |
continue | |
else: | |
break | |
while True: | |
try: | |
target = float(input('Target Close Price: ')) | |
except ValueError: | |
print('Target must be a number. Try Again') | |
continue | |
else: | |
break | |
while True: | |
try: | |
active_contracts = list(range(0, len(contractsDict))) | |
for x in active_contracts: | |
if contract == contractsDict[x]: | |
market_pricing = bitmex_client.Instrument.Instrument_getActive().result()[0] | |
market_pricing = next(item for item in market_pricing if item["symbol"] == str(contractsDict[x])) | |
tick_size = str(market_pricing["tickSize"]) | |
round_point = len(tick_size) | |
tick_size = float(tick_size) | |
bidPrice = float(market_pricing['bidPrice']) | |
askPrice = float(market_pricing['askPrice']) | |
if order_type == 'Limit': | |
entry = float(input('Limit Entry Price: ')) | |
else: | |
if stop > target: | |
entry = bidPrice | |
else: | |
entry = askPrice | |
except ValueError: | |
print('Entry must be a number. Try Again') | |
continue | |
else: | |
break | |
while True: | |
try: | |
risk = int(input('BTC Risk Percentage. Or 0 for 1x Short: '))/100 | |
if risk == 0: | |
risk = (stop - entry) / entry | |
else: | |
None | |
except ValueError: | |
print('Risk must be expressed as whole number. I.e. 3% is 3. Or choose 0 for 1x Short') | |
continue | |
else: | |
break | |
balance = bitmex_client.User.User_getWalletHistory().result()[0][0]['walletBalance']/100000000 | |
# In[ ]: | |
#Fee Data. Do not change these | |
if contract.find('XBT')==0 or contract.find('ETHUSD')==0: | |
maker_rebate = 0.00025 | |
taker_fee = 0.00075 | |
else: | |
maker_rebate = 0.0005 | |
taker_fee = 0.0025 | |
# In[ ]: | |
eth_multiplier = bitmex_client.Instrument.Instrument_getActive().result()[0] | |
eth_multiplier = next(item for item in eth_multiplier if item["symbol"] == 'ETHUSD') | |
eth_multiplier = float(eth_multiplier['quoteToSettleMultiplier'])/10000000000 | |
# In[ ]: | |
def position_size(entry, stop, balance, risk): | |
x = symbols('x') | |
if contract.find('XBT')==0 and target < entry: #Calculate short position_size | |
if order_type == 'Limit': | |
eq1 = Eq((((x/stop)+((x/stop)*taker_fee)) - ((x/entry)+((x/entry)*maker_rebate))+(balance*risk))) | |
else: | |
eq1 = Eq((((x/stop)+((x/stop)*taker_fee)) - ((x/entry)-((x/entry)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
return size | |
elif contract.find('XBT')==0 and entry < target: #Calculate long position_size | |
if order_type == 'Limit': | |
eq1 = Eq((((x/entry)-(x/entry)*maker_rebate) - ((x/stop)-((x/stop)*taker_fee))+(balance*risk))) | |
else: | |
eq1 = Eq((((x/entry)+(x/entry)*taker_fee) - ((x/stop)-((x/stop)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
return size | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1and target < entry: #Calculate short alt position_size | |
if order_type == 'Limit': | |
eq1 = Eq((((x*stop)+((x*stop)*taker_fee)) - ((x*entry)+((x*entry)*maker_rebate))+(balance*risk))) | |
else: | |
eq1 = Eq((((x*stop)+((x*stop)*taker_fee)) - ((x*entry)-((x*entry)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
size = float(size[0])*-1 | |
return size | |
elif contract.find('XBT')==1 and entry < target: #Calculate long alt position_size | |
if order_type == 'Limit': | |
eq1 = Eq((((x*entry)-(x*entry)*maker_rebate) - ((x*stop)-((x*stop)*taker_fee))+(balance*risk))) | |
else: | |
eq1 = Eq((((x*entry)+(x*entry)*taker_fee) - ((x*stop)-((x*stop)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
size = float(size[0])*-1 | |
return size | |
elif contract.find('ETHUSD')==0 and target < entry: #Calculate short ETHUSD position_size | |
if order_type == 'Limit': | |
eq1 = Eq(((stop*eth_multiplier*x)+((stop*eth_multiplier*x*taker_fee)) - ((entry*eth_multiplier*x)+((entry*eth_multiplier*x)*maker_rebate))+(balance*risk))) | |
else: | |
eq1 = Eq(((stop*eth_multiplier*x)+((stop*eth_multiplier*x*taker_fee)) - ((entry*eth_multiplier*x)-((entry*eth_multiplier*x)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
size = float(size[0])*-1 | |
return size | |
elif contract.find('ETHUSD')==0 and entry < target: #Calculate long ETHUSD position_size | |
if order_type == 'Limit': | |
eq1 = Eq(((entry*eth_multiplier*x)-((entry*eth_multiplier*x*maker_rebate)) - ((stop*eth_multiplier*x)-((stop*eth_multiplier*x)*taker_fee))+(balance*risk))) | |
else: | |
eq1 = Eq(((entry*eth_multiplier*x)+((entry*eth_multiplier*x*taker_fee)) - ((stop*eth_multiplier*x)-((stop*eth_multiplier*x)*taker_fee))+(balance*risk))) | |
size = solve(eq1) | |
size = [ '%.0f' % elem for elem in size ] | |
size = float(size[0])*-1 | |
return size | |
# In[ ]: | |
def risk_amount(entry, stop, size): | |
if contract.find('XBT')==0 and target < entry: #Calculate short risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((size/stop+((size/stop)*taker_fee)) - ((size/entry)+((size/entry)*maker_rebate))) | |
else: | |
risk_amount = ((size/stop+((size/stop)*taker_fee)) - ((size/entry)-((size/entry)*taker_fee))) | |
risk_amount = round(risk_amount, 8)*-1 | |
return risk_amount | |
elif contract.find('XBT')==0 and entry < target: #Calculate long risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((size/entry-((size/entry)*maker_rebate)) - ((size/stop)-((size/stop)*taker_fee))) | |
else: | |
risk_amount = ((size/entry+((size/entry)*taker_fee)) - ((size/stop)-((size/stop)*taker_fee))) | |
risk_amount = round(risk_amount, 8)*-1 | |
return risk_amount | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and target < entry: #Calculate short alt risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((size*stop+((size*stop)*taker_fee)) - ((size*entry)+((size*entry)*maker_rebate))) | |
else: | |
risk_amount = ((size*stop+((size*stop)*taker_fee)) - ((size*entry)-((size*entry)*taker_fee))) | |
risk_amount = round(risk_amount, 8) | |
return risk_amount | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and entry < target: #Calculate long alt risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((size*entry-((size*entry)*maker_rebate)) - ((size*stop)-((size*stop)*taker_fee))) | |
else: | |
risk_amount = ((size*entry+((size*entry)*taker_fee)) - ((size*stop)-((size*stop)*taker_fee))) | |
risk_amount = round(risk_amount, 8) | |
return risk_amount | |
elif contract.find('ETHUSD')==0 and target < entry: #Calculate short ETHUSD risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((stop*eth_multiplier*size)+((stop*eth_multiplier*size*taker_fee)) - ((entry*eth_multiplier*size)+((entry*eth_multiplier*size)*maker_rebate))) | |
else: | |
risk_amount = ((stop*eth_multiplier*size)+((stop*eth_multiplier*size*taker_fee)) - ((entry*eth_multiplier*size)-((entry*eth_multiplier*size)*taker_fee))) | |
risk_amount = round(risk_amount, 8) | |
return risk_amount | |
elif contract.find('ETHUSD')==0 and entry < target: #Calculate long ETHUSD risk_amount | |
if order_type == 'Limit': | |
risk_amount = ((entry*eth_multiplier*size)-((entry*eth_multiplier*size*maker_rebate)) - ((stop*eth_multiplier*size)-((stop*eth_multiplier*size)*taker_fee))) | |
else: | |
risk_amount = ((entry*eth_multiplier*size)+((entry*eth_multiplier*size*taker_fee)) - ((stop*eth_multiplier*size)-((stop*eth_multiplier*size)*taker_fee))) | |
risk_amount = round(risk_amount, 8) | |
return risk_amount | |
# In[ ]: | |
def reward_amount(entry, target, size): | |
if contract.find('XBT')==0 and target < entry: #Calculate short reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((size/target-((size/target)*maker_rebate)) - ((size/entry)+((size/entry)*maker_rebate))) | |
else: | |
reward_amount = ((size/target-((size/target)*maker_rebate)) - ((size/entry)-((size/entry)*taker_fee))) | |
reward_amount = round(reward_amount, 8) | |
return reward_amount | |
elif contract.find('XBT')==0 and entry < target: #Calculate long reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((size/entry-((size/entry)*maker_rebate)) - ((size/target)+((size/target)*maker_rebate))) | |
else: | |
reward_amount = ((size/entry+((size/entry)*taker_fee)) - ((size/target)+((size/target)*maker_rebate))) | |
reward_amount = round(reward_amount, 8) | |
return reward_amount | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and target < entry: #Calculate short alt reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((size*target-((size*target)*maker_rebate)) - ((size*entry)+((size*entry)*maker_rebate))) | |
else: | |
reward_amount = ((size*target-((size*target)*maker_rebate)) - ((size*entry)-((size*entry)*taker_fee))) | |
reward_amount = round(reward_amount, 8)*-1 | |
return reward_amount | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and entry < target: #Calculate long alt reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((size*entry-((size*entry)*maker_rebate)) - ((size*target)+((size*target)*maker_rebate))) | |
else: | |
reward_amount = ((size*entry+((size*entry)*taker_fee)) - ((size*target)+((size*target)*maker_rebate))) | |
reward_amount = round(reward_amount, 8)*-1 | |
return reward_amount | |
elif contract.find('ETHUSD')==0 and target < entry: #Calculate short ETHUSD reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((target*eth_multiplier*size)-((target*eth_multiplier*size*maker_rebate)) - ((entry*eth_multiplier*size)+((entry*eth_multiplier*size)*maker_rebate))) | |
else: | |
reward_amount = ((target*eth_multiplier*size)-((target*eth_multiplier*size*maker_rebate)) - ((entry*eth_multiplier*size)-((entry*eth_multiplier*size)*taker_fee))) | |
reward_amount = round(reward_amount, 8)*-1 | |
return reward_amount | |
elif contract.find('ETHUSD')==0 and entry < target: #Calculate long ETHUSD reward_amount | |
if order_type == 'Limit': | |
reward_amount = ((entry*eth_multiplier*size)-((entry*eth_multiplier*size*maker_rebate)) - ((target*eth_multiplier*size)+((target*eth_multiplier*size)*maker_rebate))) | |
else: | |
reward_amount = ((entry*eth_multiplier*size)+((entry*eth_multiplier*size*taker_fee)) - ((target*eth_multiplier*size)+((target*eth_multiplier*size)*maker_rebate))) | |
reward_amount = round(reward_amount, 8)*-1 | |
return reward_amount | |
# In[ ]: | |
def r(reward_amount, risk_amount): | |
r_r = reward_amount/risk_amount | |
return r_r | |
# In[ ]: | |
def breakeven(entry, size): | |
y = symbols('y') | |
if contract.find('XBT')==0 and target < entry: #Calculate short breakeven | |
if order_type == 'Limit': | |
eq2 = Eq(((size/y)-((size/y)*taker_fee)) - (size/entry-((size/entry)*maker_rebate))) | |
else: | |
eq2 = Eq(((size/y)-((size/y)*taker_fee)) - (size/entry+((size/entry)*taker_fee))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.1f' % elem for elem in breakeven ] | |
return breakeven | |
elif contract.find('XBT')==0 and entry < target: #Calculate long breakeven | |
if order_type == 'Limit': | |
eq2 = Eq((size/entry-((size/entry)*maker_rebate)) - ((size/y)+((size/y)*taker_fee))) | |
else: | |
eq2 = Eq((size/entry+((size/entry)*taker_fee)) - ((size/y)+((size/y)*taker_fee))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.1f' % elem for elem in breakeven ] | |
return breakeven | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and target < entry: #Calculate short breakeven | |
if order_type == 'Limit': | |
eq2 = Eq(((size*y)+((size*y)*taker_fee)) - (size*entry+((size*entry)*maker_rebate))) | |
else: | |
eq2 = Eq(((size*y)+((size*y)*taker_fee)) - (size*entry-((size*entry)*taker_fee))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.8f' % elem for elem in breakeven ] | |
return breakeven | |
elif contract.find('XBT')==1 and contract.find('ETHUSD')==1 and entry < target: #Calculate long breakeven | |
if order_type == 'Limit': | |
eq2 = Eq((size*entry-((size*entry)*maker_rebate)) - ((size*y)-((size*y)*taker_fee))) | |
else: | |
eq2 = Eq((size*entry+((size*entry)*taker_fee)) - ((size*y)-((size*y)*taker_fee))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.8f' % elem for elem in breakeven ] | |
return breakeven | |
elif contract.find('ETHUSD')==0 and target < entry: #Calculate short ETHUSD breakeven | |
if order_type == 'Limit': | |
eq2 = Eq(((y*eth_multiplier*size)+((y*eth_multiplier*size*taker_fee)) - ((entry*eth_multiplier*size)+((entry*eth_multiplier*size)*maker_rebate)))) | |
else: | |
eq2 = Eq(((y*eth_multiplier*size)+((y*eth_multiplier*size*taker_fee)) - ((entry*eth_multiplier*size)-((entry*eth_multiplier*size)*taker_fee)))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.2f' % elem for elem in breakeven ] | |
return breakeven | |
elif contract.find('ETHUSD')==0 and entry < target: #Calculate long ETHUSD breakeven | |
if order_type == 'Limit': | |
eq2 = Eq(((entry*eth_multiplier*size)-((entry*eth_multiplier*size*maker_rebate)) - ((y*eth_multiplier*size)-((y*eth_multiplier*size)*taker_fee)))) | |
else: | |
eq2 = Eq(((entry*eth_multiplier*size)+((entry*eth_multiplier*size*taker_fee)) - ((y*eth_multiplier*size)-((y*eth_multiplier*size)*taker_fee)))) | |
breakeven = solve(eq2) | |
breakeven = [ '%.2f' % elem for elem in breakeven ] | |
return breakeven | |
# In[ ]: | |
def initiate_trade(contract, size, entry, target, stop): | |
if target < entry: | |
if order_type == order_types[0]: | |
entry_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), ordType='Market').result() | |
exit_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, price=target, execInst='ReduceOnly', ordType='Limit').result() | |
stop_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, stopPx=stop, execInst='LastPrice', ordType='Stop').result() | |
else: | |
entry_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), price=entry).result() | |
exit_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, price=target, stopPx=(entry+tick_size), execInst='LastPrice', ordType='StopLimit').result() | |
stop_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, stopPx=stop, execInst='LastPrice', ordType='Stop').result() | |
elif target > entry: | |
if order_type == order_types[0]: | |
entry_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, ordType='Market').result() | |
exit_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), price=target, execInst='ReduceOnly', ordType='Limit').result() | |
stop_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), stopPx=stop, execInst='LastPrice', ordType='Stop').result() | |
else: | |
entry_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=size, price=entry).result() | |
exit_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), price=target, stopPx=(entry-tick_size), execInst='LastPrice', ordType='StopLimit').result() | |
stop_placement = bitmex_client.Order.Order_new(symbol=contract, orderQty=(size*-1), stopPx=stop, execInst='LastPrice', ordType='Stop').result() | |
# In[ ]: | |
if contract.find('XBT')==0: | |
size = position_size(entry, stop, balance, risk) | |
size = float(size[0]) | |
else: | |
size = position_size(entry, stop, balance, risk) | |
risk_amount = risk_amount(entry, stop, size) | |
loss_final_balance = balance - risk_amount | |
loss_final_balance = round(loss_final_balance, 8) | |
reward_amount = reward_amount(entry, target, size) | |
win_final_balance = balance + reward_amount | |
win_final_balance = round(win_final_balance, 8) | |
r_r = r(reward_amount, risk_amount) | |
r_r = round(r_r, 2) | |
starting_usd = balance*entry | |
starting_usd = round(starting_usd, 2) | |
winning_usd = win_final_balance*target | |
winning_usd = round(winning_usd, 2) | |
losing_usd = loss_final_balance*stop | |
losing_usd = round(losing_usd, 2) | |
breakeven = breakeven(entry, size) | |
breakeven = float(breakeven[0]) | |
risk_amount = format(risk_amount, '.8f') | |
reward_amount = format(reward_amount, '.8f') | |
if target < entry: | |
direction = 'Short' | |
else: | |
direction = 'Long' | |
risk_percentage = str((risk*100))+'%' | |
if contract.find('XBT')==1 and contract.find('ETHUSD')==1: | |
entry_print = format(entry, '.8f') | |
stop_print = format(stop, '.8f') | |
target_print = format(target, '.8f') | |
breakeven_print = format(breakeven, '.8f') | |
message = f""" | |
Contract: {contract} | |
Direction: {direction} | |
BTC Percent Risk: {risk_percentage} | |
Size: {size} | |
""" | |
if contract.find('XBT')==0 or contract.find('ETHUSD')==0: | |
message_1 = f"""Entry: {entry} | |
Stop: {stop} | |
Target: {target} | |
Risk: {risk_amount} BTC | |
Reward: {reward_amount} BTC | |
R: {r_r} | |
Breakeven: {breakeven} | |
""" | |
else: | |
message_1 = f"""Entry: {entry_print} | |
Stop: {stop_print} | |
Target: {target_print} | |
Risk: {risk_amount} BTC | |
Reward: {reward_amount} BTC | |
R: {r_r} | |
Breakeven: {breakeven} | |
""" | |
if contract.find('XBT')==0: | |
message_2 = f"""Starting Balance: {balance} / ${starting_usd} | |
Winning Balance: {win_final_balance} / ${winning_usd} | |
Losing Balance: {loss_final_balance} / ${losing_usd} | |
""" | |
else: | |
message_2 = f"""Starting Balance: {balance} | |
Winning Balance: {win_final_balance} | |
Losing Balance: {loss_final_balance} | |
""" | |
print(message+message_1+message_2) | |
# In[ ]: | |
while True: | |
try: | |
trade_execution = int(input('Do you wish to take this trade? 0:Yes, 1:No' + '\n')) | |
if trade_execution == 0: | |
initiate_trade(contract, size, entry, target, stop) | |
print('TRADE EXECUTED. Script Complete') | |
else: | |
print('TRADE NOT EXECUTED. Script Complete') | |
except ValueError: | |
print('Selection must be a number 0-1. Try Again') | |
continue | |
else: | |
break |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment