initial diagonal work (unfinished)
This commit is contained in:
@@ -129,7 +129,6 @@ watchEffect(()=>{
|
||||
const absTimeA = computed({
|
||||
get() { return _timeEndpoints.value[0] },
|
||||
set(v) {
|
||||
console.log('set A', v)
|
||||
if (v!==null)
|
||||
v = Number(v)
|
||||
updateA(v)
|
||||
|
||||
181
src/components/chart/DiagonalBuilder.vue
Normal file
181
src/components/chart/DiagonalBuilder.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<rung-builder name="Diagonal" :order="order" :builder="builder" v-model="endpoints"
|
||||
:shape="DLine" :mode="0"
|
||||
:get-model-value="getModelValue" :set-model-value="setModelValue"
|
||||
:get-points-value="getPointsValue"
|
||||
:set-values="setLines" :set-weights="setWeights"
|
||||
:std-width="stdWidth" :build-tranches="buildTranches">
|
||||
<table>
|
||||
<tbody>
|
||||
<template v-if="prices.length>1">
|
||||
<tr>
|
||||
<td>
|
||||
<v-text-field type="number" v-model="higherPrice" min="0"
|
||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||
label="Price"
|
||||
:color="color" :base-color="color"
|
||||
style="flex: 6em"
|
||||
/>
|
||||
</td>
|
||||
<td class="weight">{{ allocationText(weights[higherIndex]) }}</td>
|
||||
</tr>
|
||||
<tr v-for="i in innerIndexes" class="ml-5">
|
||||
<td class="pl-5">{{ prices[i] }}</td>
|
||||
<td class="weight">{{ allocationText(weights[i]) }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
<tr>
|
||||
<td>
|
||||
<v-text-field type="number" v-model="lowerPrice" min="0"
|
||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||
label="Price"
|
||||
:color="color" :base-color="color"
|
||||
style="flex: 6em"
|
||||
/>
|
||||
</td>
|
||||
<td class="weight">{{ weights.length ? allocationText(weights[lowerIndex]) : '' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</rung-builder>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {allocationText, applyLine, applyLinePoints, builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {interpolate, sideColor} from "@/misc.js";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
import {computed, ref} from "vue";
|
||||
import {DLine} from "@/charts/shape.js";
|
||||
import {vectorInterpolate} from "@/vector.js";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
const props = defineProps(['order', 'builder'])
|
||||
const emit = defineEmits(['update:builder'])
|
||||
|
||||
function computeDefaultColor() {
|
||||
const index = props.order.builders.indexOf(props.builder)
|
||||
return sideColor(props.order.buy, index)
|
||||
}
|
||||
|
||||
const defaultColor = computeDefaultColor()
|
||||
|
||||
// Fields must be defined in order to be reactive
|
||||
builderDefaults(props.builder, {
|
||||
lineA: [null, null], // [{time, price}, {time, price}]
|
||||
lineB: [null, null],
|
||||
rungs: 1,
|
||||
skew: 0,
|
||||
color: defaultColor,
|
||||
})
|
||||
|
||||
|
||||
function buildTranches() {
|
||||
throw Error('unimplemented') // todo
|
||||
const order = props.order
|
||||
const builder = props.builder
|
||||
const tranches = []
|
||||
|
||||
console.log('buildTranches', builder, order, tranches)
|
||||
const la = buildLine(_endpoints[0])
|
||||
const lb = buildLine(_endpoints[1])
|
||||
const ws = weights.value
|
||||
for (let i = 0; i < ws.length; i++) {
|
||||
const w = ws[i]
|
||||
const line = vectorInterpolate(la, lb, i/(ws.length-1))
|
||||
const t = newTranche({fraction: w * MAX_FRACTION})
|
||||
const symbol = co.selectedSymbol
|
||||
console.log('symbol', symbol)
|
||||
applyLinePoints(t, order.buy, ...line, symbol.decimals, symbol.inverted)
|
||||
tranches.push(t)
|
||||
}
|
||||
return tranches
|
||||
}
|
||||
|
||||
|
||||
function flattenLine(l) {
|
||||
return l === null ? [null, null, null, null] : [l[0].time, l[0].price, l[1].time, l[1].price]
|
||||
}
|
||||
|
||||
|
||||
function buildLine(f) {
|
||||
return f[0] === null ? null : [{time: f[0], price: f[1]}, {time: f[2], price: f[3]}]
|
||||
}
|
||||
|
||||
const _endpoints = ref([flattenLine(props.builder.lineA), flattenLine(props.builder.lineB)])
|
||||
const endpoints = computed({
|
||||
get() {
|
||||
return _endpoints.value
|
||||
},
|
||||
set(v) {
|
||||
const [a, b] = v
|
||||
update(a, b)
|
||||
}
|
||||
})
|
||||
|
||||
function update(a, b) { // a and b are lines of two points
|
||||
_endpoints.value = [flattenLine(a), flattenLine(b)]
|
||||
const newBuilder = {...props.builder}
|
||||
newBuilder.lineA = a
|
||||
newBuilder.lineB = b
|
||||
emit('update:builder', newBuilder)
|
||||
}
|
||||
|
||||
|
||||
const innerIndexes = computed(() => {
|
||||
const n = flatLines.value.length
|
||||
const result = []
|
||||
for (let i = 1; i < n - 1; i++)
|
||||
result.push(n - 1 - i)
|
||||
return result
|
||||
})
|
||||
|
||||
|
||||
const flatLines = ref([])
|
||||
const weights = ref([])
|
||||
|
||||
function setLines(ls) {
|
||||
flatLines.value = ls
|
||||
}
|
||||
|
||||
function setWeights(ws) {
|
||||
weights.value = ws
|
||||
}
|
||||
|
||||
|
||||
const color = computed(() => props.builder.color ? props.builder.color : defaultColor)
|
||||
|
||||
const stdWidth = [2 * co.meanRange, 2 * co.meanRange]
|
||||
|
||||
|
||||
function getModelValue(model) {
|
||||
if (!model)
|
||||
return null
|
||||
return [flattenLine(model.lineA), flattenLine(model.lineB)]
|
||||
}
|
||||
|
||||
function getPointsValue(points) {
|
||||
return points[0].price
|
||||
}
|
||||
|
||||
function setModelValue(model, value) {
|
||||
// console.log('setModelValue->', model.price, value)
|
||||
if (model.price !== value)
|
||||
model.price = value
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
td.weight {
|
||||
width: 11em;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<rung-builder :name="prices.length>1?'Ladder':'Limit'" :order="order" :builder="builder"
|
||||
v-model="priceEndpoints" :mode="0" :flip="flipped"
|
||||
:shape="HLine"
|
||||
:shape="HLine"
|
||||
:get-model-value="getModelValue" :set-model-value="setModelValue"
|
||||
:get-points-value="getPointsValue"
|
||||
:set-values="setPrices" :set-weights="setWeights"
|
||||
@@ -42,14 +42,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {applyLine2, builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {allocationText, applyLine, builderDefaults, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {sideColor} from "@/misc.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
import {computed, ref, watchEffect} from "vue";
|
||||
import {chart} from "@/charts/chart.js";
|
||||
import {computed, ref} from "vue";
|
||||
import {chartMeanRange} from "@/charts/chart.js";
|
||||
import {HLine} from "@/charts/shape.js";
|
||||
|
||||
const s = useStore()
|
||||
@@ -93,7 +92,7 @@ function buildTranches() {
|
||||
})
|
||||
const symbol = co.selectedSymbol
|
||||
console.log('symbol', symbol)
|
||||
applyLine2(t, !order.buy, p, 0, symbol.decimals, symbol.inverted)
|
||||
applyLine(t, , p, 0, symbol.decimals, symbol.inverted)
|
||||
tranches.push(t)
|
||||
}
|
||||
return tranches
|
||||
@@ -195,39 +194,8 @@ function setWeights(ws) { weights.value = ws }
|
||||
|
||||
const color = computed(()=>props.builder.color ? props.builder.color : defaultColor)
|
||||
|
||||
function computeRange() {
|
||||
let range = 0
|
||||
const series = chart.getSeries()
|
||||
const bars = series.data().bars();
|
||||
const final = Math.max(bars.size() - 50, 0)
|
||||
let count = 0
|
||||
for (let barIndex = bars.size() - 1; barIndex >= final; barIndex--) {
|
||||
count++
|
||||
const [_time, _open, high, low, _close, _volume, _ms] = bars.valueAt(barIndex)
|
||||
range += (high - low)
|
||||
}
|
||||
if (count > 0)
|
||||
range /= count
|
||||
else
|
||||
range = 1
|
||||
return range
|
||||
}
|
||||
const stdWidth = 2*co.meanRange
|
||||
|
||||
const stdWidth = 2*computeRange() // todo make reactive
|
||||
|
||||
|
||||
const amountSymbol = computed(()=>props.order.amountIsTokenA ? co.selectedSymbol.base.s : co.selectedSymbol.quote.s )
|
||||
|
||||
|
||||
// todo move into misc and use in shape as well
|
||||
function allocationText(weight) {
|
||||
const alloc = props.builder.allocation
|
||||
if (alloc===null) return ''
|
||||
const w = weight * alloc
|
||||
// console.log('weight', weight, alloc, props.amount)
|
||||
const a = props.order.amount * w
|
||||
return `${(w*100).toFixed(1)}% = ${a.toLocaleString('fullwide')} ${amountSymbol.value}`
|
||||
}
|
||||
|
||||
function getModelValue(model) {
|
||||
if(!model)
|
||||
|
||||
@@ -41,7 +41,16 @@ import {linspace, sideColor} from "@/misc.js";
|
||||
import {computed, watchEffect} from "vue";
|
||||
import Color from "color";
|
||||
import {cancelDrawing} from "@/charts/chart.js";
|
||||
import {devectorize, vectorAdd, vectorDiv, vectorMul, vectorSub, vectorIsNull, vectorize} from "@/vector.js";
|
||||
import {
|
||||
devectorize,
|
||||
vectorAdd,
|
||||
vectorDiv,
|
||||
vectorMul,
|
||||
vectorSub,
|
||||
vectorIsNull,
|
||||
vectorize,
|
||||
vectorIsZero
|
||||
} from "@/vector.js";
|
||||
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
@@ -99,9 +108,8 @@ const rungs = computed({
|
||||
r = Number(r)
|
||||
const prevR = Number(props.builder.rungs)
|
||||
props.builder.rungs = r
|
||||
console.log('set rungs', prevR, r, a, b)
|
||||
// console.log('set rungs', prevR, r, a, b)
|
||||
if ( r > 0 && vectorIsNull(b) ) {
|
||||
console.log('convert to range')
|
||||
// convert single shape to a range
|
||||
if (props.mode===0) {
|
||||
const width = props.stdWidth
|
||||
@@ -126,7 +134,6 @@ const rungs = computed({
|
||||
else {
|
||||
// from multi to multi
|
||||
if (props.mode===1) {
|
||||
console.log('multi-multi mode 1')
|
||||
const width = vectorDiv(vectorSub(b, a), (prevR-1))
|
||||
b = vectorAdd(a, vectorMul(width, (r-1)))
|
||||
setEndpoints(a,b)
|
||||
@@ -222,18 +229,18 @@ function translateOnModel(shape) {
|
||||
const oldOnModel = shape.onModel
|
||||
shape.onModel = function (model, oldModel) {
|
||||
oldOnModel.call(this, ...arguments)
|
||||
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
|
||||
if (!this.beingDragged())
|
||||
return
|
||||
const prev = getModelValue(oldModel)
|
||||
const cur = getModelValue(this.model)
|
||||
const delta = cur - prev
|
||||
const cur = vectorize(getModelValue(this.model))
|
||||
const delta = vectorSub(cur, prev)
|
||||
// console.log('delta', shape.id, prev, cur, delta)
|
||||
let [a, b] = endpoints.value
|
||||
if (delta !== 0) {
|
||||
a = vectorize(a)
|
||||
if (!vectorIsZero(delta)) {
|
||||
a = vectorAdd(a, delta)
|
||||
if (rungs.value > 1)
|
||||
b = vectorAdd(b, delta)
|
||||
b = vectorAdd(vectorize(b), delta)
|
||||
setEndpoints(a,b)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user