diff --git a/helper/README.md b/helper/README.md index 17a9438..2df98be 100644 --- a/helper/README.md +++ b/helper/README.md @@ -83,6 +83,7 @@ The information provided on this project is strictly for informational purposes - [func \(r \*Report\) WriteToFile\(fileName string\) error](<#Report.WriteToFile>) - [func \(r \*Report\) WriteToWriter\(writer io.Writer\) error](<#Report.WriteToWriter>) - [type ReportColumn](<#ReportColumn>) + - [func NewAnnotationReportColumn\(values \<\-chan string\) ReportColumn](<#NewAnnotationReportColumn>) - [func NewNumericReportColumn\[T Number\]\(name string, values \<\-chan T\) ReportColumn](<#NewNumericReportColumn>) - [type Ring](<#Ring>) - [func NewRing\[T any\]\(size int\) \*Ring\[T\]](<#NewRing>) @@ -851,7 +852,7 @@ type Number interface { ``` -## type [Report]() +## type [Report]() Report generates an HTML file containing an interactive chart that visually represents the provided data and annotations. @@ -864,7 +865,7 @@ type Report struct { ``` -### func [NewReport]() +### func [NewReport]() ```go func NewReport(title string, date <-chan time.Time) *Report @@ -873,7 +874,7 @@ func NewReport(title string, date <-chan time.Time) *Report NewReport takes a channel of time as the time axis and returns a new instance of the Report struct. This instance can later be used to add data and annotations and subsequently generate a report. -### func \(\*Report\) [AddColumn]() +### func \(\*Report\) [AddColumn]() ```go func (r *Report) AddColumn(column ReportColumn) @@ -882,7 +883,7 @@ func (r *Report) AddColumn(column ReportColumn) AddColumn adds a new data column to the report. -### func \(\*Report\) [WriteToFile]() +### func \(\*Report\) [WriteToFile]() ```go func (r *Report) WriteToFile(fileName string) error @@ -891,7 +892,7 @@ func (r *Report) WriteToFile(fileName string) error WriteToFile writes the generated report content to a file with the specified name. This allows users to conveniently save the report for later viewing or analysis. -### func \(\*Report\) [WriteToWriter]() +### func \(\*Report\) [WriteToWriter]() ```go func (r *Report) WriteToWriter(writer io.Writer) error @@ -900,7 +901,7 @@ func (r *Report) WriteToWriter(writer io.Writer) error WriteToWriter writes the report content to the provided io.Writer. This allows the report to be sent to various destinations, such as a file, a network socket, or even the standard output. -## type [ReportColumn]() +## type [ReportColumn]() ReportColumn defines the interface that all report data columns must implement. This interface ensures that different types of data columns can be used consistently within the report generation process. @@ -912,13 +913,25 @@ type ReportColumn interface { // Type returns the data type of the report column. Type() string + // Role returns the role of the report column. + Role() string + // Value returns the next data value for the report column. Value() string } ``` + +### func [NewAnnotationReportColumn]() + +```go +func NewAnnotationReportColumn(values <-chan string) ReportColumn +``` + +NewAnnotationReportColumn returns a new instance of a annotation column for a report. + -### func [NewNumericReportColumn]() +### func [NewNumericReportColumn]() ```go func NewNumericReportColumn[T Number](name string, values <-chan T) ReportColumn diff --git a/helper/annotation_report_column.go b/helper/annotation_report_column.go new file mode 100644 index 0000000..d7431ff --- /dev/null +++ b/helper/annotation_report_column.go @@ -0,0 +1,46 @@ +// Copyright (c) 2023 Onur Cinar. All Rights Reserved. +// The source code is provided under MIT License. +// https://github.com/cinar/indicator + +package helper + +import "fmt" + +// annotationReportColumn is the annotation report column struct. +type annotationReportColumn struct { + ReportColumn + values <-chan string +} + +// NewAnnotationReportColumn returns a new instance of a annotation column for a report. +func NewAnnotationReportColumn(values <-chan string) ReportColumn { + return &annotationReportColumn{ + values: values, + } +} + +// Name returns the name of the report column. +func (c *annotationReportColumn) Name() string { + return "" +} + +// Type returns number as the data type. +func (c *annotationReportColumn) Type() string { + return "string" +} + +// Role returns the role of the report column. +func (c *annotationReportColumn) Role() string { + return "annotation" +} + +// Value returns the next data value for the report column. +func (c *annotationReportColumn) Value() string { + value := <-c.values + + if value != "" { + return fmt.Sprintf("\"%s\"", value) + } + + return "null" +} diff --git a/helper/numeric_report_column.go b/helper/numeric_report_column.go new file mode 100644 index 0000000..3f269de --- /dev/null +++ b/helper/numeric_report_column.go @@ -0,0 +1,42 @@ +// Copyright (c) 2023 Onur Cinar. All Rights Reserved. +// The source code is provided under MIT License. +// https://github.com/cinar/indicator + +package helper + +import "fmt" + +// numericReportColumn is the number report column struct. +type numericReportColumn[T Number] struct { + ReportColumn + name string + values <-chan T +} + +// NewNumericReportColumn returns a new instance of a numeric data column for a report. +func NewNumericReportColumn[T Number](name string, values <-chan T) ReportColumn { + return &numericReportColumn[T]{ + name: name, + values: values, + } +} + +// Name returns the name of the report column. +func (c *numericReportColumn[T]) Name() string { + return c.name +} + +// Type returns number as the data type. +func (c *numericReportColumn[T]) Type() string { + return "number" +} + +// Role returns the role of the report column. +func (c *numericReportColumn[T]) Role() string { + return "data" +} + +// Value returns the next data value for the report column. +func (c *numericReportColumn[T]) Value() string { + return fmt.Sprintf("%v", <-c.values) +} diff --git a/helper/report.go b/helper/report.go index 4c7516f..0bd6935 100644 --- a/helper/report.go +++ b/helper/report.go @@ -7,7 +7,6 @@ package helper import ( // Go embed report template. _ "embed" - "fmt" "io" "os" "path/filepath" @@ -28,40 +27,13 @@ type ReportColumn interface { // Type returns the data type of the report column. Type() string + // Role returns the role of the report column. + Role() string + // Value returns the next data value for the report column. Value() string } -// numericReportColumn is the number report column struct. -type numericReportColumn[T Number] struct { - ReportColumn - name string - values <-chan T -} - -// NewNumericReportColumn returns a new instance of a numeric data column for a report. -func NewNumericReportColumn[T Number](name string, values <-chan T) ReportColumn { - return &numericReportColumn[T]{ - name: name, - values: values, - } -} - -// Name returns the name of the report column. -func (c *numericReportColumn[T]) Name() string { - return c.name -} - -// Type returns number as the data type. -func (c *numericReportColumn[T]) Type() string { - return "number" -} - -// Value returns the next data value for the report column. -func (c *numericReportColumn[T]) Value() string { - return fmt.Sprintf("%v", <-c.values) -} - // reportModel struct holds the data that is exposed to the template renderer // for generating the report. It encapsulates all the information necessary // to render the report's content, including data, and annotations. diff --git a/helper/report.tmpl b/helper/report.tmpl index a797fdf..6616588 100644 --- a/helper/report.tmpl +++ b/helper/report.tmpl @@ -44,8 +44,9 @@ "curveType": "function", "legend": { "position": "right", - } - } + }, + "height": 400, + }, }); var rangeFilter = new google.visualization.ControlWrapper({ @@ -55,17 +56,21 @@ "filterColumnLabel": "Date", "ui": { "chartOptions": { - "height": 50 - } - } - } + "height": 50, + }, + }, + }, }); // Create the data table. var data = new google.visualization.DataTable(); data.addColumn("date", "Date"); {{ range.Columns }} - data.addColumn("{{ .Type }}", "{{ .Name }}"); + data.addColumn({ + "type": "{{ .Type }}", + "label": "{{ .Name }}", + "role": "{{ .Role }}", + }); {{ end }} {{ range.Date }} diff --git a/helper/report_test.go b/helper/report_test.go index eb1bcf2..6be6b2c 100644 --- a/helper/report_test.go +++ b/helper/report_test.go @@ -14,10 +14,11 @@ import ( func TestReportWriteToFile(t *testing.T) { type Row struct { - Date time.Time `format:"2006-01-02"` - High float64 - Low float64 - Close float64 + Date time.Time `format:"2006-01-02"` + High float64 + Low float64 + Close float64 + Annotation string } input, err := helper.ReadFromCsvFile[Row]("testdata/report.csv", true) @@ -25,22 +26,51 @@ func TestReportWriteToFile(t *testing.T) { t.Fatal(err) } - inputs := helper.Duplicate(input, 4) + inputs := helper.Duplicate(input, 5) dates := helper.Map(inputs[0], func(row *Row) time.Time { return row.Date }) highs := helper.Map(inputs[1], func(row *Row) float64 { return row.High }) lows := helper.Map(inputs[2], func(row *Row) float64 { return row.Low }) closes := helper.Map(inputs[3], func(row *Row) float64 { return row.Close }) + annotations := helper.Map(inputs[4], func(row *Row) string { return row.Annotation }) report := helper.NewReport("Test Report", dates) report.AddColumn(helper.NewNumericReportColumn("High", highs)) report.AddColumn(helper.NewNumericReportColumn("Low", lows)) report.AddColumn(helper.NewNumericReportColumn("Close", closes)) + report.AddColumn(helper.NewAnnotationReportColumn(annotations)) fileName := "report.html" defer os.Remove(fileName) - err = report.WriteToFile("report.html") + err = report.WriteToFile(fileName) if err != nil { t.Fatal(err) } } + +func TestReportWriteToFileFailed(t *testing.T) { + type Row struct { + Date time.Time `format:"2006-01-02"` + High float64 + Low float64 + Close float64 + Annotation string + } + + input, err := helper.ReadFromCsvFile[Row]("testdata/report.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 }) + closes := helper.Map(inputs[1], func(row *Row) float64 { return row.Close }) + + report := helper.NewReport("Test Report", dates) + report.AddColumn(helper.NewNumericReportColumn("Close", closes)) + + err = report.WriteToFile("") + if err == nil { + t.Fatal("expected error") + } +} diff --git a/helper/testdata/report.csv b/helper/testdata/report.csv index 3727711..4f259c5 100644 --- a/helper/testdata/report.csv +++ b/helper/testdata/report.csv @@ -1,252 +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 +Date,Open,High,Low,Close,Adj Close,Volume,Annotation +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,"B" +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,"S" +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,"B" +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,"S" +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,"" diff --git a/pre-commit.sh b/pre-commit.sh index 7ccb172..c040940 100755 --- a/pre-commit.sh +++ b/pre-commit.sh @@ -1,6 +1,8 @@ #!/bin/bash -(command -v gomarkdoc) || go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest + +(command -v revive) || go install github.com/mgechev/revive@latest (command -v staticcheck) || go install honnef.co/go/tools/cmd/staticcheck@latest +(command -v gomarkdoc) || go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest go fmt ./... go fix ./... diff --git a/strategy/README.md b/strategy/README.md index d0a7fba..5d931b2 100644 --- a/strategy/README.md +++ b/strategy/README.md @@ -6,18 +6,46 @@ import "github.com/cinar/indicator/strategy" ``` +Package strategy contains the strategy functions. + +This package belongs to the Indicator project. Indicator is a Golang module that supplies a variety of technical indicators, strategies, and a backtesting framework for analysis. + +### License + +``` +Copyright (c) 2023 Onur Cinar. All Rights Reserved. +The source code is provided under MIT License. +https://github.com/cinar/indicator +``` + +### Disclaimer + +The information provided on this project is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security. + ## Index +- [func ActionsToAnnotations\(ac \<\-chan Action\) \<\-chan string](<#ActionsToAnnotations>) - [type Action](<#Action>) + - [func \(a Action\) Annotation\(\) string](<#Action.Annotation>) - [type ApoStrategy](<#ApoStrategy>) - [func NewApoStrategy\[T helper.Number\]\(\) \*ApoStrategy\[T\]](<#NewApoStrategy>) - [func \(a \*ApoStrategy\[T\]\) Compute\(c \<\-chan T\) \<\-chan Action](<#ApoStrategy[T].Compute>) + - [func \(a \*ApoStrategy\[T\]\) Report\(dates \<\-chan time.Time, c \<\-chan T\) \*helper.Report](<#ApoStrategy[T].Report>) + + +## func [ActionsToAnnotations]() + +```go +func ActionsToAnnotations(ac <-chan Action) <-chan string +``` + +ActionsToAnnotations takes a channel of action recommendations and returns a new channel containing corresponding annotations for those actions. -## type [Action]() +## type [Action]() -ActionType represents the different action categories that a strategy can recommend. +Action represents the different action categories that a strategy can recommend. ```go type Action int @@ -43,8 +71,17 @@ const ( ) ``` + +### func \(Action\) [Annotation]() + +```go +func (a Action) Annotation() string +``` + +Annotation returns a single character string representing the recommended action. It returns "S" for Sell, "B" for Buy, and an empty string for Hold. + -## type [ApoStrategy]() +## type [ApoStrategy]() ApoStrategy represents the configuration parameters for calculating the APO strategy. 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. @@ -57,16 +94,16 @@ type ApoStrategy[T helper.Number] struct { ``` -### func [NewApoStrategy]() +### func [NewApoStrategy]() ```go func NewApoStrategy[T helper.Number]() *ApoStrategy[T] ``` -NewApo function initializes a new APO strategy instance with the default parameters. +NewApoStrategy function initializes a new APO strategy instance with the default parameters. -### func \(\*ApoStrategy\[T\]\) [Compute]() +### func \(\*ApoStrategy\[T\]\) [Compute]() ```go func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action @@ -74,4 +111,13 @@ func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action Compute uses the given values as input and returns a channel of action recommendations. + +### func \(\*ApoStrategy\[T\]\) [Report]() + +```go +func (a *ApoStrategy[T]) Report(dates <-chan time.Time, c <-chan T) *helper.Report +``` + +Report takes input channels containing dates and values, computes the recommended actions based on the data, and generates a report annotated with those actions. + Generated by [gomarkdoc]() diff --git a/strategy/action.go b/strategy/action.go index 72bab2e..695cc63 100644 --- a/strategy/action.go +++ b/strategy/action.go @@ -4,7 +4,9 @@ package strategy -// ActionType represents the different action categories that a +import "github.com/cinar/indicator/helper" + +// Action represents the different action categories that a // strategy can recommend. type Action int @@ -23,3 +25,26 @@ const ( // asset's price is undervalued. Buy Action = 1 ) + +// Annotation returns a single character string representing the recommended action. +// It returns "S" for Sell, "B" for Buy, and an empty string for Hold. +func (a Action) Annotation() string { + switch a { + case Sell: + return "S" + + case Buy: + return "B" + + default: + return "" + } +} + +// ActionsToAnnotations takes a channel of action recommendations and returns a +// new channel containing corresponding annotations for those actions. +func ActionsToAnnotations(ac <-chan Action) <-chan string { + return helper.Map(ac, func(a Action) string { + return a.Annotation() + }) +} diff --git a/strategy/action_test.go b/strategy/action_test.go new file mode 100644 index 0000000..55407be --- /dev/null +++ b/strategy/action_test.go @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Onur Cinar. All Rights Reserved. +// The source code is provided under MIT License. +// https://github.com/cinar/indicator + +package strategy_test + +import ( + "testing" + + "github.com/cinar/indicator/helper" + "github.com/cinar/indicator/strategy" +) + +func TestAnnotation(t *testing.T) { + actions := []strategy.Action{strategy.Hold, strategy.Sell, strategy.Buy} + annotations := []string{"", "S", "B"} + + for i, action := range actions { + actual := action.Annotation() + expected := annotations[i] + + if actual != expected { + t.Fatalf("actual %s expected %s", actual, expected) + } + } +} + +func TestActionsToAnnotations(t *testing.T) { + actions := helper.SliceToChan([]strategy.Action{strategy.Hold, strategy.Sell, strategy.Buy}) + expected := helper.SliceToChan([]string{"", "S", "B"}) + + actual := strategy.ActionsToAnnotations(actions) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} diff --git a/strategy/apo_strategy.go b/strategy/apo_strategy.go index 2a7527b..f13f3f9 100644 --- a/strategy/apo_strategy.go +++ b/strategy/apo_strategy.go @@ -5,6 +5,8 @@ package strategy import ( + "time" + "github.com/cinar/indicator/helper" "github.com/cinar/indicator/trend" ) @@ -19,7 +21,7 @@ type ApoStrategy[T helper.Number] struct { Apo *trend.Apo[T] } -// NewApo function initializes a new APO strategy instance with the default parameters. +// 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](), @@ -51,3 +53,20 @@ func (a *ApoStrategy[T]) Compute(c <-chan T) <-chan Action { return Hold }), 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, 2) + + dates = helper.Skip(dates, a.Apo.SlowPeriod-1) + cs[0] = helper.Skip(cs[0], a.Apo.SlowPeriod-1) + + annotations := ActionsToAnnotations(a.Compute(cs[1])) + + report := helper.NewReport("APO Strategy", dates) + report.AddColumn(helper.NewNumericReportColumn("Close", cs[0])) + report.AddColumn(helper.NewAnnotationReportColumn(annotations)) + + return report +} diff --git a/strategy/apo_strategy_test.go b/strategy/apo_strategy_test.go index 5da40b2..ec6cd5e 100644 --- a/strategy/apo_strategy_test.go +++ b/strategy/apo_strategy_test.go @@ -5,26 +5,28 @@ package strategy_test import ( + "os" "testing" + "time" "github.com/cinar/indicator/helper" "github.com/cinar/indicator/strategy" ) func TestApoStrategy(t *testing.T) { - type ApoData struct { + type Row struct { Close float64 Action strategy.Action } - input, err := helper.ReadFromCsvFile[ApoData]("testdata/apo_strategy.csv", true) + input, err := helper.ReadFromCsvFile[Row]("testdata/apo_strategy.csv", true) if err != nil { t.Fatal(err) } inputs := helper.Duplicate(input, 2) - closing := helper.Map(inputs[0], func(a *ApoData) float64 { return a.Close }) - expected := helper.Map(inputs[1], func(a *ApoData) strategy.Action { return a.Action }) + 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 }) apo := strategy.NewApoStrategy[float64]() expected = helper.Skip(expected, apo.Apo.SlowPeriod-1) @@ -36,3 +38,31 @@ func TestApoStrategy(t *testing.T) { t.Fatal(err) } } + +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) + 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]() + + report := apo.Report(dates, closing) + + fileName := "apo_strategy.html" + defer os.Remove(fileName) + + err = report.WriteToFile(fileName) + if err != nil { + t.Fatal(err) + } +} diff --git a/strategy/strategy.go b/strategy/strategy.go new file mode 100644 index 0000000..4f2d52b --- /dev/null +++ b/strategy/strategy.go @@ -0,0 +1,19 @@ +// Package strategy contains the strategy functions. +// +// This package belongs to the Indicator project. Indicator is +// a Golang module that supplies a variety of technical +// indicators, strategies, and a backtesting framework +// for analysis. +// +// # License +// +// Copyright (c) 2023 Onur Cinar. All Rights Reserved. +// The source code is provided under MIT License. +// https://github.com/cinar/indicator +// +// # Disclaimer +// +// The information provided on this project is strictly for +// informational purposes and is not to be construed as +// advice or solicitation to buy or sell any security. +package strategy diff --git a/strategy/testdata/apo_strategy.csv b/strategy/testdata/apo_strategy.csv index b66dd93..5dcddec 100644 --- a/strategy/testdata/apo_strategy.csv +++ b/strategy/testdata/apo_strategy.csv @@ -1,252 +1,252 @@ -Close,Action -318.600006,0 -315.839996,0 -316.149994,0 -310.570007,0 -307.779999,0 -305.820007,0 -305.98999,0 -306.390015,0 -311.450012,0 -312.329987,0 -309.290009,0 -301.910004,0 -300,0 -300.029999,0 -302,0 -307.820007,0 -302.690002,0 -306.48999,0 -305.549988,0 -303.429993,0 -309.059998,0 -308.899994,0 -309.910004,0 -314.549988,0 -312.899994,0 -318.690002,0 -315.529999,0 -316.350006,0 -320.369995,0 -318.929993,0 -317.640015,0 -314.859985,0 -308.299988,0 -305.230011,0 -309.869995,0 -310.420013,0 -311.299988,0 -311.899994,0 -310.950012,0 -309.170013,0 -307.329987,0 -311.519989,1 -310.570007,0 -311.859985,0 -308.51001,0 -308.429993,0 -312.970001,0 -308.480011,0 -307.209991,0 -309.890015,0 -313.73999,0 -310.790009,0 -309.630005,0 -308.179993,0 -308.23999,0 -302.720001,0 -303.160004,0 -303.070007,0 -304.019989,0 -304.660004,0 -305.179993,0 -304.619995,0 -307.75,0 -312.450012,0 -316.970001,0 -311.119995,0 -311.369995,0 -304.820007,0 -303.630005,0 -302.880005,0 -305.329987,0 -297.880005,0 -302.01001,0 -293.51001,0 -301.059998,0 -303.850006,0 -299.730011,0 -298.369995,0 -298.920013,0 -302.140015,0 -302.320007,0 -305.299988,0 -305.079987,0 -308.769989,0 -310.309998,0 -309.070007,0 -310.390015,0 -312.51001,-1 -312.619995,0 -313.700012,0 -314.549988,0 -318.049988,0 -319.73999,0 -323.790009,0 -324.630005,0 -323.089996,0 -323.820007,0 -324.329987,0 -326.049988,0 -324.339996,0 -320.529999,0 -326.230011,0 -328.549988,0 -330.170013,0 -325.859985,0 -323.220001,0 -320,0 -323.880005,0 -326.140015,0 -324.869995,0 -322.98999,0 -322.640015,0 -322.48999,0 -323.529999,0 -323.75,0 -327.390015,0 -329.76001,0 -330.390015,0 -329.130005,0 -323.109985,1 -320.200012,0 -319.019989,0 -320.600006,0 -322.190002,0 -321.079987,0 -323.119995,0 -329.480011,0 -328.579987,0 -333.410004,-1 -335.420013,0 -335.950012,0 -335.290009,0 -333.600006,0 -336.390015,0 -335.899994,0 -339.820007,0 -338.309998,0 -338.670013,0 -338.609985,0 -336.959991,0 -335.25,0 -334.119995,0 -335.339996,0 -334.149994,0 -336.910004,0 -341,0 -342,0 -341.559998,0 -341.459991,0 -340.899994,0 -341.130005,0 -343.369995,0 -345.350006,0 -343.540009,0 -341.089996,0 -344.25,0 -345.339996,0 -342.429993,0 -346.609985,0 -345.76001,0 -349.630005,0 -347.579987,0 -349.799988,0 -349.309998,0 -349.809998,0 -351.959991,0 -352.26001,0 -351.190002,0 -353.809998,0 -349.98999,0 -362.579987,0 -363.730011,0 -358.019989,0 -356.980011,0 -358.350006,0 -358.480011,0 -354.5,0 -354.109985,0 -353.190002,0 -352.559998,0 -352.089996,0 -350.570007,0 -354.26001,0 -354.299988,0 -355.929993,0 -355.549988,0 -358.290009,0 -361.059998,0 -360.200012,1 -362.459991,-1 -360.470001,1 -361.670013,0 -361.799988,-1 -363.149994,0 -365.519989,0 -367.779999,0 -367.820007,0 -369.5,0 -367.859985,0 -370.429993,0 -370.480011,0 -366.820007,0 -363.279999,0 -360.160004,0 -361.709991,0 -359.420013,0 -357.779999,0 -357.059998,0 -350.299988,0 -348.079987,1 -343.040009,0 -343.690002,0 -345.059998,0 -346.339996,0 -345.450012,0 -348.559998,0 -348.429993,0 -345.660004,0 -345.089996,0 -346.230011,0 -345.390015,0 -340.890015,0 -338.660004,0 -335.859985,0 -336.839996,0 -338.630005,0 -336.899994,0 -336.160004,0 -331.709991,0 -337.410004,0 -341.329987,0 -343.75,0 -349.019989,0 -351.809998,0 -346.630005,0 -346.170013,0 -346.299988,0 -348.179993,0 -350.559998,0 -350.01001,-1 -354.25,0 -356.790009,0 -359.859985,0 -358.929993,0 -361.329987,0 -361,0 -361.799988,0 -362.679993,0 -361.339996,0 -360.049988,0 -358.690002,0 \ No newline at end of file +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