Skip to content

Instantly share code, notes, and snippets.

@kebman
Created May 7, 2021 19:57
Show Gist options
  • Save kebman/5c4e4cc4da306a03645b910db397e1fe to your computer and use it in GitHub Desktop.
Save kebman/5c4e4cc4da306a03645b910db397e1fe to your computer and use it in GitHub Desktop.
Coinbase Pro Order Formatting Tool in HTML5
<!DOCTYPE html>
<html class="no-js" lang="eng">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="Order Formatting App">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" href="css/main.css"> -->
<style type="text/css">
#outData {
/* background-color: red; */
width: 60%;
/* float: right; */
position: absolute;
padding: 1em;
padding-top: 0px;
margin-top: 0px;
margin-left: 55ex;
}
#outData p {
padding-top: 0px;
margin-top: 0.5ex;
}
article {
width: 50ex;
}
section {
position: relative;
}
</style>
</head>
<body>
<h1>Order Formatting App</h1>
<section>
<div id="outData" style="user-select: all">
</div>
<article>
<form id="orderData" action="" method="post">
<textarea rows="5" cols="50" name="input" onpaste="return true;" placeholder="Paste price data here."></textarea>
<!-- <input type="submit" value="submit" /> -->
</form>
</article>
<article>
<h1>Use</h1>
<p>Copy an order from Coinbase Pro > Orders > Filled, including fills. </p>
<p>Make sure you get everything form the Buy or Sell keyword and to the last fill. Then paste it into the above box.</p>
</article>
<article>
<h1>What</h1>
<p>This bare-bones app makes human-readable “JSON” out of raw orders copied from Coinbase Pro. It also calculates totals for later use with Profit Loss calculations, and it spits out a handy Break Even price based upon Coinbase Pro starter fees (0.5%).</p>
</article>
<article>
<h1>Background</h1>
<p>I often found myself copying orders from Coinbase Pro for two major reasons. First off Coinbase Pro doesn't show how much you spent on a trade. It's good to know how much you spent, with fees subtracted, in order to figure out your profit loss ratio. Additionally, I'd usually copy recent orders to find the break even point, so that I'd know where to trail my stop loss once a trade became profitable.</p>
<p>Complete re-build of an earlier version that spat out strings formatted for storage in spreadsheets such as Excel. New features include totals and break even, plus getting rid of the submit button entirely, and make the paste itself the submit trigger.</p>
</article>
<article>
<h1>Raw data example for testing</h1>
<pre style="user-select: all">
Buy
ETH/BTC
0.01000000 ETH
0.01000000
₿0.03874
₿0.00000
Apr 16, 2021 - 02:24:52 PM
Side
Market
Size
Trade ID
Price
Fee
Date
Buy
ETH/BTC
0.00066370
14465622
₿0.03874
₿0.00000
Apr 16, 2021 - 03:45:02 PM
Buy
ETH/BTC
0.00800000
14465626
₿0.03874
₿0.00000
Apr 16, 2021 - 03:45:02 PM
Buy
ETH/BTC
0.00133630
14465627
₿0.03874
₿0.00000
Apr 16, 2021 - 03:45:01 PM
</pre>
</article>
<article>
<p><a href="raw order data example.txt">More examples.</a></p>
</article>
</section>
</body>
</html>
<script type="text/javascript">
const form = document.getElementById('orderData')
const outData = document.getElementById('outData')
const currencySymbols = [{"BTC":"₿"},{"ETH":"Ξ"},{"USD":"$"},{"EUR":"€"},{"GBP":"£"}]
let orderObject = {
order: {}
}
let orderStr = ""
// automagically fetch raw data pasted in form
form.addEventListener('paste', function(e) {
let input = this.input.value
let clipboardData = e.clipboardData || window.clipboardData
let raw = clipboardData.getData('Text')
prepData(raw)
e.preventDefault()
}, false)
// prepare data
function prepData(data) {
let trade = data.split('\n')
if (trade[0].trim() == 'Buy' || trade[0].trim() == 'Sell') {
// populate the orderObject with trade data
orderObject.order.side = trade[0].trim()
orderObject.order.market = trade[1].trim()
orderObject.order.size = trade[2].trim()
orderObject.order.filled = parseFloat(trade[3].trim())
orderObject.order.price = trade[4].trim()
orderObject.order.fee = trade[5].trim()
orderObject.order.dateSet = trade[6].trim()
// prepare strings for calculations
let priceFloat = parseFloat(trade[4].slice(1).replace(/,/g, ''))
let priceCurrencySymbol = trade[4].slice(0,1)
let feeFloat = parseFloat(trade[5].slice(1).replace(/,/g, ''))
let feeCurrencySymbol = trade[5].slice(0,1)
let filledFloat = parseFloat(trade[3])
// calculate totals while substracting fees
let total = filledFloat*priceFloat
if (trade[0].trim() == 'Buy') {
total = total + feeFloat
orderObject.order.breakEven = breakEven(priceFloat)
}
if (trade[0].trim() == 'Sell') {
total = total - feeFloat
}
orderObject.order.total = total
// check for fills
if (trade.length > 14) {
orderObject.fills = []
if (trade[14].trim() == 'Buy' || trade[14].trim() == 'Sell') {
fills = trade.slice(14)
checkFills(fills)
}
}
formatOrder(orderObject)
} else {
console.error("Likely error in data")
}
}
// run through all fills as well
function checkFills(data) {
let fillObject = {}
fillObject.size = parseFloat(data[2].trim())
fillObject.tradeId = parseInt(data[3].trim())
fillObject.price = data[4].trim()
fillObject.fee = data[5].trim()
fillObject.dateFilled = data[6].trim()
// and save them as objects in an array
orderObject.fills.push(fillObject)
if (data.length > 7) {
if (data[7].trim() == 'Buy' || data[7].trim() == 'Sell') {
data = data.slice(7)
// callback
checkFills(data)
}
}
}
function breakEven(price) {
let feeRate = 0.005 // starter fee
let fee1 = 1*feeRate
let amount1 = 1-fee1
let fee2 = (1+fee1)*feeRate
let amount2 = 1+fee2
return amount2*price/amount1
}
function formatOrder(obj) {
let order = "Order: {\nSide: "+
obj.order.side
+"\nMarket: "+
obj.order.market
+"\nSize: "+
obj.order.size
+"\nFilled: "+
obj.order.filled
+"\nPrice: "+
obj.order.price.replace(/,/g, '')
+"\nFee: "+
obj.order.fee
+"\nDate set: "+
obj.order.dateSet
+"\nBreak even: "+
obj.order.breakEven
+"\nTotal: "+
obj.order.total
+"\n},\nFills: [{\n"
publish(order, obj)
}
function publish(data, obj) {
let pre = document.createElement("pre")
let node = document.createTextNode(data)
pre.append(node)
outData.appendChild(pre)
let i = 0
obj.fills.forEach(function (element) {
i++
let fill = "Date Filled: "+
element.dateFilled
+"\nTrade ID: "+
element.tradeId
+"\nSize: "+
element.size+"\n"
if(i == obj.fills.length) {
fill+= "}]}\n"
} else {
fill+= "},{\n"
}
node = document.createTextNode(fill)
pre.append(node)
outData.appendChild(pre)
})
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment