Switch to a functional implementation
Pros: More extensible Cons: Slower than the reactive version
This commit is contained in:
parent
220df309c3
commit
b04134c9c5
|
@ -6,7 +6,7 @@
|
|||
type="range"
|
||||
v-model.number="steps"
|
||||
min="1"
|
||||
:max="allEntries.length"
|
||||
:max="bids.length"
|
||||
/>
|
||||
<!-- Two-column layout (on large screen sizes) -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2">
|
||||
|
@ -21,9 +21,9 @@
|
|||
<th>Type</th>
|
||||
<th>Bid</th>
|
||||
<th>Weight</th>
|
||||
<th>Implied Probability</th>
|
||||
<th>Probability</th>
|
||||
<th>Payout</th>
|
||||
<th>Return on win</th>
|
||||
<th>Return</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -34,16 +34,16 @@
|
|||
<td>{{ entry.yesBid }}</td>
|
||||
<td>{{ entry.yesWeight.toFixed(2) }}</td>
|
||||
<td>{{ entry.prob.toFixed(2) }}</td>
|
||||
<td>{{ entry.yesPayout.value.toFixed(2) }}</td>
|
||||
<td>{{ (entry.yesReturn.value * 100).toFixed(2) }}%</td>
|
||||
<td>{{ entry.yesPayout.toFixed(2) }}</td>
|
||||
<td>{{ (entry.yesReturn * 100).toFixed(2) }}%</td>
|
||||
</template>
|
||||
<template v-else>
|
||||
<td><div class="badge badge-error">NO</div></td>
|
||||
<td>{{ entry.noBid }}</td>
|
||||
<td>{{ entry.noWeight.toFixed(2) }}</td>
|
||||
<td>{{ entry.prob.toFixed(2) }}</td>
|
||||
<td>{{ entry.noPayout.value.toFixed(2) }}</td>
|
||||
<td>{{ (entry.noReturn.value * 100).toFixed(2) }}%</td>
|
||||
<td>{{ entry.noPayout.toFixed(2) }}</td>
|
||||
<td>{{ (entry.noReturn * 100).toFixed(2) }}%</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -55,71 +55,19 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import Chart from 'chart.js/auto'
|
||||
import { bids } from './orders'
|
||||
import { bids } from './sample-bids'
|
||||
import { makeEntries } from './entries'
|
||||
import { ref, computed } from '@vue/reactivity'
|
||||
import { onMounted, watch } from '@vue/runtime-core'
|
||||
|
||||
const allEntries = [] as any
|
||||
// Constants. TODO: Pull these from the orders instead of hardcoding.
|
||||
const YES_SEED = 1
|
||||
const NO_SEED = 9
|
||||
// Regular variables
|
||||
let yesPot = 0
|
||||
let noPot = 0
|
||||
// Need this import so script setup will export 'bids' lol
|
||||
const BIDS_LENGTH = bids.length
|
||||
|
||||
// UI parameters
|
||||
const steps = ref(10)
|
||||
|
||||
// Computed variables: stop the simulation at the appropriate number of steps
|
||||
const entries = computed(() => allEntries.slice(0, steps.value))
|
||||
const yesPotC = computed(() =>
|
||||
entries.value.reduce((acc, entry) => acc + entry.yesBid, 0)
|
||||
)
|
||||
const noPotC = computed(() =>
|
||||
entries.value.reduce((acc, entry) => acc + entry.noBid, 0)
|
||||
)
|
||||
const yesWeightsC = computed(() =>
|
||||
entries.value.reduce((acc, entry) => acc + entry.yesWeight, 0)
|
||||
)
|
||||
const noWeightsC = computed(() =>
|
||||
entries.value.reduce((acc, entry) => acc + entry.noWeight, 0)
|
||||
)
|
||||
|
||||
// Calculations:
|
||||
for (const bid of bids) {
|
||||
const { yesBid, noBid } = bid
|
||||
const yesWeight = noPot * (Math.log(yesBid + yesPot) - Math.log(yesPot)) || 0
|
||||
const noWeight = yesPot * (Math.log(noBid + noPot) - Math.log(noPot)) || 0
|
||||
|
||||
// Note: Need to calculate weights BEFORE updating pot
|
||||
yesPot += yesBid
|
||||
noPot += noBid
|
||||
const prob = yesPot / (yesPot + noPot)
|
||||
|
||||
// Payout: You get your initial bid back, as well as your share of the
|
||||
// (noPot - seed) according to your yesWeight
|
||||
const yesPayout = computed(
|
||||
() => yesBid + (yesWeight / yesWeightsC.value) * (noPotC.value - NO_SEED)
|
||||
)
|
||||
const noPayout = computed(
|
||||
() => noBid + (noWeight / noWeightsC.value) * (yesPotC.value - YES_SEED)
|
||||
)
|
||||
|
||||
const yesReturn = computed(() => (yesPayout.value - yesBid) / yesBid)
|
||||
const noReturn = computed(() => (noPayout.value - noBid) / noBid)
|
||||
|
||||
allEntries.push({
|
||||
yesBid,
|
||||
noBid,
|
||||
// Show two decimal places
|
||||
yesWeight,
|
||||
noWeight,
|
||||
prob,
|
||||
yesPayout,
|
||||
noPayout,
|
||||
yesReturn,
|
||||
noReturn,
|
||||
})
|
||||
}
|
||||
const entries = computed(() => makeEntries(bids.slice(0, steps.value)))
|
||||
|
||||
// Graph the probabilities over time
|
||||
const probs = computed(() => entries.value.map((entry) => entry.prob))
|
||||
|
|
60
market-simulator/src/components/entries.ts
Normal file
60
market-simulator/src/components/entries.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
type Bid = { yesBid: number; noBid: number }
|
||||
|
||||
// An entry has a yes/no for bid, weight, payout, return. Also a current probability
|
||||
type Entry = {
|
||||
yesBid: number
|
||||
noBid: number
|
||||
yesWeight: number
|
||||
noWeight: number
|
||||
yesPayout: number
|
||||
noPayout: number
|
||||
yesReturn: number
|
||||
noReturn: number
|
||||
prob: number
|
||||
}
|
||||
|
||||
export function makeEntries(bids: Bid[]): Entry[] {
|
||||
const entries: Entry[] = []
|
||||
let yesPot = 0
|
||||
let noPot = 0
|
||||
// First pass: calculate all the weights
|
||||
for (const { yesBid, noBid } of bids) {
|
||||
const yesWeight =
|
||||
noPot * (Math.log(yesBid + yesPot) - Math.log(yesPot)) || 0
|
||||
const noWeight = yesPot * (Math.log(noBid + noPot) - Math.log(noPot)) || 0
|
||||
|
||||
// Note: Need to calculate weights BEFORE updating pot
|
||||
yesPot += yesBid
|
||||
noPot += noBid
|
||||
const prob = yesPot / (yesPot + noPot)
|
||||
|
||||
entries.push({
|
||||
yesBid,
|
||||
noBid,
|
||||
yesWeight,
|
||||
noWeight,
|
||||
prob,
|
||||
// To be filled in below
|
||||
yesPayout: 0,
|
||||
noPayout: 0,
|
||||
yesReturn: 0,
|
||||
noReturn: 0,
|
||||
})
|
||||
}
|
||||
|
||||
const YES_SEED = bids[0].yesBid
|
||||
const NO_SEED = bids[0].noBid
|
||||
const yesWeightsSum = entries.reduce((sum, entry) => sum + entry.yesWeight, 0)
|
||||
const noWeightsSum = entries.reduce((sum, entry) => sum + entry.noWeight, 0)
|
||||
// Second pass: calculate all the payouts
|
||||
for (const entry of entries) {
|
||||
const { yesBid, noBid, yesWeight, noWeight } = entry
|
||||
// Payout: You get your initial bid back, as well as your share of the
|
||||
// (noPot - seed) according to your yesWeight
|
||||
entry.yesPayout = yesBid + (yesWeight / yesWeightsSum) * (noPot - NO_SEED)
|
||||
entry.noPayout = noBid + (noWeight / noWeightsSum) * (yesPot - YES_SEED)
|
||||
entry.yesReturn = (entry.yesPayout - yesBid) / yesBid
|
||||
entry.noReturn = (entry.noPayout - noBid) / noBid
|
||||
}
|
||||
return entries
|
||||
}
|
Loading…
Reference in New Issue
Block a user