From 33d2f9d27e757d309c7d9e236b44c85389dc8679 Mon Sep 17 00:00:00 2001 From: Bogdan Popa Date: Sun, 5 Nov 2023 18:05:40 +0200 Subject: [PATCH] FranzCocoa,ResultDetail: enable programmatic control of candle widths --- FranzCocoa/Backend.swift | 4 ++-- FranzCocoa/ResultDetail.swift | 27 +++++++++------------------ FranzCross/result-detail.rkt | 5 +++-- core/script.rkt | 4 ++-- manual/index.scrbl | 3 +++ 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/FranzCocoa/Backend.swift b/FranzCocoa/Backend.swift index f4beb23..51ade91 100644 --- a/FranzCocoa/Backend.swift +++ b/FranzCocoa/Backend.swift @@ -95,7 +95,7 @@ public enum ChartScaleType: Readable, Writable { public enum ChartStyle: Readable, Writable { case bar - case candlestick(UVarint) + case candlestick(UVarint?) case line case scatter @@ -106,7 +106,7 @@ public enum ChartStyle: Readable, Writable { return .bar case 0x0001: return .candlestick( - UVarint.read(from: inp, using: &buf) + UVarint?.read(from: inp, using: &buf) ) case 0x0002: return .line diff --git a/FranzCocoa/ResultDetail.swift b/FranzCocoa/ResultDetail.swift index 606413d..347ffc2 100644 --- a/FranzCocoa/ResultDetail.swift +++ b/FranzCocoa/ResultDetail.swift @@ -1,4 +1,5 @@ import Charts +import NoiseSerde import SwiftUI struct ResultDetail: View { @@ -61,11 +62,11 @@ fileprivate struct ChartResult: View { switch chart.style { case .bar: try? p.barMark(xLabel: chart.xLabel, yLabel: chart.yLabel) - case .candlestick: + case .candlestick(let width): try? p.candlestickMark( xLabel: chart.xLabel, yLabel: chart.yLabel, - previous: p.id > 0 && p.id < ps.endIndex ? ps[p.id-1] : nil + width: width ) case .line: try? p.lineMark(xLabel: chart.xLabel, yLabel: chart.yLabel) @@ -91,21 +92,17 @@ fileprivate struct ChartResult: View { case badMarks } - private enum CandlestickDirection { - case up - case down - } - private struct CandlestickMark: ChartContent { let x: PlottableValue let o: PlottableValue let h: PlottableValue let l: PlottableValue let c: PlottableValue + let w: UVarint? var body: some ChartContent { RectangleMark(x: x, yStart: l, yEnd: h, width: 1) - RectangleMark(x: x, yStart: o, yEnd: c, width: 14) + RectangleMark(x: x, yStart: o, yEnd: c, width: MarkDimension(integerLiteral: Int(w ?? 14))) } } @@ -132,25 +129,19 @@ fileprivate struct ChartResult: View { func candlestickMark( xLabel: String, yLabel: String, - previous: Pair? + width: UVarint? ) throws -> some ChartContent { switch (x, y) { case (.timestamp(let ts), .candlestick(let o, let h, let l, let c)): - var direction: CandlestickDirection - switch previous?.y { - case .some(.candlestick(_, _, _, let oc)): - direction = oc > c ? .down : .up - default: - direction = .up - } return CandlestickMark( x: .value("Date", Date(timeIntervalSince1970: Double(ts))), o: .value("Open", o), h: .value("High", h), l: .value("Low", l), - c: .value("Close", c) + c: .value("Close", c), + w: width ) - .foregroundStyle(direction == .down ? .red : .green) + .foregroundStyle(o > c ? .red : .green) default: throw ChartError.badMarks } diff --git a/FranzCross/result-detail.rkt b/FranzCross/result-detail.rkt index d060dbd..ae39f3d 100644 --- a/FranzCross/result-detail.rkt +++ b/FranzCross/result-detail.rkt @@ -57,8 +57,9 @@ (ormap ChartValue.timestamp? (Chart-ys c))) (parameterize ([candlestick-width (match (Chart-style c) - [(ChartStyle.candlestick width) width] - [_ 1])] + [(ChartStyle.candlestick width) + (or width 60)] + [_ 60])] [plot-x-ticks (if x-date-ticks? (date-ticks) diff --git a/core/script.rkt b/core/script.rkt index 2f077f6..3d2482f 100644 --- a/core/script.rkt +++ b/core/script.rkt @@ -45,7 +45,7 @@ (define-enum ChartStyle [bar] [candlestick - {width : UVarint}] + {width : (Optional UVarint)}] [line] [scatter]) @@ -106,7 +106,7 @@ [(#"CandlestickChart") (ChartStyle.candlestick (let ([width (table-ref v #"candlestick_width")]) - (if (nil? width) 1 (inexact->exact width))))] + (if (nil? width) #f (inexact->exact width))))] [(#"LineChart") (ChartStyle.line)] [(#"ScatterChart") diff --git a/manual/index.scrbl b/manual/index.scrbl index 24efce6..96f310d 100644 --- a/manual/index.scrbl +++ b/manual/index.scrbl @@ -812,6 +812,9 @@ aggregated data to a window when applying a script. chart. The width of a candle must be the length of the interval (in seconds) between x ticks on the chart. For example, if the chart is to display daily candles, the width of each candle would be @tt{86400}. + + On macOS, this method controls the pixel width of the candles. Use it + to make thinner candles when necessary. } @deflua[render.Candlestick (o h l c) Candlestick]{