Skip to content

Instantly share code, notes, and snippets.

@Dereek69
Created January 23, 2020 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dereek69/c585de7903dc13bbec2691124872096b to your computer and use it in GitHub Desktop.
Save Dereek69/c585de7903dc13bbec2691124872096b to your computer and use it in GitHub Desktop.
Python Script for Risk Management and Order Placement through Bitmex API
#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