diff --git a/src/charts/chart.js b/src/charts/chart.js index a60088a..713441c 100644 --- a/src/charts/chart.js +++ b/src/charts/chart.js @@ -27,6 +27,7 @@ function changeSymbol(symbol) { lastSymbolChangedArgs = info symbolChangedCbs.forEach((cb)=>cb(info)) co.selectedSymbol = info + co.meanRange = chartMeanRange() } @@ -364,3 +365,21 @@ export function deleteShapeId(id) { // console.log('removing entity', id) chart.removeEntity(id) } + +function chartMeanRange() { + 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 +} diff --git a/src/charts/shape.js b/src/charts/shape.js index 3bdc693..4545337 100644 --- a/src/charts/shape.js +++ b/src/charts/shape.js @@ -1,9 +1,9 @@ // noinspection JSPotentiallyInvalidUsageOfThis import {invokeCallback, mixin} from "@/common.js"; -import {chart, createShape, deleteShapeId, dragging, draggingShapeIds, drawShape, widget} from "@/charts/chart.js"; -import {unique} from "@/misc.js"; -import {allocationText, useChartOrderStore} from "@/orderbuild.js"; +import {chart, createShape, deleteShapeId, draggingShapeIds, drawShape, widget} from "@/charts/chart.js"; +import {pointsToOhlcStart, unique} from "@/misc.js"; +import {allocationText} from "@/orderbuild.js"; import Color from "color"; @@ -203,11 +203,11 @@ export class Shape { // createShape(this.type, this.points, {overrides:this.props}, new ShapeTVCallbacks(this)) options = {...options} options['overrides'] = props - this.tvPoints = [...points] + this.tvPoints = pointsToOhlcStart(points) this.tvCallbacks = new ShapeTVCallbacks(this); - const id = createShape(this.type, points, options, this.tvCallbacks) + const id = createShape(this.type, this.tvPoints, options, this.tvCallbacks) // todo set id? - if (this.debug) console.log('created', this.type.name, points, id) + if (this.debug) console.log('created', this.type.name, this.tvPoints, id) } onCreate(points, props) { @@ -241,23 +241,25 @@ export class Shape { // setting points to null will delete the shape from the chart. setting points to a valid value will cause the // shape to be drawn. if (this.debug) console.log('setPoints', this.id, this.ourPoints, points) - const oldPoints = this.ourPoints this.ourPoints = points if (points === null || !points.length) this.delete() else { if (this.id === null) this.create() - else if (dirtyPoints(this.tvPoints, points)) { - const s = this.tvShape(); - const lbe = s._model._lineBeingEdited - const lpbc = s._model._linePointBeingChanged - const lpbe = s._model._linePointBeingEdited - if (lpbc!==null) - s._model.endChangingLinetool(lbe, lpbc) - s.setPoints(points) - if (lpbc!==null) - s._model.startChangingLinetool(lbe, lpbc, lpbe) + else { + points = pointsToOhlcStart(points) + if (dirtyPoints(this.tvPoints, points)) { + const s = this.tvShape(); + const lbe = s._model._lineBeingEdited + const lpbc = s._model._linePointBeingChanged + const lpbe = s._model._linePointBeingEdited + if (lpbc!==null) + s._model.endChangingLinetool(lbe, lpbc) + s.setPoints(points) + if (lpbc!==null) + s._model.startChangingLinetool(lbe, lpbc, lpbe) + } } } } @@ -376,15 +378,15 @@ class ShapeTVCallbacks { onPoints(shapeId, _tvShape, points) { if (!this.enabled) return // possible when shape is deleted and re-created if (this.shape.debug) console.log('tvcb onPoints', points) - this.shape.tvPoints = points this.shape.onPoints(points) + this.shape.tvPoints = points } onProps(shapeId, _tvShape, props) { if (!this.enabled) return // possible when shape is deleted and re-created if (this.shape.debug) console.log('tvOnProps', props) - this.shape.tvProps = props this.shape.onProps(props) + this.shape.tvProps = props } onDraw() { @@ -492,12 +494,6 @@ export class HLine extends Line { } -function nearestOhlcStart(time) { - const period = useChartOrderStore().intervalSecs - return Math.round(time/period) * period -} - - export class VLine extends Line { constructor(model, onModel=null, onDelete=null, props=null) { super(ShapeType.VLine, onModel, onDelete, props) @@ -505,23 +501,12 @@ export class VLine extends Line { // Model this.model.time = null - // since VLines must be on the start of an OHLC boundry, we track that value separately - this.shapeTime = null - this.setModel(model) // call setModel at the end } - doCreate(points, props, options = {}) { - this.shapeTime = nearestOhlcStart(points[0].time); - points = [{time: this.shapeTime, price:0}] - if (this.debug) console.log('VLine.doCreate', this.shapeTime, points) - super.doCreate(points, props, options); - } - delete() { this.model.time = null - this.shapeTime = null super.delete() } @@ -537,26 +522,9 @@ export class VLine extends Line { } } - setPoints(points) { - // if (this.debug) console.error('VLine setPoints...', points) - if (points !== null && points.length) { - // adjust shape to ohlc boundry - const time = nearestOhlcStart(points[0].time); - if (time !== this.shapeTime) { - this.shapeTime = time - super.setPoints([{time, price:0}]); - } - } - else { - this.shapeTime = null - super.setPoints(points); - } - // if (this.debug) console.error('VLine setPoints', points) - } - onPoints(points) { const time = points[0].time; - if ( time !== this.shapeTime ) { + if ( time !== this.tvPoints[0].time ) { super.onPoints(points); this.updateModel({time: time}) } @@ -564,3 +532,50 @@ export class VLine extends Line { } + +export class DLine extends Line { + constructor(model, onModel=null, onDelete=null, props=null) { + super(ShapeType.Line, onModel, onDelete, props) + + this.debug = true // todo debug + + // Model + this.model.pointA = null // {time:..., price:...} + this.model.pointB = null + + // since VLines must be on the start of an OHLC boundry, we track those value separately + this.shapeTimes = null + + this.setModel(model) // call setModel at the end + } + + + delete() { + this.model.pointA = null + this.model.pointB = null + super.delete(); + } + + setModel(model) { + super.setModel(model) + if (model.pointA === null || model.pointB === null) + this.delete() + else if (dirtyPoints(this.model.pointA, model.pointA) || dirtyPoints(this.model.pointB, model.pointB)) { + this.model.pointA = model.pointA + this.model.pointB = model.pointB + this.setPoints([model.pointA, model.pointB]) + } + } + + onPoints(points) { + let dirty = this.tvPoints === null + for (let i=0; !dirty && i{console.log('ate now',props.modelValue); return DateTime.fromSeconds(props.modelValue).setZone(s.timeZone)}) +const now = computed(()=>DateTime.fromSeconds(props.modelValue).setZone(s.timeZone)) const year = computed({ get() { return now.value.year }, diff --git a/src/components/chart/DCABuilder.vue b/src/components/chart/DCABuilder.vue index adfbd11..6fecc1b 100644 --- a/src/components/chart/DCABuilder.vue +++ b/src/components/chart/DCABuilder.vue @@ -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) diff --git a/src/components/chart/DiagonalBuilder.vue b/src/components/chart/DiagonalBuilder.vue new file mode 100644 index 0000000..c0a0a09 --- /dev/null +++ b/src/components/chart/DiagonalBuilder.vue @@ -0,0 +1,181 @@ + + + + + + diff --git a/src/components/chart/LimitBuilder.vue b/src/components/chart/LimitBuilder.vue index c32bc6d..cb5029f 100644 --- a/src/components/chart/LimitBuilder.vue +++ b/src/components/chart/LimitBuilder.vue @@ -1,7 +1,7 @@