-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lets go on and make it more beautiful. First things first: - modify it, so that you could toggle between dark and light mode on the upper right corner - add some nice graphic as background behind the 'h1' - make the field for the trading stack a bit more spacious. - dont display results table, before pushing the 'calculate' button - dont show the add row button - show one row from the beginning. - when hopping from the win probability column with 'tab' to the next field, add automatically another row - adjust the 'calculate' button a bit more in the middle and below the table - when pushing the 'calculate' button: 1. hide the entry table 2. show the results table, but without the 'results' label 3. resize the table to the values inside 4. publish it in the middle of the page
- Loading branch information
1 parent
e47fb43
commit ab6739c
Showing
1 changed file
with
66 additions
and
50 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,85 @@ | ||
function createRow() { | ||
const row = document.createElement('tr'); | ||
row.innerHTML = ` | ||
<td><input type="text" name="ticker" required></td> | ||
<td><input type="number" step="0.01" name="entry" required></td> | ||
<td><input type="number" step="0.01" name="tp" required></td> | ||
<td><input type="number" step="0.01" name="sl" required></td> | ||
<td><input type="number" step="0.01" min="0" max="1" name="winProbability" required></td> | ||
`; | ||
return row; | ||
} | ||
|
||
function calculate_rr(entry, tp, sl) { | ||
return Math.abs((tp - entry) / (entry - sl)); | ||
} | ||
|
||
function kelly_criterion(win_probability, win_loss_ratio) { | ||
return win_probability - ((1 - win_probability) / win_loss_ratio); | ||
} | ||
|
||
document.addEventListener('DOMContentLoaded', () => { | ||
const themeSwitch = document.getElementById('theme-switch'); | ||
const tradesForm = document.getElementById('trades-form'); | ||
const tradesInput = document.getElementById('trades-input'); | ||
const results = document.getElementById('results'); | ||
const addRowButton = document.getElementById('add-row'); | ||
const resultsTable = document.getElementById('results'); | ||
|
||
addRowButton.addEventListener('click', (event) => { | ||
event.preventDefault(); | ||
tradesInput.appendChild(createRow()); | ||
themeSwitch.addEventListener('change', () => { | ||
document.body.classList.toggle('dark-mode'); | ||
}); | ||
|
||
addRow(); | ||
|
||
tradesForm.addEventListener('submit', (event) => { | ||
event.preventDefault(); | ||
const tradingStack = parseFloat(document.getElementById('trading-stack').value); | ||
const tradeData = Array.from(tradesInput.querySelectorAll('tr')) | ||
.slice(1) | ||
.map(row => { | ||
const inputs = row.querySelectorAll('input'); | ||
const ticker = inputs[0].value; | ||
const entry = parseFloat(inputs[1].value); | ||
const tp = parseFloat(inputs[2].value); | ||
const sl = parseFloat(inputs[3].value); | ||
const winProbability = parseFloat(inputs[4].value); | ||
|
||
const tradeInputs = Array.from(tradesInput.querySelectorAll('tr')); | ||
const trades = tradeInputs.map((row) => { | ||
const ticker = row.querySelector('[name="ticker"]').value; | ||
const entry = parseFloat(row.querySelector('[name="entry"]').value); | ||
const tp = parseFloat(row.querySelector('[name="tp"]').value); | ||
const sl = parseFloat(row.querySelector('[name="sl"]').value); | ||
const winProbability = parseFloat(row.querySelector('[name="winProbability"]').value); | ||
|
||
const rr = calculate_rr(entry, tp, sl); | ||
const kellyValue = kelly_criterion(winProbability, rr); | ||
return { ticker, entry, tp, sl, winProbability }; | ||
}); | ||
|
||
return { ticker, entry, tp, sl, winProbability, rr, kellyValue }; | ||
}); | ||
const results = calculate(tradeData, tradingStack); | ||
displayResults(results); | ||
|
||
const totalKellyValue = trades.reduce((sum, trade) => sum + trade.kellyValue, 0); | ||
tradesForm.classList.add('hidden'); | ||
resultsTable.classList.remove('hidden'); | ||
}); | ||
|
||
const tradingStack = parseFloat(document.getElementById('trading-stack').value); | ||
function addRow() { | ||
const row = tradesInput.insertRow(); | ||
for (let i = 0; i < 5; i++) { | ||
const cell = row.insertCell(); | ||
const input = document.createElement('input'); | ||
input.type = i < 4 ? 'number' : 'text'; | ||
input.required = true; | ||
cell.appendChild(input); | ||
} | ||
|
||
const winProbabilityInput = row.querySelector('input:nth-child(5)'); | ||
winProbabilityInput.addEventListener('focus', () => { | ||
addRow(); | ||
}); | ||
} | ||
|
||
trades.forEach((trade) => { | ||
trade.adjustedTradingSize = (trade.kellyValue / totalKellyValue) * tradingStack; | ||
function calculate(tradeData, tradingStack) { | ||
const results = tradeData.map(data => { | ||
const rr = (data.tp - data.entry) / (data.entry - data.sl); | ||
const kellyValue = kelly_criterion(data.winProbability, rr); | ||
const tradingSize = tradingStack * kellyValue; | ||
return { ticker: data.ticker, rr, kellyValue, tradingSize }; | ||
}); | ||
|
||
results.innerHTML = trades | ||
.map( | ||
(trade) => ` | ||
return results; | ||
} | ||
|
||
function kelly_criterion(winProbability, rr) { | ||
return (winProbability * rr - (1 - winProbability)) / rr; | ||
} | ||
|
||
function displayResults(results) { | ||
resultsTable.innerHTML = ` | ||
<tr> | ||
<td>${trade.ticker}</td> | ||
<td>${trade.adjustedTradingSize.toFixed(2)}</td> | ||
<th>Ticker</th> | ||
<th>RR</th> | ||
<th>Kelly Value</th> | ||
<th>Trading Size</th> | ||
</tr> | ||
` | ||
) | ||
.join(''); | ||
}); | ||
`; | ||
|
||
for (const result of results) { | ||
const row = resultsTable.insertRow(); | ||
row.insertCell().textContent = result.ticker; | ||
row.insertCell().textContent = result.rr.toFixed(2); | ||
row.insertCell().textContent = result.kellyValue.toFixed(2); | ||
row.insertCell().textContent = result.tradingSize.toFixed(2); | ||
} | ||
} | ||
}); |