From 47aafaa3188926979b01823e6e2406b2f6d07eb6 Mon Sep 17 00:00:00 2001 From: Onur Cinar Date: Sat, 23 Dec 2023 07:32:21 -0800 Subject: [PATCH] Apo strategy implementing the strategy interface. --- strategy/apo_strategy.go | 70 ++-- strategy/apo_strategy_test.go | 41 ++- strategy/testdata/apo_strategy.csv | 504 ++++++++++++++--------------- strategy/testdata/brk-b.csv | 252 +++++++++++++++ 4 files changed, 571 insertions(+), 296 deletions(-) create mode 100644 strategy/testdata/brk-b.csv diff --git a/strategy/apo_strategy.go b/strategy/apo_strategy.go index d653a90..edcc371 100644 --- a/strategy/apo_strategy.go +++ b/strategy/apo_strategy.go @@ -7,6 +7,7 @@ package strategy import ( "time" + "github.com/cinar/indicator/asset" "github.com/cinar/indicator/helper" "github.com/cinar/indicator/trend" ) @@ -15,23 +16,32 @@ import ( // An APO value crossing above zero suggests a bullish trend, while crossing below zero // indicates a bearish trend. Positive APO values signify an upward trend, while // negative values signify a downward trend. -type ApoStrategy[T helper.Number] struct { +type ApoStrategy struct { // Apo represents the configuration parameters for calculating the // Absolute Price Oscillator (APO). - Apo *trend.Apo[T] + Apo *trend.Apo[float64] } // NewApoStrategy function initializes a new APO strategy instance with the default parameters. -func NewApoStrategy[T helper.Number]() *ApoStrategy[T] { - return &ApoStrategy[T]{ - Apo: trend.NewApo[T](), +func NewApoStrategy() *ApoStrategy { + return &ApoStrategy{ + Apo: trend.NewApo[float64](), } } -// Compute uses the given values as input and returns a channel of -// action recommendations. -func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action { - apo := a.Apo.Compute(c) +// Name returns the name of the strategy. +func (a *ApoStrategy) Name() string { + return "Apo Strategy" +} + +// Compute processes the provided asset snapshots and generates a +// stream of actionable recommendations, +func (a *ApoStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan Action { + closing := helper.Map(snapshots, func(snapshot *asset.Snapshot) float64 { + return snapshot.Close + }) + + apo := a.Apo.Compute(closing) apo = helper.Buffered(apo, 2) inputs := helper.Duplicate(apo, 2) @@ -39,7 +49,7 @@ func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action { // Ship the first value inputs[1] = helper.Skip(inputs[1], 1) - return helper.Shift(helper.Operate(inputs[0], inputs[1], func(b, c T) Action { + return helper.Shift(helper.Operate(inputs[0], inputs[1], func(b, c float64) Action { // An APO value crossing above zero suggests a bullish trend. if c >= 0 && b < 0 { return Buy @@ -54,26 +64,42 @@ func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action { }), 1, Hold) } -// Report takes input channels containing dates and values, computes the recommended actions -// based on the data, and generates a report annotated with those actions. -func (a *ApoStrategy[T]) Report(dates <-chan time.Time, c <-chan T) *helper.Report { - cs := helper.Duplicate(c, 4) +// Report processes the provided asset snapshots and generates a +// report annotated with the recommended actions. +func (a *ApoStrategy) Report(c <-chan *asset.Snapshot) *helper.Report { + // + // snapshots[0] -> dates + // snapshots[1] -> Compute -> actions[0] -> annotations + // -> actions[1] |> outcome + // snapshots[2] -> closings[2] -> | + // -> closings[0] -> close + // -> closings[1] -> Apo.Compute -> apo + // + snapshots := helper.Duplicate(c, 3) + + dates := helper.Map(snapshots[0], func(snapshot *asset.Snapshot) time.Time { + return snapshot.Date + }) + + closings := helper.Duplicate(helper.Map(snapshots[2], func(snapshot *asset.Snapshot) float64 { + return snapshot.Close + }), 3) dates = helper.Skip(dates, a.Apo.SlowPeriod-1) - cs[0] = helper.Skip(cs[0], a.Apo.SlowPeriod-1) - cs[3] = helper.Skip(cs[3], a.Apo.SlowPeriod-1) - apo := a.Apo.Compute(cs[1]) - actions := helper.Duplicate(a.Compute(cs[2]), 2) - annotations := ActionsToAnnotations(actions[0]) + closings[0] = helper.Skip(closings[0], a.Apo.SlowPeriod-1) + closings[2] = helper.Skip(closings[2], a.Apo.SlowPeriod-1) + apo := a.Apo.Compute(closings[1]) - outcome := Outcome(cs[3], actions[1]) + actions := helper.Duplicate(a.Compute(snapshots[1]), 2) + annotations := ActionsToAnnotations(actions[0]) + outcome := Outcome(closings[2], actions[1]) - report := helper.NewReport("APO Strategy", dates) + report := helper.NewReport(a.Name(), dates) report.AddChart() report.AddChart() - report.AddColumn(helper.NewNumericReportColumn("Close", cs[0])) + report.AddColumn(helper.NewNumericReportColumn("Close", closings[0])) report.AddColumn(helper.NewNumericReportColumn("APO", apo), 1) report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1) diff --git a/strategy/apo_strategy_test.go b/strategy/apo_strategy_test.go index 81a2abe..f1ce343 100644 --- a/strategy/apo_strategy_test.go +++ b/strategy/apo_strategy_test.go @@ -5,32 +5,38 @@ package strategy_test import ( + "os" "testing" - "time" + "github.com/cinar/indicator/asset" "github.com/cinar/indicator/helper" "github.com/cinar/indicator/strategy" ) func TestApoStrategy(t *testing.T) { - type Row struct { - Close float64 + type Result struct { Action strategy.Action } - input, err := helper.ReadFromCsvFile[Row]("testdata/apo_strategy.csv", true) + snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv", true) if err != nil { t.Fatal(err) } - inputs := helper.Duplicate(input, 2) - closing := helper.Map(inputs[0], func(row *Row) float64 { return row.Close }) - expected := helper.Map(inputs[1], func(row *Row) strategy.Action { return row.Action }) + results, err := helper.ReadFromCsvFile[Result]("testdata/apo_strategy.csv", true) + if err != nil { + t.Fatal(err) + } + + apo := strategy.NewApoStrategy() + + expected := helper.Map(results, func(r *Result) strategy.Action { + return r.Action + }) - apo := strategy.NewApoStrategy[float64]() expected = helper.Skip(expected, apo.Apo.SlowPeriod-1) - actual := apo.Compute(closing) + actual := apo.Compute(snapshots) err = helper.CheckEquals(actual, expected) if err != nil { @@ -39,26 +45,17 @@ func TestApoStrategy(t *testing.T) { } func TestApoStrategyReport(t *testing.T) { - type Row struct { - Date time.Time `format:"2006-01-02"` - Close float64 - } - - input, err := helper.ReadFromCsvFile[Row]("testdata/apo_strategy.csv", true) + snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv", true) if err != nil { t.Fatal(err) } - inputs := helper.Duplicate(input, 2) - dates := helper.Map(inputs[0], func(row *Row) time.Time { return row.Date }) - closing := helper.Map(inputs[1], func(row *Row) float64 { return row.Close }) - - apo := strategy.NewApoStrategy[float64]() + apo := strategy.NewApoStrategy() - report := apo.Report(dates, closing) + report := apo.Report(snapshots) fileName := "apo_strategy.html" - // defer os.Remove(fileName) + defer os.Remove(fileName) err = report.WriteToFile(fileName) if err != nil { diff --git a/strategy/testdata/apo_strategy.csv b/strategy/testdata/apo_strategy.csv index 5dcddec..abd2664 100644 --- a/strategy/testdata/apo_strategy.csv +++ b/strategy/testdata/apo_strategy.csv @@ -1,252 +1,252 @@ -Date,Close,Action -2022-11-30,318.600006,0 -2022-12-01,315.839996,0 -2022-12-02,316.149994,0 -2022-12-05,310.570007,0 -2022-12-06,307.779999,0 -2022-12-07,305.820007,0 -2022-12-08,305.98999,0 -2022-12-09,306.390015,0 -2022-12-12,311.450012,0 -2022-12-13,312.329987,0 -2022-12-14,309.290009,0 -2022-12-15,301.910004,0 -2022-12-16,300,0 -2022-12-19,300.029999,0 -2022-12-20,302,0 -2022-12-21,307.820007,0 -2022-12-22,302.690002,0 -2022-12-23,306.48999,0 -2022-12-27,305.549988,0 -2022-12-28,303.429993,0 -2022-12-29,309.059998,0 -2022-12-30,308.899994,0 -2023-01-03,309.910004,0 -2023-01-04,314.549988,0 -2023-01-05,312.899994,0 -2023-01-06,318.690002,0 -2023-01-09,315.529999,0 -2023-01-10,316.350006,0 -2023-01-11,320.369995,0 -2023-01-12,318.929993,0 -2023-01-13,317.640015,0 -2023-01-17,314.859985,0 -2023-01-18,308.299988,0 -2023-01-19,305.230011,0 -2023-01-20,309.869995,0 -2023-01-23,310.420013,0 -2023-01-24,311.299988,0 -2023-01-25,311.899994,0 -2023-01-26,310.950012,0 -2023-01-27,309.170013,0 -2023-01-30,307.329987,0 -2023-01-31,311.519989,1 -2023-02-01,310.570007,0 -2023-02-02,311.859985,0 -2023-02-03,308.51001,0 -2023-02-06,308.429993,0 -2023-02-07,312.970001,0 -2023-02-08,308.480011,0 -2023-02-09,307.209991,0 -2023-02-10,309.890015,0 -2023-02-13,313.73999,0 -2023-02-14,310.790009,0 -2023-02-15,309.630005,0 -2023-02-16,308.179993,0 -2023-02-17,308.23999,0 -2023-02-21,302.720001,0 -2023-02-22,303.160004,0 -2023-02-23,303.070007,0 -2023-02-24,304.019989,0 -2023-02-27,304.660004,0 -2023-02-28,305.179993,0 -2023-03-01,304.619995,0 -2023-03-02,307.75,0 -2023-03-03,312.450012,0 -2023-03-06,316.970001,0 -2023-03-07,311.119995,0 -2023-03-08,311.369995,0 -2023-03-09,304.820007,0 -2023-03-10,303.630005,0 -2023-03-13,302.880005,0 -2023-03-14,305.329987,0 -2023-03-15,297.880005,0 -2023-03-16,302.01001,0 -2023-03-17,293.51001,0 -2023-03-20,301.059998,0 -2023-03-21,303.850006,0 -2023-03-22,299.730011,0 -2023-03-23,298.369995,0 -2023-03-24,298.920013,0 -2023-03-27,302.140015,0 -2023-03-28,302.320007,0 -2023-03-29,305.299988,0 -2023-03-30,305.079987,0 -2023-03-31,308.769989,0 -2023-04-03,310.309998,0 -2023-04-04,309.070007,0 -2023-04-05,310.390015,0 -2023-04-06,312.51001,-1 -2023-04-10,312.619995,0 -2023-04-11,313.700012,0 -2023-04-12,314.549988,0 -2023-04-13,318.049988,0 -2023-04-14,319.73999,0 -2023-04-17,323.790009,0 -2023-04-18,324.630005,0 -2023-04-19,323.089996,0 -2023-04-20,323.820007,0 -2023-04-21,324.329987,0 -2023-04-24,326.049988,0 -2023-04-25,324.339996,0 -2023-04-26,320.529999,0 -2023-04-27,326.230011,0 -2023-04-28,328.549988,0 -2023-05-01,330.170013,0 -2023-05-02,325.859985,0 -2023-05-03,323.220001,0 -2023-05-04,320,0 -2023-05-05,323.880005,0 -2023-05-08,326.140015,0 -2023-05-09,324.869995,0 -2023-05-10,322.98999,0 -2023-05-11,322.640015,0 -2023-05-12,322.48999,0 -2023-05-15,323.529999,0 -2023-05-16,323.75,0 -2023-05-17,327.390015,0 -2023-05-18,329.76001,0 -2023-05-19,330.390015,0 -2023-05-22,329.130005,0 -2023-05-23,323.109985,1 -2023-05-24,320.200012,0 -2023-05-25,319.019989,0 -2023-05-26,320.600006,0 -2023-05-30,322.190002,0 -2023-05-31,321.079987,0 -2023-06-01,323.119995,0 -2023-06-02,329.480011,0 -2023-06-05,328.579987,0 -2023-06-06,333.410004,-1 -2023-06-07,335.420013,0 -2023-06-08,335.950012,0 -2023-06-09,335.290009,0 -2023-06-12,333.600006,0 -2023-06-13,336.390015,0 -2023-06-14,335.899994,0 -2023-06-15,339.820007,0 -2023-06-16,338.309998,0 -2023-06-20,338.670013,0 -2023-06-21,338.609985,0 -2023-06-22,336.959991,0 -2023-06-23,335.25,0 -2023-06-26,334.119995,0 -2023-06-27,335.339996,0 -2023-06-28,334.149994,0 -2023-06-29,336.910004,0 -2023-06-30,341,0 -2023-07-03,342,0 -2023-07-05,341.559998,0 -2023-07-06,341.459991,0 -2023-07-07,340.899994,0 -2023-07-10,341.130005,0 -2023-07-11,343.369995,0 -2023-07-12,345.350006,0 -2023-07-13,343.540009,0 -2023-07-14,341.089996,0 -2023-07-17,344.25,0 -2023-07-18,345.339996,0 -2023-07-19,342.429993,0 -2023-07-20,346.609985,0 -2023-07-21,345.76001,0 -2023-07-24,349.630005,0 -2023-07-25,347.579987,0 -2023-07-26,349.799988,0 -2023-07-27,349.309998,0 -2023-07-28,349.809998,0 -2023-07-31,351.959991,0 -2023-08-01,352.26001,0 -2023-08-02,351.190002,0 -2023-08-03,353.809998,0 -2023-08-04,349.98999,0 -2023-08-07,362.579987,0 -2023-08-08,363.730011,0 -2023-08-09,358.019989,0 -2023-08-10,356.980011,0 -2023-08-11,358.350006,0 -2023-08-14,358.480011,0 -2023-08-15,354.5,0 -2023-08-16,354.109985,0 -2023-08-17,353.190002,0 -2023-08-18,352.559998,0 -2023-08-21,352.089996,0 -2023-08-22,350.570007,0 -2023-08-23,354.26001,0 -2023-08-24,354.299988,0 -2023-08-25,355.929993,0 -2023-08-28,355.549988,0 -2023-08-29,358.290009,0 -2023-08-30,361.059998,0 -2023-08-31,360.200012,1 -2023-09-01,362.459991,-1 -2023-09-05,360.470001,1 -2023-09-06,361.670013,0 -2023-09-07,361.799988,-1 -2023-09-08,363.149994,0 -2023-09-11,365.519989,0 -2023-09-12,367.779999,0 -2023-09-13,367.820007,0 -2023-09-14,369.5,0 -2023-09-15,367.859985,0 -2023-09-18,370.429993,0 -2023-09-19,370.480011,0 -2023-09-20,366.820007,0 -2023-09-21,363.279999,0 -2023-09-22,360.160004,0 -2023-09-25,361.709991,0 -2023-09-26,359.420013,0 -2023-09-27,357.779999,0 -2023-09-28,357.059998,0 -2023-09-29,350.299988,0 -2023-10-02,348.079987,1 -2023-10-03,343.040009,0 -2023-10-04,343.690002,0 -2023-10-05,345.059998,0 -2023-10-06,346.339996,0 -2023-10-09,345.450012,0 -2023-10-10,348.559998,0 -2023-10-11,348.429993,0 -2023-10-12,345.660004,0 -2023-10-13,345.089996,0 -2023-10-16,346.230011,0 -2023-10-17,345.390015,0 -2023-10-18,340.890015,0 -2023-10-19,338.660004,0 -2023-10-20,335.859985,0 -2023-10-23,336.839996,0 -2023-10-24,338.630005,0 -2023-10-25,336.899994,0 -2023-10-26,336.160004,0 -2023-10-27,331.709991,0 -2023-10-30,337.410004,0 -2023-10-31,341.329987,0 -2023-11-01,343.75,0 -2023-11-02,349.019989,0 -2023-11-03,351.809998,0 -2023-11-06,346.630005,0 -2023-11-07,346.170013,0 -2023-11-08,346.299988,0 -2023-11-09,348.179993,0 -2023-11-10,350.559998,0 -2023-11-13,350.01001,-1 -2023-11-14,354.25,0 -2023-11-15,356.790009,0 -2023-11-16,359.859985,0 -2023-11-17,358.929993,0 -2023-11-20,361.329987,0 -2023-11-21,361,0 -2023-11-22,361.799988,0 -2023-11-24,362.679993,0 -2023-11-27,361.339996,0 -2023-11-28,360.049988,0 -2023-11-29,358.690002,0 \ No newline at end of file +Action +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +-1 +1 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 \ No newline at end of file diff --git a/strategy/testdata/brk-b.csv b/strategy/testdata/brk-b.csv new file mode 100644 index 0000000..3727711 --- /dev/null +++ b/strategy/testdata/brk-b.csv @@ -0,0 +1,252 @@ +Date,Open,High,Low,Close,Adj Close,Volume +2022-11-30,315.130005,318.600006,308.700012,318.600006,318.600006,7919700 +2022-12-01,319,319.559998,313.299988,315.839996,315.839996,4351600 +2022-12-02,313.48999,316.380005,312.75,316.149994,316.149994,3025700 +2022-12-05,315.220001,315.660004,308.730011,310.570007,310.570007,3835800 +2022-12-06,309.950012,310.290009,306.350006,307.779999,307.779999,3877400 +2022-12-07,307.070007,309.380005,304.920013,305.820007,305.820007,4130800 +2022-12-08,306,307.48999,305.089996,305.98999,305.98999,2351700 +2022-12-09,305.320007,308.339996,304.709991,306.390015,306.390015,3326000 +2022-12-12,307.549988,311.910004,305.459991,311.450012,311.450012,4366700 +2022-12-13,318.399994,318.910004,310.820007,312.329987,312.329987,5042800 +2022-12-14,312.73999,316.359985,308.399994,309.290009,309.290009,4056900 +2022-12-15,306.429993,306.959991,299.450012,301.910004,301.910004,5103900 +2022-12-16,299.049988,302.470001,297.76001,300,300,8305700 +2022-12-19,300.51001,301.480011,297.149994,300.029999,300.029999,3842200 +2022-12-20,300.089996,304.190002,297,302,302,3090700 +2022-12-21,304.380005,308.540009,304.160004,307.820007,307.820007,3264600 +2022-12-22,306.100006,306.5,297.640015,302.690002,302.690002,3560100 +2022-12-23,302.880005,306.570007,300.929993,306.48999,306.48999,2460400 +2022-12-27,306.450012,308.579987,304.649994,305.549988,305.549988,2730900 +2022-12-28,304.769989,307.459991,303.26001,303.429993,303.429993,2628200 +2022-12-29,305.940002,309.380005,305.23999,309.059998,309.059998,2846200 +2022-12-30,306.950012,309.040009,305.619995,308.899994,308.899994,3298300 +2023-01-03,310.070007,312.390015,307.380005,309.910004,309.910004,3549900 +2023-01-04,312,316.890015,311.25,314.549988,314.549988,5121200 +2023-01-05,313.570007,314.230011,310,312.899994,312.899994,3416300 +2023-01-06,315,320.160004,313.380005,318.690002,318.690002,3647900 +2023-01-09,319.019989,320.5,314.75,315.529999,315.529999,4397400 +2023-01-10,315,316.799988,313.339996,316.350006,316.350006,3049100 +2023-01-11,318.519989,320.570007,316.600006,320.369995,320.369995,2999500 +2023-01-12,321.149994,321.320007,317.720001,318.929993,318.929993,3070300 +2023-01-13,317.48999,318.420013,315.790009,317.640015,317.640015,2773000 +2023-01-17,318.399994,318.519989,314.25,314.859985,314.859985,3478900 +2023-01-18,315,315.540009,307.75,308.299988,308.299988,3406000 +2023-01-19,306.119995,307.23999,303.859985,305.230011,305.230011,3614600 +2023-01-20,305.209991,310.01001,304.359985,309.869995,309.869995,3770100 +2023-01-23,309.630005,312.730011,306.850006,310.420013,310.420013,3086700 +2023-01-24,309.299988,312.829987,307.5,311.299988,311.299988,2234300 +2023-01-25,308.329987,312.549988,307.709991,311.899994,311.899994,2299800 +2023-01-26,312.98999,313.679993,309.579987,310.950012,310.950012,2856600 +2023-01-27,309.790009,311.730011,308.339996,309.170013,309.170013,3031200 +2023-01-30,307.600006,309.51001,306.809998,307.329987,307.329987,3474600 +2023-01-31,307.73999,311.859985,305.790009,311.519989,311.519989,3653400 +2023-02-01,309.630005,312.670013,306.380005,310.570007,310.570007,3518300 +2023-02-02,312.350006,312.600006,308.299988,311.859985,311.859985,4421400 +2023-02-03,311,311.549988,305.920013,308.51001,308.51001,5385700 +2023-02-06,308.25,308.799988,305.600006,308.429993,308.429993,2973100 +2023-02-07,307.299988,314.149994,306.630005,312.970001,312.970001,3786700 +2023-02-08,311.119995,313.410004,308.01001,308.480011,308.480011,3370000 +2023-02-09,310.170013,311.420013,306.98999,307.209991,307.209991,3461200 +2023-02-10,307.079987,309.980011,305.279999,309.890015,309.890015,2808000 +2023-02-13,310.299988,313.73999,309.619995,313.73999,313.73999,3261500 +2023-02-14,313.779999,314.100006,309.040009,310.790009,310.790009,2907100 +2023-02-15,309.980011,310.369995,308.279999,309.630005,309.630005,2410700 +2023-02-16,307.579987,310.200012,306.869995,308.179993,308.179993,2801700 +2023-02-17,307.149994,308.410004,305.480011,308.23999,308.23999,2720500 +2023-02-21,306.170013,307.299988,300.5,302.720001,302.720001,4131100 +2023-02-22,303.200012,305.269989,301.769989,303.160004,303.160004,2899500 +2023-02-23,305.01001,305.559998,300.25,303.070007,303.070007,2736400 +2023-02-24,300.399994,305.619995,300.01001,304.019989,304.019989,3656200 +2023-02-27,304.369995,305.779999,302.01001,304.660004,304.660004,3652200 +2023-02-28,304.890015,306.149994,303.410004,305.179993,305.179993,4736800 +2023-03-01,304.019989,305.619995,302.079987,304.619995,304.619995,3397200 +2023-03-02,303.660004,308.100006,301.450012,307.75,307.75,3152100 +2023-03-03,309.559998,312.660004,308.5,312.450012,312.450012,4493000 +2023-03-06,312.820007,317.290009,312.429993,316.970001,316.970001,4889800 +2023-03-07,316.390015,316.5,310.230011,311.119995,311.119995,3609700 +2023-03-08,310.720001,312.679993,309.25,311.369995,311.369995,2701600 +2023-03-09,311,313.179993,303.940002,304.820007,304.820007,3929500 +2023-03-10,302.950012,306.720001,301.920013,303.630005,303.630005,5294800 +2023-03-13,301.75,306.589996,300.76001,302.880005,302.880005,4993000 +2023-03-14,306.920013,307.549988,301.679993,305.329987,305.329987,5251500 +2023-03-15,300.019989,300.549988,294.899994,297.880005,297.880005,7162800 +2023-03-16,296.369995,304.429993,295.359985,302.01001,302.01001,6325700 +2023-03-17,301.299988,301.299988,292.420013,293.51001,293.51001,15609400 +2023-03-20,295.570007,301.51001,295.059998,301.059998,301.059998,6056000 +2023-03-21,304.559998,305.630005,302.25,303.850006,303.850006,4724000 +2023-03-22,303.720001,307.049988,299.649994,299.730011,299.730011,3086300 +2023-03-23,301.390015,302.079987,296.299988,298.369995,298.369995,4015800 +2023-03-24,294.679993,299.5,293.390015,298.920013,298.920013,3905400 +2023-03-27,300.880005,303.209991,298.970001,302.140015,302.140015,3833900 +2023-03-28,301.929993,302.720001,300.589996,302.320007,302.320007,2436500 +2023-03-29,304.799988,305.380005,303.359985,305.299988,305.299988,2650000 +2023-03-30,307.089996,307.470001,302.579987,305.079987,305.079987,2694000 +2023-03-31,305.899994,308.809998,304.98999,308.769989,308.769989,5020200 +2023-04-03,309.25,311.5,308.23999,310.309998,310.309998,4862300 +2023-04-04,310.76001,311,307.070007,309.070007,309.070007,2740300 +2023-04-05,307.850006,311.070007,307.850006,310.390015,310.390015,2314500 +2023-04-06,309.820007,313.220001,309.049988,312.51001,312.51001,3131400 +2023-04-10,311.410004,313.700012,310.329987,312.619995,312.619995,2330900 +2023-04-11,312.559998,315.940002,311.769989,313.700012,313.700012,3109500 +2023-04-12,315.970001,316.920013,313.720001,314.549988,314.549988,2662600 +2023-04-13,315.269989,318.809998,313.26001,318.049988,318.049988,3323300 +2023-04-14,318.890015,321.880005,318.119995,319.73999,319.73999,2975400 +2023-04-17,320.200012,323.980011,319,323.790009,323.790009,3425500 +2023-04-18,324.950012,325.720001,322.5,324.630005,324.630005,3581200 +2023-04-19,323.850006,324.549988,322.76001,323.089996,323.089996,2406200 +2023-04-20,322.200012,324.369995,321.320007,323.820007,323.820007,2428400 +2023-04-21,322.359985,324.850006,321.609985,324.329987,324.329987,2405700 +2023-04-24,324.429993,326.399994,324.299988,326.049988,326.049988,2261900 +2023-04-25,325.98999,327.100006,324.109985,324.339996,324.339996,2552200 +2023-04-26,323.309998,323.73999,319,320.529999,320.529999,2718600 +2023-04-27,322.859985,326.910004,322.109985,326.230011,326.230011,2950000 +2023-04-28,325.440002,328.809998,325.190002,328.549988,328.549988,2909600 +2023-05-01,329.160004,331.839996,328.570007,330.170013,330.170013,2461300 +2023-05-02,330.149994,330.25,322.76001,325.859985,325.859985,3366500 +2023-05-03,327.130005,328.070007,323.059998,323.220001,323.220001,2653800 +2023-05-04,323.440002,325.98999,317.410004,320,320,3185600 +2023-05-05,323.359985,325.160004,322.619995,323.880005,323.880005,3869500 +2023-05-08,328.26001,330.690002,325.790009,326.140015,326.140015,3302400 +2023-05-09,324.869995,326.880005,323.480011,324.869995,324.869995,2283400 +2023-05-10,326.079987,326.160004,320.149994,322.98999,322.98999,2639800 +2023-05-11,321,322.959991,319.809998,322.640015,322.640015,2548900 +2023-05-12,323.820007,324.23999,320.540009,322.48999,322.48999,1937300 +2023-05-15,322.890015,323.829987,320.130005,323.529999,323.529999,2190000 +2023-05-16,322.459991,324.690002,322.359985,323.75,323.75,2139500 +2023-05-17,325.019989,328.26001,324.820007,327.390015,327.390015,3046800 +2023-05-18,326.869995,329.980011,325.850006,329.76001,329.76001,2805000 +2023-05-19,331,333.940002,329.119995,330.390015,330.390015,4322900 +2023-05-22,330.75,331.48999,328.350006,329.130005,329.130005,2762500 +2023-05-23,328.190002,329.269989,322.970001,323.109985,323.109985,4029300 +2023-05-24,322.709991,323,319.559998,320.200012,320.200012,3071500 +2023-05-25,320.559998,320.559998,317.709991,319.019989,319.019989,4245400 +2023-05-26,320.440002,322.630005,319.670013,320.600006,320.600006,3229400 +2023-05-30,321.859985,322.470001,319,322.190002,322.190002,3231800 +2023-05-31,321.119995,322.410004,319.390015,321.079987,321.079987,6175000 +2023-06-01,321.420013,323.220001,319.529999,323.119995,323.119995,3375300 +2023-06-02,325.160004,330.670013,324.420013,329.480011,329.480011,3962200 +2023-06-05,330.890015,330.890015,327.570007,328.579987,328.579987,3091800 +2023-06-06,329.040009,334.160004,328.679993,333.410004,333.410004,3181400 +2023-06-07,334.01001,335.820007,331.429993,335.420013,335.420013,3727800 +2023-06-08,335.48999,336.320007,334.100006,335.950012,335.950012,2759300 +2023-06-09,335.76001,337.589996,334.920013,335.290009,335.290009,2619200 +2023-06-12,335.160004,335.350006,332.220001,333.600006,333.600006,2873400 +2023-06-13,333.220001,336.619995,332.200012,336.390015,336.390015,2953000 +2023-06-14,337.220001,340.380005,334.089996,335.899994,335.899994,5164600 +2023-06-15,335.970001,341.679993,335.540009,339.820007,339.820007,4095200 +2023-06-16,341.019989,341.299988,337.660004,338.309998,338.309998,8486200 +2023-06-20,338.149994,339.279999,336.619995,338.670013,338.670013,3751700 +2023-06-21,337.299988,341.350006,336.369995,338.609985,338.609985,4507000 +2023-06-22,338.839996,338.850006,335.660004,336.959991,336.959991,3303300 +2023-06-23,335.100006,337.470001,334.190002,335.25,335.25,4451700 +2023-06-26,335.170013,335.829987,331.839996,334.119995,334.119995,3220900 +2023-06-27,334.390015,336.730011,334.369995,335.339996,335.339996,2625600 +2023-06-28,336.049988,336.399994,332.609985,334.149994,334.149994,3175100 +2023-06-29,334.26001,337.01001,334.140015,336.910004,336.910004,2498900 +2023-06-30,338.779999,342.5,338.399994,341,341,4520600 +2023-07-03,340.75,342.079987,338.410004,342,342,2047400 +2023-07-05,340.049988,341.890015,338.700012,341.559998,341.559998,2870700 +2023-07-06,339.75,341.799988,338.910004,341.459991,341.459991,2548300 +2023-07-07,340.519989,344.070007,340.390015,340.899994,340.899994,2940800 +2023-07-10,340.480011,343.480011,339.869995,341.130005,341.130005,2966500 +2023-07-11,341.230011,343.839996,340.929993,343.369995,343.369995,2754900 +2023-07-12,345.290009,346.440002,344.309998,345.350006,345.350006,2897100 +2023-07-13,345.600006,346.209991,343.450012,343.540009,343.540009,2831800 +2023-07-14,344.98999,345,340.51001,341.089996,341.089996,2669300 +2023-07-17,341.089996,345.720001,341.089996,344.25,344.25,2359500 +2023-07-18,344.049988,347.25,343.540009,345.339996,345.339996,2565300 +2023-07-19,344.209991,345.380005,341.98999,342.429993,342.429993,3032100 +2023-07-20,343.089996,346.790009,342.850006,346.609985,346.609985,3146000 +2023-07-21,346.76001,347.619995,345.100006,345.76001,345.76001,3301900 +2023-07-24,346.769989,351.190002,346.279999,349.630005,349.630005,3269400 +2023-07-25,349.320007,349.660004,345.540009,347.579987,347.579987,3014000 +2023-07-26,347.559998,351.089996,347.519989,349.799988,349.799988,2682900 +2023-07-27,350.690002,351.269989,348.600006,349.309998,349.309998,2706700 +2023-07-28,349.929993,351,348.320007,349.809998,349.809998,2473300 +2023-07-31,350.730011,352.329987,350.209991,351.959991,351.959991,2621600 +2023-08-01,352.029999,353.420013,351.25,352.26001,352.26001,2293300 +2023-08-02,351.450012,352.890015,349.690002,351.190002,351.190002,3085900 +2023-08-03,350.290009,354.470001,349.420013,353.809998,353.809998,2942000 +2023-08-04,353.98999,355.109985,349.390015,349.98999,349.98999,2842000 +2023-08-07,355.730011,364.630005,355.149994,362.579987,362.579987,5379900 +2023-08-08,359.420013,364.25,358.850006,363.730011,363.730011,3428800 +2023-08-09,364.200012,364.429993,356.059998,358.019989,358.019989,4424600 +2023-08-10,359.359985,362.350006,355.920013,356.980011,356.980011,3098800 +2023-08-11,356.26001,359.25,353.200012,358.350006,358.350006,2475200 +2023-08-14,358.25,358.950012,356.809998,358.480011,358.480011,1990700 +2023-08-15,357,357.920013,353.670013,354.5,354.5,2863700 +2023-08-16,354.600006,358.720001,353.380005,354.109985,354.109985,2196100 +2023-08-17,354.01001,356.299988,351.880005,353.190002,353.190002,2847700 +2023-08-18,351.470001,354.299988,351.25,352.559998,352.559998,2870600 +2023-08-21,354.089996,354.179993,349.609985,352.089996,352.089996,2540000 +2023-08-22,353.01001,353.5,349.660004,350.570007,350.570007,2363300 +2023-08-23,351.630005,354.320007,351.540009,354.26001,354.26001,2239500 +2023-08-24,354.350006,357.230011,354.130005,354.299988,354.299988,2521100 +2023-08-25,354.98999,357.350006,352.920013,355.929993,355.929993,2136800 +2023-08-28,357.890015,358.410004,354.529999,355.549988,355.549988,1728000 +2023-08-29,355.040009,358.589996,354.01001,358.290009,358.290009,2285600 +2023-08-30,358.630005,362.679993,358.600006,361.059998,361.059998,3058300 +2023-08-31,362.179993,362.470001,359.25,360.200012,360.200012,2842300 +2023-09-01,362,363.390015,360.600006,362.459991,362.459991,2637900 +2023-09-05,363.880005,366.470001,360,360.470001,360.470001,2976800 +2023-09-06,360.019989,362.799988,359.26001,361.670013,361.670013,2655800 +2023-09-07,360.959991,363.299988,360.869995,361.799988,361.799988,3263800 +2023-09-08,362.519989,364.829987,361.769989,363.149994,363.149994,3019100 +2023-09-11,364.869995,366.609985,364.51001,365.519989,365.519989,2921600 +2023-09-12,365.649994,370.429993,365.470001,367.779999,367.779999,2898400 +2023-09-13,369.329987,370.839996,365.970001,367.820007,367.820007,3261400 +2023-09-14,370.100006,370.220001,368.26001,369.5,369.5,3670100 +2023-09-15,368.519989,370.200012,367.519989,367.859985,367.859985,11595000 +2023-09-18,369.329987,371.329987,367.790009,370.429993,370.429993,3130900 +2023-09-19,371.640015,373.339996,368.459991,370.480011,370.480011,2603700 +2023-09-20,371.329987,371.339996,366.730011,366.820007,366.820007,2268400 +2023-09-21,366.559998,367.200012,362.940002,363.279999,363.279999,3178600 +2023-09-22,362.779999,363.420013,359.76001,360.160004,360.160004,3969400 +2023-09-25,359.01001,361.890015,357.269989,361.709991,361.709991,2556200 +2023-09-26,359.799988,360.790009,357.950012,359.420013,359.420013,3063900 +2023-09-27,360.01001,360.519989,354.269989,357.779999,357.779999,3535400 +2023-09-28,357.799988,359.470001,356.670013,357.059998,357.059998,2731700 +2023-09-29,357.299988,357.5,348.549988,350.299988,350.299988,4932900 +2023-10-02,349.640015,350,345.410004,348.079987,348.079987,3527600 +2023-10-03,347.390015,348.23999,342.130005,343.040009,343.040009,3151700 +2023-10-04,342.920013,344.01001,339.51001,343.690002,343.690002,3244600 +2023-10-05,343.700012,345.940002,342.369995,345.059998,345.059998,3027300 +2023-10-06,344.100006,348.76001,341.859985,346.339996,346.339996,3174700 +2023-10-09,344.23999,345.899994,342.829987,345.450012,345.450012,2762800 +2023-10-10,347,349.51001,345.5,348.559998,348.559998,2858600 +2023-10-11,349.380005,349.600006,344.920013,348.429993,348.429993,2620800 +2023-10-12,348.209991,348.660004,343.019989,345.660004,345.660004,2677500 +2023-10-13,346,348.440002,343.880005,345.089996,345.089996,2804800 +2023-10-16,348,349.940002,345.829987,346.230011,346.230011,3117800 +2023-10-17,346.179993,348.410004,344.149994,345.390015,345.390015,2998600 +2023-10-18,344.720001,344.829987,339.959991,340.890015,340.890015,2977100 +2023-10-19,340.309998,342.690002,338.450012,338.660004,338.660004,2741300 +2023-10-20,338.149994,340,334.350006,335.859985,335.859985,3466100 +2023-10-23,334.070007,338.880005,333.48999,336.839996,336.839996,2794200 +2023-10-24,338.179993,339.850006,337.769989,338.630005,338.630005,2355700 +2023-10-25,338.589996,339.619995,336.549988,336.899994,336.899994,2623200 +2023-10-26,337.070007,338.320007,335.459991,336.160004,336.160004,2685400 +2023-10-27,336.119995,336.190002,330.579987,331.709991,331.709991,3608200 +2023-10-30,332.959991,338.359985,332.179993,337.410004,337.410004,2634700 +2023-10-31,337.950012,341.48999,337.5,341.329987,341.329987,3066900 +2023-11-01,341.209991,345.329987,340.579987,343.75,343.75,2789700 +2023-11-02,346.390015,349.390015,344.5,349.019989,349.019989,3433700 +2023-11-03,350.170013,354.350006,349.790009,351.809998,351.809998,4409100 +2023-11-06,354.029999,354.029999,344.059998,346.630005,346.630005,5486200 +2023-11-07,346.809998,346.950012,344.299988,346.170013,346.170013,3062900 +2023-11-08,346.850006,348,344.690002,346.299988,346.299988,2602400 +2023-11-09,347.640015,350.109985,346.880005,348.179993,348.179993,3052100 +2023-11-10,349.600006,351.200012,348.600006,350.559998,350.559998,3701100 +2023-11-13,350.089996,350.649994,348.809998,350.01001,350.01001,2196200 +2023-11-14,352.519989,355.950012,351.25,354.25,354.25,3387500 +2023-11-15,355.019989,357.309998,354.480011,356.790009,356.790009,3572900 +2023-11-16,357.790009,360,357.230011,359.859985,359.859985,2822500 +2023-11-17,360.470001,360.559998,358.070007,358.929993,358.929993,3260000 +2023-11-20,359.350006,362.609985,358.179993,361.329987,361.329987,3215300 +2023-11-21,360.579987,363.029999,360.25,361,361,2918800 +2023-11-22,361.76001,362.459991,360.049988,361.799988,361.799988,2110200 +2023-11-24,362.51001,363.190002,361.23999,362.679993,362.679993,1282000 +2023-11-27,362.640015,362.640015,359.579987,361.339996,361.339996,2580300 +2023-11-28,361.549988,362.119995,359.209991,360.049988,360.049988,2953500 +2023-11-29,360.950012,361.519989,358.299988,358.690002,358.690002,3141100