diff --git a/asset/README.md b/asset/README.md index 6907cda1..bc1126cc 100644 --- a/asset/README.md +++ b/asset/README.md @@ -563,7 +563,7 @@ type TiingoEndOfDay struct { Close float64 `json:"close"` // Volume is the total volume. - Volume int64 `json:"volume"` + Volume float64 `json:"volume"` // AdjOpen is the adjusted opening price. AdjOpen float64 `json:"adjOpen"` @@ -578,7 +578,7 @@ type TiingoEndOfDay struct { AdjClose float64 `json:"adjClose"` // AdjVolume is the adjusted total volume. - AdjVolume int64 `json:"adjVolume"` + AdjVolume float64 `json:"adjVolume"` // Dividend is the dividend paid out. Dividend float64 `json:"divCash"` diff --git a/strategy/momentum/README.md b/strategy/momentum/README.md index 5db30354..d72bd362 100644 --- a/strategy/momentum/README.md +++ b/strategy/momentum/README.md @@ -55,6 +55,12 @@ The information provided on this project is strictly for informational purposes - [func \(t \*TripleRsiStrategy\) IdlePeriod\(\) int](<#TripleRsiStrategy.IdlePeriod>) - [func \(t \*TripleRsiStrategy\) Name\(\) string](<#TripleRsiStrategy.Name>) - [func \(t \*TripleRsiStrategy\) Report\(c \<\-chan \*asset.Snapshot\) \*helper.Report](<#TripleRsiStrategy.Report>) +- [type WilliamsRStrategy](<#WilliamsRStrategy>) + - [func NewWilliamsRStrategy\(\) \*WilliamsRStrategy](<#NewWilliamsRStrategy>) + - [func NewWilliamsRStrategyWith\(buyAt, sellAt float64\) \*WilliamsRStrategy](<#NewWilliamsRStrategyWith>) + - [func \(r \*WilliamsRStrategy\) Compute\(snapshots \<\-chan \*asset.Snapshot\) \<\-chan strategy.Action](<#WilliamsRStrategy.Compute>) + - [func \(r \*WilliamsRStrategy\) Name\(\) string](<#WilliamsRStrategy.Name>) + - [func \(r \*WilliamsRStrategy\) Report\(c \<\-chan \*asset.Snapshot\) \*helper.Report](<#WilliamsRStrategy.Report>) ## Constants @@ -107,6 +113,18 @@ const ( ) ``` + + +```go +const ( + // DefaultWilliamsRStrategyBuyAt defines the default Williams R level at which a Buy action is generated. + DefaultWilliamsRStrategyBuyAt = -80.0 + + // DefaultWilliamsRStrategySellAt defines the default Williams R level at which a Sell action is generated. + DefaultWilliamsRStrategySellAt = -20.0 +) +``` + ## func [AllStrategies]() @@ -425,4 +443,67 @@ func (t *TripleRsiStrategy) Report(c <-chan *asset.Snapshot) *helper.Report Report processes the provided asset snapshots and generates a report annotated with the recommended actions. + +## type [WilliamsRStrategy]() + +WilliamsRStrategy represents the configuration parameters for calculating the Williams R strategy. + +```go +type WilliamsRStrategy struct { + // WilliamsR represents the configuration parameters for calculating the Williams %R. + WilliamsR *momentum.WilliamsR[float64] + + // BuyAt defines the Williams R level at which a Buy action is generated. + BuyAt float64 + + // SellAt defines the Williams R level at which a Sell action is generated. + SellAt float64 +} +``` + + +### func [NewWilliamsRStrategy]() + +```go +func NewWilliamsRStrategy() *WilliamsRStrategy +``` + +NewWilliamsRStrategy function initializes a new Williams R strategy instance with the default parameters. + + +### func [NewWilliamsRStrategyWith]() + +```go +func NewWilliamsRStrategyWith(buyAt, sellAt float64) *WilliamsRStrategy +``` + +NewWilliamsRStrategyWith function initializes a new Williams R strategy instance with the given parameters. + + +### func \(\*WilliamsRStrategy\) [Compute]() + +```go +func (r *WilliamsRStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action +``` + +Compute processes the provided asset snapshots and generates a stream of actionable recommendations. + + +### func \(\*WilliamsRStrategy\) [Name]() + +```go +func (r *WilliamsRStrategy) Name() string +``` + +Name returns the name of the strategy. + + +### func \(\*WilliamsRStrategy\) [Report]() + +```go +func (r *WilliamsRStrategy) Report(c <-chan *asset.Snapshot) *helper.Report +``` + +Report processes the provided asset snapshots and generates a report annotated with the recommended actions. + Generated by [gomarkdoc]() diff --git a/strategy/volume/README.md b/strategy/volume/README.md index 3cb5e8c8..5433b895 100644 --- a/strategy/volume/README.md +++ b/strategy/volume/README.md @@ -56,6 +56,12 @@ The information provided on this project is strictly for informational purposes - [func \(n \*NegativeVolumeIndexStrategy\) Compute\(snapshots \<\-chan \*asset.Snapshot\) \<\-chan strategy.Action](<#NegativeVolumeIndexStrategy.Compute>) - [func \(n \*NegativeVolumeIndexStrategy\) Name\(\) string](<#NegativeVolumeIndexStrategy.Name>) - [func \(n \*NegativeVolumeIndexStrategy\) Report\(c \<\-chan \*asset.Snapshot\) \*helper.Report](<#NegativeVolumeIndexStrategy.Report>) +- [type ObvStrategy](<#ObvStrategy>) + - [func NewObvStrategy\(\) \*ObvStrategy](<#NewObvStrategy>) + - [func NewObvStrategyWith\(period int\) \*ObvStrategy](<#NewObvStrategyWith>) + - [func \(s \*ObvStrategy\) Compute\(snapshots \<\-chan \*asset.Snapshot\) \<\-chan strategy.Action](<#ObvStrategy.Compute>) + - [func \(s \*ObvStrategy\) Name\(\) string](<#ObvStrategy.Name>) + - [func \(s \*ObvStrategy\) Report\(snapshots \<\-chan \*asset.Snapshot\) \*helper.Report](<#ObvStrategy.Report>) - [type PercentBandMFIStrategy](<#PercentBandMFIStrategy>) - [func NewPercentBandMFIStrategy\(\) \*PercentBandMFIStrategy](<#NewPercentBandMFIStrategy>) - [func NewPercentBandMFIStrategyWith\(sellPercentBAt, buyPercentBAt, sellMfiAt, buyMfiAt float64\) \*PercentBandMFIStrategy](<#NewPercentBandMFIStrategyWith>) @@ -111,6 +117,15 @@ const ( ) ``` + + +```go +const ( + // DefaultObvStrategyPeriod is the default OBV strategy period. + DefaultObvStrategyPeriod = 10 +) +``` + ## func [AllStrategies]() @@ -414,6 +429,66 @@ func (n *NegativeVolumeIndexStrategy) Report(c <-chan *asset.Snapshot) *helper.R Report processes the provided asset snapshots and generates a report annotated with the recommended actions. + +## type [ObvStrategy]() + +ObvStrategy represents the configuration parameters for calculating the On\-Balance Volume \(OBV\) strategy. Recommends a Buy action when OBV crosses above its SMA, and recommends a Sell action when OBV crosses below its SMA. + +```go +type ObvStrategy struct { + // Obv is the OBV indicator instance. + Obv *volume.Obv[float64] + + // Sma is the SMA indicator instance. + Sma *trend.Sma[float64] +} +``` + + +### func [NewObvStrategy]() + +```go +func NewObvStrategy() *ObvStrategy +``` + +NewObvStrategy function initializes a new OBV strategy instance with the default parameters. + + +### func [NewObvStrategyWith]() + +```go +func NewObvStrategyWith(period int) *ObvStrategy +``` + +NewObvStrategyWith function initializes a new OBV strategy instance with the given period. + + +### func \(\*ObvStrategy\) [Compute]() + +```go +func (s *ObvStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action +``` + +Compute function processes the provided asset snapshots and generates a stream of actionable recommendations. + + +### func \(\*ObvStrategy\) [Name]() + +```go +func (s *ObvStrategy) Name() string +``` + +Name function returns the name of the strategy. + + +### func \(\*ObvStrategy\) [Report]() + +```go +func (s *ObvStrategy) Report(snapshots <-chan *asset.Snapshot) *helper.Report +``` + +Report function processes the provided asset snapshots and generates a report annotated with the recommended actions. + ## type [PercentBandMFIStrategy]() diff --git a/strategy/volume/obv_strategy.go b/strategy/volume/obv_strategy.go new file mode 100644 index 00000000..38c903ee --- /dev/null +++ b/strategy/volume/obv_strategy.go @@ -0,0 +1,140 @@ +// Copyright (c) 2021-2026 Onur Cinar. +// The source code is provided under GNU AGPLv3 License. +// https://github.com/cinar/indicator + +package volume + +import ( + "fmt" + + "github.com/cinar/indicator/v2/asset" + "github.com/cinar/indicator/v2/helper" + "github.com/cinar/indicator/v2/strategy" + "github.com/cinar/indicator/v2/trend" + "github.com/cinar/indicator/v2/volume" +) + +const ( + // DefaultObvStrategyPeriod is the default OBV strategy period. + DefaultObvStrategyPeriod = 10 +) + +// ObvStrategy represents the configuration parameters for calculating the On-Balance Volume (OBV) strategy. +// Recommends a Buy action when OBV crosses above its SMA, and recommends a Sell action when OBV crosses below its SMA. +type ObvStrategy struct { + // Obv is the OBV indicator instance. + Obv *volume.Obv[float64] + + // Sma is the SMA indicator instance. + Sma *trend.Sma[float64] +} + +// NewObvStrategy function initializes a new OBV strategy instance with the default parameters. +func NewObvStrategy() *ObvStrategy { + return NewObvStrategyWith( + DefaultObvStrategyPeriod, + ) +} + +// NewObvStrategyWith function initializes a new OBV strategy instance with the given period. +func NewObvStrategyWith(period int) *ObvStrategy { + return &ObvStrategy{ + Obv: volume.NewObv[float64](), + Sma: trend.NewSmaWithPeriod[float64](period), + } +} + +// Name function returns the name of the strategy. +func (s *ObvStrategy) Name() string { + return fmt.Sprintf("OBV Strategy (%d)", s.Sma.Period) +} + +// Compute function processes the provided asset snapshots and generates a stream of actionable recommendations. +func (s *ObvStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action { + snapshotsSplice := helper.Duplicate(snapshots, 2) + + closings := asset.SnapshotsAsClosings(snapshotsSplice[0]) + volumes := asset.SnapshotsAsVolumes(snapshotsSplice[1]) + + obvValues := s.Obv.Compute(closings, volumes) + obvSplice := helper.Duplicate(obvValues, 2) + + smaValues := s.Sma.Compute(obvSplice[0]) + + // Align OBV with SMA + obvValuesAligned := helper.Skip(obvSplice[1], s.Sma.IdlePeriod()) + + actions := helper.Operate(obvValuesAligned, smaValues, func(obv, sma float64) strategy.Action { + if obv > sma { + return strategy.Buy + } + + if obv < sma { + return strategy.Sell + } + + return strategy.Hold + }) + + // OBV starts after its idle period (0), but SMA starts after its idle period. + actions = helper.Shift(actions, s.Sma.IdlePeriod(), strategy.Hold) + + return actions +} + +// Report function processes the provided asset snapshots and generates a report annotated with the recommended actions. +func (s *ObvStrategy) Report(snapshots <-chan *asset.Snapshot) *helper.Report { + // + // snapshots[0] -> dates + // snapshots[1] -> closings (for report) + // snapshots[2] -> closings (for obv) + // snapshots[3] -> volumes (for obv) + // snapshots[4] -> actions / outcomes + // + snapshotsSplice := helper.Duplicate(snapshots, 5) + + dates := helper.Skip( + asset.SnapshotsAsDates(snapshotsSplice[0]), + s.Sma.IdlePeriod(), + ) + + closingsForReport := helper.Duplicate( + helper.Skip( + asset.SnapshotsAsClosings(snapshotsSplice[1]), + s.Sma.IdlePeriod(), + ), + 2, + ) + + closingsForObv := asset.SnapshotsAsClosings(snapshotsSplice[2]) + volumesForObv := asset.SnapshotsAsVolumes(snapshotsSplice[3]) + + obvValues := s.Obv.Compute(closingsForObv, volumesForObv) + obvSplice := helper.Duplicate(obvValues, 2) + + smaValues := s.Sma.Compute(obvSplice[0]) + obvValuesAligned := helper.Skip(obvSplice[1], s.Sma.IdlePeriod()) + + actions, outcomes := strategy.ComputeWithOutcome(s, snapshotsSplice[4]) + actions = helper.Skip(actions, s.Sma.IdlePeriod()) + outcomes = helper.Skip(outcomes, s.Sma.IdlePeriod()) + + annotations := strategy.ActionsToAnnotations(actions) + outcomes = helper.MultiplyBy(outcomes, 100) + + report := helper.NewReport(s.Name(), dates) + report.AddChart() + report.AddChart() + + report.AddColumn(helper.NewNumericReportColumn("Close", closingsForReport[0])) + + report.AddColumn(helper.NewNumericReportColumn("Close", closingsForReport[1]), 1) + report.AddColumn(helper.NewNumericReportColumn("OBV", obvValuesAligned), 1) + report.AddColumn(helper.NewNumericReportColumn("SMA", smaValues), 1) + + report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1) + + report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 2) + + return report +} diff --git a/strategy/volume/obv_strategy_test.go b/strategy/volume/obv_strategy_test.go new file mode 100644 index 00000000..8e5f1da7 --- /dev/null +++ b/strategy/volume/obv_strategy_test.go @@ -0,0 +1,77 @@ +// Copyright (c) 2021-2026 Onur Cinar. +// The source code is provided under GNU AGPLv3 License. +// https://github.com/cinar/indicator + +package volume_test + +import ( + "testing" + + "github.com/cinar/indicator/v2/asset" + "github.com/cinar/indicator/v2/helper" + "github.com/cinar/indicator/v2/strategy" + "github.com/cinar/indicator/v2/strategy/volume" +) + +func TestObvStrategy(t *testing.T) { + snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv") + if err != nil { + t.Fatal(err) + } + + results, err := helper.ReadFromCsvFile[strategy.Result]("testdata/obv_strategy.csv") + if err != nil { + t.Fatal(err) + } + + expected := helper.Map(results, func(r *strategy.Result) strategy.Action { return r.Action }) + + obv := volume.NewObvStrategy() + actual := obv.Compute(snapshots) + + err = helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} + +func TestObvStrategyHold(t *testing.T) { + // A mock setup where OBV equals SMA to test the Hold branch in Compute. + // SMA of [10, 10] is 10. So if current OBV is 10, it's a Hold. + snapshots := helper.SliceToChan([]*asset.Snapshot{ + {Close: 10, Volume: 10}, + {Close: 10, Volume: 0}, + }) + + // 2-period SMA of OBV + s := volume.NewObvStrategyWith(2) + actions := s.Compute(snapshots) + + // Shift(actions, 1, Hold) -> first is Hold. + // Second: OBV is 10, SMA is 10. OBV == SMA -> Hold. + expected := []strategy.Action{strategy.Hold, strategy.Hold} + + err := helper.CheckEquals(actions, helper.SliceToChan(expected)) + if err != nil { + t.Fatal(err) + } +} + +func TestObvStrategyReport(t *testing.T) { + snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv") + if err != nil { + t.Fatal(err) + } + + obv := volume.NewObvStrategy() + + report := obv.Report(snapshots) + + fileName := "obv_strategy.html" + defer helper.Remove(t, fileName) + + err = report.WriteToFile(fileName) + if err != nil { + t.Fatal(err) + } +} diff --git a/strategy/volume/testdata/obv_strategy.csv b/strategy/volume/testdata/obv_strategy.csv new file mode 100644 index 00000000..ac4ba7f4 --- /dev/null +++ b/strategy/volume/testdata/obv_strategy.csv @@ -0,0 +1,252 @@ +Action +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +-1 +-1 +-1 +-1 +1 +-1 +1 +-1 +-1 +1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +1 +1 +-1 +-1 +1 +-1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +-1 +-1 +1 +1 +-1 +-1 +-1 +-1 +1 +1 +1 +1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +-1 +1 +1 +1 +1 +1 +1 +-1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +1 +1 +-1 +-1 +1 +1 +1 +1 +-1 +1 +1 +1 +1 +-1 +1 +-1 +1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +-1 +1 +1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-1 +-1 diff --git a/strategy/volume/volume.go b/strategy/volume/volume.go index 2aec14f2..f5e46dd9 100644 --- a/strategy/volume/volume.go +++ b/strategy/volume/volume.go @@ -30,6 +30,7 @@ func AllStrategies() []strategy.Strategy { NewForceIndexStrategy(), NewMoneyFlowIndexStrategy(), NewNegativeVolumeIndexStrategy(), + NewObvStrategy(), NewWeightedAveragePriceStrategy(), } } diff --git a/strategy/volume/volume_test.go b/strategy/volume/volume_test.go index 8fd717bb..eeca1da4 100644 --- a/strategy/volume/volume_test.go +++ b/strategy/volume/volume_test.go @@ -12,7 +12,7 @@ import ( func TestAllStrategies(t *testing.T) { strategies := volume.AllStrategies() - if len(strategies) != 6 { - t.Fatalf("expected 6 strategies, got %d", len(strategies)) + if len(strategies) != 7 { + t.Fatalf("expected 7 strategies, got %d", len(strategies)) } } diff --git a/volume/README.md b/volume/README.md index 8eb070aa..1b3b9c9f 100644 --- a/volume/README.md +++ b/volume/README.md @@ -712,7 +712,7 @@ func (*Obv[T]) Compute(closings, volumes <-chan T) <-chan T Compute function takes a channel of numbers and computes the OBV. -### func \(\*Obv\[T\]\) [IdlePeriod]() +### func \(\*Obv\[T\]\) [IdlePeriod]() ```go func (*Obv[T]) IdlePeriod() int diff --git a/volume/obv.go b/volume/obv.go index 99b36743..b07185da 100644 --- a/volume/obv.go +++ b/volume/obv.go @@ -27,19 +27,21 @@ func NewObv[T helper.Number]() *Obv[T] { // Compute function takes a channel of numbers and computes the OBV. func (*Obv[T]) Compute(closings, volumes <-chan T) <-chan T { - var previous T + var previousClosing T + var previousObv T return helper.Operate(closings, volumes, func(closing, volume T) T { - current := previous + currentObv := previousObv - if closing > previous { - current += volume - } else if closing < previous { - current -= volume + if closing > previousClosing { + currentObv += volume + } else if closing < previousClosing { + currentObv -= volume } - previous = current - return current + previousClosing = closing + previousObv = currentObv + return currentObv }) } diff --git a/volume/testdata/obv.csv b/volume/testdata/obv.csv index f3c2b576..c7581443 100644 --- a/volume/testdata/obv.csv +++ b/volume/testdata/obv.csv @@ -1,252 +1,252 @@ Close,Volume,Obv 318.600006,7919700,7919700.00 315.839996,4351600,3568100.00 -316.149994,3025700,542400.00 -310.570007,3835800,-3293400.00 -307.779999,3877400,584000.00 -305.820007,4130800,-3546800.00 -305.98999,2351700,-1195100.00 -306.390015,3326000,2130900.00 -311.450012,4366700,-2235800.00 -312.329987,5042800,2807000.00 -309.290009,4056900,-1249900.00 -301.910004,5103900,3854000.00 -300,8305700,-4451700.00 -300.029999,3842200,-609500.00 -302,3090700,2481200.00 -307.820007,3264600,-783400.00 -302.690002,3560100,2776700.00 -306.48999,2460400,316300.00 -305.549988,2730900,-2414600.00 -303.429993,2628200,213600.00 -309.059998,2846200,-2632600.00 -308.899994,3298300,665700.00 -309.910004,3549900,-2884200.00 -314.549988,5121200,2237000.00 -312.899994,3416300,-1179300.00 -318.690002,3647900,2468600.00 -315.529999,4397400,-1928800.00 -316.350006,3049100,1120300.00 -320.369995,2999500,-1879200.00 -318.929993,3070300,1191100.00 -317.640015,2773000,-1581900.00 -314.859985,3478900,1897000.00 -308.299988,3406000,-1509000.00 -305.230011,3614600,2105600.00 -309.869995,3770100,-1664500.00 -310.420013,3086700,1422200.00 -311.299988,2234300,-812100.00 -311.899994,2299800,1487700.00 -310.950012,2856600,-1368900.00 -309.170013,3031200,1662300.00 -307.329987,3474600,-1812300.00 -311.519989,3653400,1841100.00 -310.570007,3518300,-1677200.00 -311.859985,4421400,2744200.00 -308.51001,5385700,-2641500.00 -308.429993,2973100,331600.00 -312.970001,3786700,-3455100.00 -308.480011,3370000,-85100.00 -307.209991,3461200,3376100.00 -309.890015,2808000,568100.00 -313.73999,3261500,-2693400.00 -310.790009,2907100,213700.00 -309.630005,2410700,-2197000.00 -308.179993,2801700,604700.00 -308.23999,2720500,-2115800.00 -302.720001,4131100,2015300.00 -303.160004,2899500,-884200.00 -303.070007,2736400,1852200.00 -304.019989,3656200,-1804000.00 -304.660004,3652200,1848200.00 -305.179993,4736800,-2888600.00 -304.619995,3397200,508600.00 -307.75,3152100,-2643500.00 -312.450012,4493000,1849500.00 -316.970001,4889800,-3040300.00 -311.119995,3609700,569400.00 -311.369995,2701600,-2132200.00 -304.820007,3929500,1797300.00 -303.630005,5294800,-3497500.00 -302.880005,4993000,1495500.00 -305.329987,5251500,-3756000.00 -297.880005,7162800,3406800.00 -302.01001,6325700,-2918900.00 -293.51001,15609400,12690500.00 -301.059998,6056000,6634500.00 -303.850006,4724000,1910500.00 -299.730011,3086300,-1175800.00 -298.369995,4015800,2840000.00 -298.920013,3905400,-1065400.00 -302.140015,3833900,2768500.00 -302.320007,2436500,332000.00 -305.299988,2650000,-2318000.00 -305.079987,2694000,376000.00 -308.769989,5020200,-4644200.00 -310.309998,4862300,218100.00 -309.070007,2740300,-2522200.00 -310.390015,2314500,-207700.00 -312.51001,3131400,2923700.00 -312.619995,2330900,592800.00 -313.700012,3109500,-2516700.00 -314.549988,2662600,145900.00 -318.049988,3323300,-3177400.00 -319.73999,2975400,-202000.00 -323.790009,3425500,3223500.00 -324.630005,3581200,-357700.00 -323.089996,2406200,2048500.00 -323.820007,2428400,-379900.00 -324.329987,2405700,2025800.00 -326.049988,2261900,-236100.00 -324.339996,2552200,2316100.00 -320.529999,2718600,-402500.00 -326.230011,2950000,2547500.00 -328.549988,2909600,-362100.00 -330.170013,2461300,2099200.00 -325.859985,3366500,-1267300.00 -323.220001,2653800,1386500.00 -320,3185600,-1799100.00 -323.880005,3869500,2070400.00 -326.140015,3302400,-1232000.00 -324.869995,2283400,1051400.00 -322.98999,2639800,-1588400.00 -322.640015,2548900,960500.00 -322.48999,1937300,-976800.00 -323.529999,2190000,1213200.00 -323.75,2139500,-926300.00 -327.390015,3046800,2120500.00 -329.76001,2805000,-684500.00 -330.390015,4322900,3638400.00 -329.130005,2762500,875900.00 -323.109985,4029300,-3153400.00 -320.200012,3071500,-81900.00 -319.019989,4245400,4163500.00 -320.600006,3229400,934100.00 -322.190002,3231800,-2297700.00 -321.079987,6175000,3877300.00 -323.119995,3375300,502000.00 -329.480011,3962200,-3460200.00 -328.579987,3091800,-368400.00 -333.410004,3181400,2813000.00 -335.420013,3727800,-914800.00 -335.950012,2759300,1844500.00 -335.290009,2619200,-774700.00 -333.600006,2873400,2098700.00 -336.390015,2953000,-854300.00 -335.899994,5164600,4310300.00 -339.820007,4095200,215100.00 -338.309998,8486200,-8271100.00 -338.670013,3751700,-4519400.00 -338.609985,4507000,-12400.00 -336.959991,3303300,3290900.00 -335.25,4451700,-1160800.00 -334.119995,3220900,2060100.00 -335.339996,2625600,-565500.00 -334.149994,3175100,2609600.00 -336.910004,2498900,110700.00 -341,4520600,-4409900.00 -342,2047400,-2362500.00 -341.559998,2870700,508200.00 -341.459991,2548300,-2040100.00 -340.899994,2940800,900700.00 -341.130005,2966500,-2065800.00 -343.369995,2754900,689100.00 -345.350006,2897100,-2208000.00 -343.540009,2831800,623800.00 -341.089996,2669300,-2045500.00 -344.25,2359500,314000.00 -345.339996,2565300,-2251300.00 -342.429993,3032100,780800.00 -346.609985,3146000,-2365200.00 -345.76001,3301900,936700.00 -349.630005,3269400,-2332700.00 -347.579987,3014000,681300.00 -349.799988,2682900,-2001600.00 -349.309998,2706700,705100.00 -349.809998,2473300,-1768200.00 -351.959991,2621600,853400.00 -352.26001,2293300,-1439900.00 -351.190002,3085900,1646000.00 -353.809998,2942000,-1296000.00 -349.98999,2842000,1546000.00 -362.579987,5379900,-3833900.00 -363.730011,3428800,-405100.00 -358.019989,4424600,4019500.00 -356.980011,3098800,920700.00 -358.350006,2475200,-1554500.00 -358.480011,1990700,436200.00 -354.5,2863700,-2427500.00 -354.109985,2196100,-231400.00 -353.190002,2847700,2616300.00 -352.559998,2870600,-254300.00 -352.089996,2540000,2285700.00 -350.570007,2363300,-77600.00 -354.26001,2239500,2161900.00 -354.299988,2521100,-359200.00 -355.929993,2136800,1777600.00 -355.549988,1728000,49600.00 -358.290009,2285600,-2236000.00 -361.059998,3058300,822300.00 -360.200012,2842300,-2020000.00 -362.459991,2637900,617900.00 -360.470001,2976800,-2358900.00 -361.670013,2655800,296900.00 -361.799988,3263800,-2966900.00 -363.149994,3019100,52200.00 -365.519989,2921600,-2869400.00 -367.779999,2898400,29000.00 -367.820007,3261400,-3232400.00 -369.5,3670100,437700.00 -367.859985,11595000,-11157300.00 -370.429993,3130900,-8026400.00 -370.480011,2603700,-5422700.00 -366.820007,2268400,-3154300.00 -363.279999,3178600,24300.00 -360.160004,3969400,-3945100.00 -361.709991,2556200,-1388900.00 -359.420013,3063900,1675000.00 -357.779999,3535400,-1860400.00 -357.059998,2731700,871300.00 -350.299988,4932900,-4061600.00 -348.079987,3527600,-534000.00 -343.040009,3151700,2617700.00 -343.690002,3244600,-626900.00 -345.059998,3027300,2400400.00 -346.339996,3174700,-774300.00 -345.450012,2762800,1988500.00 -348.559998,2858600,-870100.00 -348.429993,2620800,1750700.00 -345.660004,2677500,-926800.00 -345.089996,2804800,1878000.00 -346.230011,3117800,-1239800.00 -345.390015,2998600,1758800.00 -340.890015,2977100,-1218300.00 -338.660004,2741300,1523000.00 -335.859985,3466100,-1943100.00 -336.839996,2794200,851100.00 -338.630005,2355700,-1504600.00 -336.899994,2623200,1118600.00 -336.160004,2685400,-1566800.00 -331.709991,3608200,2041400.00 -337.410004,2634700,-593300.00 -341.329987,3066900,2473600.00 -343.75,2789700,-316100.00 -349.019989,3433700,3117600.00 -351.809998,4409100,-1291500.00 -346.630005,5486200,4194700.00 -346.170013,3062900,1131800.00 -346.299988,2602400,-1470600.00 -348.179993,3052100,1581500.00 -350.559998,3701100,-2119600.00 -350.01001,2196200,76600.00 -354.25,3387500,-3310900.00 -356.790009,3572900,262000.00 -359.859985,2822500,-2560500.00 -358.929993,3260000,699500.00 -361.329987,3215300,-2515800.00 -361,2918800,403000.00 -361.799988,2110200,-1707200.00 -362.679993,1282000,-425200.00 -361.339996,2580300,2155100.00 -360.049988,2953500,-798400.00 -358.690002,3141100,2342700.00 +316.149994,3025700,6593800.00 +310.570007,3835800,2758000.00 +307.779999,3877400,-1119400.00 +305.820007,4130800,-5250200.00 +305.98999,2351700,-2898500.00 +306.390015,3326000,427500.00 +311.450012,4366700,4794200.00 +312.329987,5042800,9837000.00 +309.290009,4056900,5780100.00 +301.910004,5103900,676200.00 +300,8305700,-7629500.00 +300.029999,3842200,-3787300.00 +302,3090700,-696600.00 +307.820007,3264600,2568000.00 +302.690002,3560100,-992100.00 +306.48999,2460400,1468300.00 +305.549988,2730900,-1262600.00 +303.429993,2628200,-3890800.00 +309.059998,2846200,-1044600.00 +308.899994,3298300,-4342900.00 +309.910004,3549900,-793000.00 +314.549988,5121200,4328200.00 +312.899994,3416300,911900.00 +318.690002,3647900,4559800.00 +315.529999,4397400,162400.00 +316.350006,3049100,3211500.00 +320.369995,2999500,6211000.00 +318.929993,3070300,3140700.00 +317.640015,2773000,367700.00 +314.859985,3478900,-3111200.00 +308.299988,3406000,-6517200.00 +305.230011,3614600,-10131800.00 +309.869995,3770100,-6361700.00 +310.420013,3086700,-3275000.00 +311.299988,2234300,-1040700.00 +311.899994,2299800,1259100.00 +310.950012,2856600,-1597500.00 +309.170013,3031200,-4628700.00 +307.329987,3474600,-8103300.00 +311.519989,3653400,-4449900.00 +310.570007,3518300,-7968200.00 +311.859985,4421400,-3546800.00 +308.51001,5385700,-8932500.00 +308.429993,2973100,-11905600.00 +312.970001,3786700,-8118900.00 +308.480011,3370000,-11488900.00 +307.209991,3461200,-14950100.00 +309.890015,2808000,-12142100.00 +313.73999,3261500,-8880600.00 +310.790009,2907100,-11787700.00 +309.630005,2410700,-14198400.00 +308.179993,2801700,-17000100.00 +308.23999,2720500,-14279600.00 +302.720001,4131100,-18410700.00 +303.160004,2899500,-15511200.00 +303.070007,2736400,-18247600.00 +304.019989,3656200,-14591400.00 +304.660004,3652200,-10939200.00 +305.179993,4736800,-6202400.00 +304.619995,3397200,-9599600.00 +307.75,3152100,-6447500.00 +312.450012,4493000,-1954500.00 +316.970001,4889800,2935300.00 +311.119995,3609700,-674400.00 +311.369995,2701600,2027200.00 +304.820007,3929500,-1902300.00 +303.630005,5294800,-7197100.00 +302.880005,4993000,-12190100.00 +305.329987,5251500,-6938600.00 +297.880005,7162800,-14101400.00 +302.01001,6325700,-7775700.00 +293.51001,15609400,-23385100.00 +301.059998,6056000,-17329100.00 +303.850006,4724000,-12605100.00 +299.730011,3086300,-15691400.00 +298.369995,4015800,-19707200.00 +298.920013,3905400,-15801800.00 +302.140015,3833900,-11967900.00 +302.320007,2436500,-9531400.00 +305.299988,2650000,-6881400.00 +305.079987,2694000,-9575400.00 +308.769989,5020200,-4555200.00 +310.309998,4862300,307100.00 +309.070007,2740300,-2433200.00 +310.390015,2314500,-118700.00 +312.51001,3131400,3012700.00 +312.619995,2330900,5343600.00 +313.700012,3109500,8453100.00 +314.549988,2662600,11115700.00 +318.049988,3323300,14439000.00 +319.73999,2975400,17414400.00 +323.790009,3425500,20839900.00 +324.630005,3581200,24421100.00 +323.089996,2406200,22014900.00 +323.820007,2428400,24443300.00 +324.329987,2405700,26849000.00 +326.049988,2261900,29110900.00 +324.339996,2552200,26558700.00 +320.529999,2718600,23840100.00 +326.230011,2950000,26790100.00 +328.549988,2909600,29699700.00 +330.170013,2461300,32161000.00 +325.859985,3366500,28794500.00 +323.220001,2653800,26140700.00 +320,3185600,22955100.00 +323.880005,3869500,26824600.00 +326.140015,3302400,30127000.00 +324.869995,2283400,27843600.00 +322.98999,2639800,25203800.00 +322.640015,2548900,22654900.00 +322.48999,1937300,20717600.00 +323.529999,2190000,22907600.00 +323.75,2139500,25047100.00 +327.390015,3046800,28093900.00 +329.76001,2805000,30898900.00 +330.390015,4322900,35221800.00 +329.130005,2762500,32459300.00 +323.109985,4029300,28430000.00 +320.200012,3071500,25358500.00 +319.019989,4245400,21113100.00 +320.600006,3229400,24342500.00 +322.190002,3231800,27574300.00 +321.079987,6175000,21399300.00 +323.119995,3375300,24774600.00 +329.480011,3962200,28736800.00 +328.579987,3091800,25645000.00 +333.410004,3181400,28826400.00 +335.420013,3727800,32554200.00 +335.950012,2759300,35313500.00 +335.290009,2619200,32694300.00 +333.600006,2873400,29820900.00 +336.390015,2953000,32773900.00 +335.899994,5164600,27609300.00 +339.820007,4095200,31704500.00 +338.309998,8486200,23218300.00 +338.670013,3751700,26970000.00 +338.609985,4507000,22463000.00 +336.959991,3303300,19159700.00 +335.25,4451700,14708000.00 +334.119995,3220900,11487100.00 +335.339996,2625600,14112700.00 +334.149994,3175100,10937600.00 +336.910004,2498900,13436500.00 +341,4520600,17957100.00 +342,2047400,20004500.00 +341.559998,2870700,17133800.00 +341.459991,2548300,14585500.00 +340.899994,2940800,11644700.00 +341.130005,2966500,14611200.00 +343.369995,2754900,17366100.00 +345.350006,2897100,20263200.00 +343.540009,2831800,17431400.00 +341.089996,2669300,14762100.00 +344.25,2359500,17121600.00 +345.339996,2565300,19686900.00 +342.429993,3032100,16654800.00 +346.609985,3146000,19800800.00 +345.76001,3301900,16498900.00 +349.630005,3269400,19768300.00 +347.579987,3014000,16754300.00 +349.799988,2682900,19437200.00 +349.309998,2706700,16730500.00 +349.809998,2473300,19203800.00 +351.959991,2621600,21825400.00 +352.26001,2293300,24118700.00 +351.190002,3085900,21032800.00 +353.809998,2942000,23974800.00 +349.98999,2842000,21132800.00 +362.579987,5379900,26512700.00 +363.730011,3428800,29941500.00 +358.019989,4424600,25516900.00 +356.980011,3098800,22418100.00 +358.350006,2475200,24893300.00 +358.480011,1990700,26884000.00 +354.5,2863700,24020300.00 +354.109985,2196100,21824200.00 +353.190002,2847700,18976500.00 +352.559998,2870600,16105900.00 +352.089996,2540000,13565900.00 +350.570007,2363300,11202600.00 +354.26001,2239500,13442100.00 +354.299988,2521100,15963200.00 +355.929993,2136800,18100000.00 +355.549988,1728000,16372000.00 +358.290009,2285600,18657600.00 +361.059998,3058300,21715900.00 +360.200012,2842300,18873600.00 +362.459991,2637900,21511500.00 +360.470001,2976800,18534700.00 +361.670013,2655800,21190500.00 +361.799988,3263800,24454300.00 +363.149994,3019100,27473400.00 +365.519989,2921600,30395000.00 +367.779999,2898400,33293400.00 +367.820007,3261400,36554800.00 +369.5,3670100,40224900.00 +367.859985,11595000,28629900.00 +370.429993,3130900,31760800.00 +370.480011,2603700,34364500.00 +366.820007,2268400,32096100.00 +363.279999,3178600,28917500.00 +360.160004,3969400,24948100.00 +361.709991,2556200,27504300.00 +359.420013,3063900,24440400.00 +357.779999,3535400,20905000.00 +357.059998,2731700,18173300.00 +350.299988,4932900,13240400.00 +348.079987,3527600,9712800.00 +343.040009,3151700,6561100.00 +343.690002,3244600,9805700.00 +345.059998,3027300,12833000.00 +346.339996,3174700,16007700.00 +345.450012,2762800,13244900.00 +348.559998,2858600,16103500.00 +348.429993,2620800,13482700.00 +345.660004,2677500,10805200.00 +345.089996,2804800,8000400.00 +346.230011,3117800,11118200.00 +345.390015,2998600,8119600.00 +340.890015,2977100,5142500.00 +338.660004,2741300,2401200.00 +335.859985,3466100,-1064900.00 +336.839996,2794200,1729300.00 +338.630005,2355700,4085000.00 +336.899994,2623200,1461800.00 +336.160004,2685400,-1223600.00 +331.709991,3608200,-4831800.00 +337.410004,2634700,-2197100.00 +341.329987,3066900,869800.00 +343.75,2789700,3659500.00 +349.019989,3433700,7093200.00 +351.809998,4409100,11502300.00 +346.630005,5486200,6016100.00 +346.170013,3062900,2953200.00 +346.299988,2602400,5555600.00 +348.179993,3052100,8607700.00 +350.559998,3701100,12308800.00 +350.01001,2196200,10112600.00 +354.25,3387500,13500100.00 +356.790009,3572900,17073000.00 +359.859985,2822500,19895500.00 +358.929993,3260000,16635500.00 +361.329987,3215300,19850800.00 +361,2918800,16932000.00 +361.799988,2110200,19042200.00 +362.679993,1282000,20324200.00 +361.339996,2580300,17743900.00 +360.049988,2953500,14790400.00 +358.690002,3141100,11649300.00