Merge pull request #1633 from ranaroussi/feature/price-repair-improvements
Improve price repairpull/1654/head
commit
6c1e26093c
|
@ -0,0 +1,6 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2023-05-30 00:00:00+02:00,19.5900001525879,19.7999992370605,19.2700004577637,19.3500003814697,18.6291382416581,196309,0,0
|
||||
2023-05-31 00:00:00+02:00,19.1200008392334,19.1399993896484,18.7000007629395,18.7900009155273,18.0900009155273,156652,0,0
|
||||
2023-06-02 00:00:00+02:00,18.5499992370605,19,18.5100002288818,18.8999996185303,18.8999996185303,83439,0.7,0
|
||||
2023-06-05 00:00:00+02:00,18.9300003051758,19.0900001525879,18.8400001525879,19,19,153167,0,0
|
||||
2023-06-06 00:00:00+02:00,18.9099998474121,18.9500007629395,18.5100002288818,18.6599998474121,18.6599998474121,104352,0,0
|
|
|
@ -0,0 +1,6 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2023-05-30 00:00:00+02:00,19.59000015258789,19.799999237060547,19.270000457763672,19.350000381469727,19.350000381469727,196309,0.0,0.0
|
||||
2023-05-31 00:00:00+02:00,19.1200008392334,19.139999389648438,18.700000762939453,18.790000915527344,18.790000915527344,156652,0.0,0.0
|
||||
2023-06-02 00:00:00+02:00,18.549999237060547,19.0,18.510000228881836,18.899999618530273,18.899999618530273,83439,0.7,0.0
|
||||
2023-06-05 00:00:00+02:00,18.93000030517578,19.09000015258789,18.84000015258789,19.0,19.0,153167,0.0,0.0
|
||||
2023-06-06 00:00:00+02:00,18.90999984741211,18.950000762939453,18.510000228881836,18.65999984741211,18.65999984741211,104352,0.0,0.0
|
|
|
@ -0,0 +1,24 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-06-06 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-06-01 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-31 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-30 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-27 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-26 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-25 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-24 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-23 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-20 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-19 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-18 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,532454,0,0
|
||||
2022-05-17 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-16 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-13 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-12 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-11 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-10 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-09 00:00:00+01:00,14.55,14.55,14.55,14.55,14.55,0,0,0
|
||||
2022-05-06 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-05 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-04 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
||||
2022-05-03 00:00:00+01:00,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,14.5500004291534,0,0,0
|
|
|
@ -0,0 +1,24 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-06-06 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-06-01 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-31 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-30 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-27 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-26 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-25 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-24 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-23 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-20 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-19 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-18 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,532454,0.0,0.0
|
||||
2022-05-17 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-16 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-13 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-12 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-11 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-10 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-09 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-06 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-05 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-04 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-03 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
|
|
@ -0,0 +1,37 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-05-30 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-05-23 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-05-16 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,532454,0,0
|
||||
2022-05-09 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-05-02 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-04-25 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-04-18 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-04-11 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-04-04 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-03-28 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-03-21 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-03-14 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-03-07 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-02-28 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-02-21 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-02-14 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-02-07 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-01-31 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-01-24 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-01-17 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-01-10 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-01-03 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-12-27 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-12-20 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-12-13 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-12-06 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-11-29 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-11-22 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-11-15 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-11-08 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-11-01 00:00:00+00:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-10-25 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-10-18 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-10-11 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2021-10-04 00:00:00+01:00,14.8000,15.3400,14.4000,14.5500,14.5500,2171373,0,0
|
||||
2021-09-27 00:00:00+01:00,15.6000,16.0000,14.9000,15.0500,15.0500,3860549,0,0
|
|
|
@ -0,0 +1,25 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-08-15 00:00:00+01:00,27.6000,28.2000,26.2000,27.6000,27.6000,3535668,0,0
|
||||
2022-08-12 00:00:00+01:00,27.3000,29.8000,26.4030,27.0000,27.0000,7223353,0,0
|
||||
2022-08-11 00:00:00+01:00,26.0000,29.8000,24.2000,27.1000,27.1000,12887933,0,0
|
||||
2022-08-10 00:00:00+01:00,25.0000,29.2000,22.5000,25.0000,25.0000,26572680,0,0
|
||||
2022-08-09 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-08 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-05 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-04 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-03 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-02 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-08-01 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-29 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-28 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-27 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-26 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-25 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-22 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-21 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-20 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-19 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-18 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-15 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-14 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
||||
2022-07-13 00:00:00+01:00,14.5500,14.5500,14.5500,14.5500,14.5500,0,0,0
|
|
@ -0,0 +1,37 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-05-30 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-23 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-05-16 00:00:00+01:00,14.550000190734863,14.550000190734863,0.14550000429153442,0.14550000429153442,0.14550000429153442,532454,0.0,0.0
|
||||
2022-05-09 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-05-02 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-04-25 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-04-18 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-04-11 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-04-04 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-03-28 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-03-21 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-03-14 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-03-07 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-02-28 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-02-21 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-02-14 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-02-07 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-01-31 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-01-24 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-01-17 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-01-10 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-01-03 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-12-27 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-12-20 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-12-13 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-12-06 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-11-29 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-11-22 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-11-15 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-11-08 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-11-01 00:00:00+00:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-10-25 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-10-18 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-10-11 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2021-10-04 00:00:00+01:00,14.800000190734863,15.34000015258789,0.14399999380111694,0.14550000429153442,0.14550000429153442,2171373,0.0,0.0
|
||||
2021-09-27 00:00:00+01:00,15.600000381469727,16.0,14.899999618530273,15.050000190734863,15.050000190734863,3860549,0.0,0.0
|
|
|
@ -0,0 +1,25 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2022-08-15 00:00:00+01:00,27.600000381469727,28.200000762939453,26.200000762939453,27.600000381469727,27.600000381469727,3535668,0.0,0.0
|
||||
2022-08-12 00:00:00+01:00,27.299999237060547,29.799999237060547,26.402999877929688,27.0,27.0,7223353,0.0,0.0
|
||||
2022-08-11 00:00:00+01:00,26.0,29.799999237060547,24.200000762939453,27.100000381469727,27.100000381469727,12887933,0.0,0.0
|
||||
2022-08-10 00:00:00+01:00,25.0,29.200000762939453,22.5,25.0,25.0,26572680,0.0,0.0
|
||||
2022-08-09 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-08 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-05 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-04 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-03 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-02 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-08-01 00:00:00+01:00,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,14.550000190734863,0,0.0,0.0
|
||||
2022-07-29 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-28 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-27 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-26 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-25 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-22 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-21 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-20 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-19 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-18 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-15 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-14 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
||||
2022-07-13 00:00:00+01:00,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0.14550000429153442,0,0.0,0.0
|
|
@ -0,0 +1,85 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2021-12-13 00:00:00+00:00,393.999975585938,406.6,391.4,402.899916992188,291.232287597656,62714764.4736842,0,0
|
||||
2021-12-20 00:00:00+00:00,393.999975585938,412.199990234375,392.502983398438,409.899997558594,296.292243652344,46596651.3157895,0,0
|
||||
2021-12-27 00:00:00+00:00,409.899997558594,416.550971679688,408.387001953125,410.4,296.653642578125,10818482.8947368,0,0
|
||||
2022-01-03 00:00:00+00:00,410.4,432.199995117188,410.4,432.099985351563,312.339265136719,44427327.6315789,0,0
|
||||
2022-01-10 00:00:00+00:00,431.3,439.199982910156,429.099970703125,436.099912109375,315.230618896484,29091400,0,0
|
||||
2022-01-17 00:00:00+00:00,437.999912109375,445.199965820313,426.999997558594,431.999975585938,312.267017822266,43787351.3157895,0,0
|
||||
2022-01-24 00:00:00+00:00,430.099975585938,440.999973144531,420.999968261719,433.499982910156,313.351237792969,58487296.0526316,0,0
|
||||
2022-01-31 00:00:00+00:00,436.199968261719,443.049987792969,432.099985351563,435.199916992188,314.580045166016,43335806.5789474,0,0
|
||||
2022-02-07 00:00:00+00:00,437.899995117188,448.799992675781,436.051994628906,444.39998046875,321.230207519531,39644061.8421053,0,0
|
||||
2022-02-14 00:00:00+00:00,437.699975585938,441.999978027344,426.699968261719,432.199995117188,312.411558837891,49972693.4210526,0,0
|
||||
2022-02-21 00:00:00+00:00,435.499992675781,438.476999511719,408.29998046875,423.399970703125,306.050571289063,65719596.0526316,0,0
|
||||
2022-02-28 00:00:00+00:00,415.099995117188,427.999909667969,386.199932861328,386.799945068359,279.594578857422,94057936.8421053,4.1875,0
|
||||
2022-03-07 00:00:00+00:00,374.999952392578,417.299978027344,361.101981201172,409.599968261719,298.389248046875,71269101.3157895,0,0
|
||||
2022-03-14 00:00:00+00:00,413.099985351563,426.699968261719,408.899992675781,422.399965820313,307.713929443359,55431927.6315789,0,0
|
||||
2022-03-21 00:00:00+00:00,422.699995117188,442.7,422.399965820313,437.799985351563,318.932696533203,39896352.6315789,0,0
|
||||
2022-03-28 00:00:00+01:00,442.49998046875,460.999978027344,440.097983398438,444.6,323.886403808594,56413515.7894737,0,0
|
||||
2022-04-04 00:00:00+01:00,439.699985351563,445.399985351563,421.999973144531,425.799973144531,310.190817871094,49415836.8421053,19.342106,0
|
||||
2022-04-11 00:00:00+01:00,425.39998046875,435.599909667969,420.799995117188,434.299968261719,327.211427001953,29875081.5789474,0,0
|
||||
2022-04-18 00:00:00+01:00,434.299968261719,447.799987792969,433.599992675781,437.799985351563,329.848419189453,49288272.3684211,0,0
|
||||
2022-04-25 00:00:00+01:00,430.699987792969,438.799990234375,423.999982910156,433.299916992188,326.457967529297,44656776.3157895,0,0
|
||||
2022-05-02 00:00:00+01:00,433.299916992188,450.999975585938,414.499982910156,414.899975585938,312.595018310547,29538167.1052632,0,0
|
||||
2022-05-09 00:00:00+01:00,413.199995117188,417.449992675781,368.282923583984,408.199970703125,307.547099609375,73989611.8421053,0,0
|
||||
2022-05-16 00:00:00+01:00,384,423.600006103516,384,412.100006103516,310.485473632813,81938261,101.69,0.76
|
||||
2022-05-23 00:00:00+01:00,416.100006103516,442.399993896484,341.915008544922,440.899993896484,409.764678955078,45432941,0,0
|
||||
2022-05-30 00:00:00+01:00,442.700012207031,444.200012207031,426.600006103516,428.700012207031,398.426239013672,37906659,0,0
|
||||
2022-06-06 00:00:00+01:00,425.299987792969,434.010009765625,405.200012207031,405.399993896484,376.771606445313,40648810,0,0
|
||||
2022-06-13 00:00:00+01:00,402.5,420,399.799987792969,411.200012207031,382.162048339844,74196958,0,0
|
||||
2022-06-20 00:00:00+01:00,412.5,421.899993896484,398.399993896484,411.5,382.440826416016,28679717,0,0
|
||||
2022-06-27 00:00:00+01:00,413.100006103516,422.399993896484,397.399993896484,401.600006103516,373.239959716797,35468994,0,0
|
||||
2022-07-04 00:00:00+01:00,405.399993896484,406.600006103516,382.299987792969,401.299987792969,372.961120605469,35304748,0,0
|
||||
2022-07-11 00:00:00+01:00,394.799987792969,405.850006103516,383.399993896484,396.600006103516,368.593048095703,42308459,0,0
|
||||
2022-07-18 00:00:00+01:00,392.5,399.700012207031,384.799987792969,391.700012207031,364.039093017578,36656839,0,0
|
||||
2022-07-25 00:00:00+01:00,392.200012207031,400.799987792969,388.700012207031,396,368.035430908203,33124660,0,0
|
||||
2022-08-01 00:00:00+01:00,396.399993896484,405.5,390.415008544922,402,373.611724853516,21753121,0,0
|
||||
2022-08-08 00:00:00+01:00,406.600006103516,473.700012207031,403.299987792969,467.899993896484,434.858032226563,59155709,0,0
|
||||
2022-08-15 00:00:00+01:00,468.100006103516,470.5,434,437,406.140106201172,36989620,10.3,0
|
||||
2022-08-22 00:00:00+01:00,436.100006103516,436.869995117188,419.299987792969,420.5,399.780303955078,36492572,0,0
|
||||
2022-08-29 00:00:00+01:00,420.5,426.600006103516,408.600006103516,426.600006103516,405.579742431641,29573657,0,0
|
||||
2022-09-05 00:00:00+01:00,418.5,444.4169921875,416.100006103516,443.100006103516,421.266723632813,34375126,0,0
|
||||
2022-09-12 00:00:00+01:00,444.649993896484,448.899993896484,435.200012207031,440.100006103516,418.414520263672,39085960,0,0
|
||||
2022-09-19 00:00:00+01:00,440.100006103516,447.200012207031,419.299987792969,422.899993896484,402.062042236328,27982081,0,0
|
||||
2022-09-26 00:00:00+01:00,421.200012207031,421.200012207031,373.31201171875,388.200012207031,369.071868896484,70408935,0,0
|
||||
2022-10-03 00:00:00+01:00,382.899993896484,409.875,380.555999755859,400.700012207031,380.955932617188,37581751,0,0
|
||||
2022-10-10 00:00:00+01:00,395.799987792969,404.470001220703,366.700012207031,394.299987792969,374.871276855469,52952323,0,0
|
||||
2022-10-17 00:00:00+01:00,394.299987792969,414.799987792969,393,406.5,386.470123291016,26441475,0,0
|
||||
2022-10-24 00:00:00+01:00,407.100006103516,418.227996826172,407.100006103516,413.299987792969,392.93505859375,26239756,0,0
|
||||
2022-10-31 00:00:00+00:00,413.899993896484,430.200012207031,412,429.299987792969,408.146667480469,23168047,0,0
|
||||
2022-11-07 00:00:00+00:00,427.299987792969,445.899993896484,420.652008056641,438.399993896484,416.798278808594,36709117,0,0
|
||||
2022-11-14 00:00:00+00:00,438.299987792969,458.489990234375,435,455.100006103516,432.675415039063,29106506,0,0
|
||||
2022-11-21 00:00:00+00:00,454.399993896484,461,450,456.600006103516,434.101501464844,21667730,0,0
|
||||
2022-11-28 00:00:00+00:00,453.799987792969,456.899993896484,435.100006103516,444.799987792969,422.882934570313,33326204,0,0
|
||||
2022-12-05 00:00:00+00:00,442.899993896484,450.25,441.299987792969,448,425.925262451172,29147089,0,0
|
||||
2022-12-12 00:00:00+00:00,445.100006103516,451.299987792969,431.200012207031,436.100006103516,414.611633300781,46593233,0,0
|
||||
2022-12-19 00:00:00+00:00,436,452.600006103516,433.600006103516,444,422.122344970703,20982140,0,0
|
||||
2022-12-26 00:00:00+00:00,444,452.058013916016,442.399993896484,442.799987792969,420.981475830078,8249664,0,0
|
||||
2023-01-02 00:00:00+00:00,445.899993896484,458.149993896484,443.299987792969,456,433.531066894531,28687622,0,0
|
||||
2023-01-09 00:00:00+00:00,456,461.066009521484,435.799987792969,444.200012207031,422.3125,39237336,0,0
|
||||
2023-01-16 00:00:00+00:00,444.299987792969,447.200012207031,434.399993896484,439,417.368713378906,35267336,0,0
|
||||
2023-01-23 00:00:00+00:00,440,459.299987792969,439.5,457.399993896484,434.862091064453,37495012,0,0
|
||||
2023-01-30 00:00:00+00:00,454.399993896484,459.399993896484,447.799987792969,450.299987792969,428.111907958984,48879358,0,0
|
||||
2023-02-06 00:00:00+00:00,448,449.200012207031,436.299987792969,440,418.319458007813,38799772,0,0
|
||||
2023-02-13 00:00:00+00:00,441.200012207031,450.299987792969,440,447.600006103516,425.544982910156,30251441,0,0
|
||||
2023-02-20 00:00:00+00:00,448.5,450.799987792969,434.299987792969,440,418.319458007813,26764528,0,0
|
||||
2023-02-27 00:00:00+00:00,442.899993896484,450.5,441.608001708984,447.200012207031,425.164703369141,29895454,0,0
|
||||
2023-03-06 00:00:00+00:00,447.399993896484,467.299987792969,443.100006103516,449.700012207031,427.54150390625,82322819,0,0
|
||||
2023-03-13 00:00:00+00:00,450,451.417999267578,400.68701171875,402.200012207031,382.382019042969,85158023,0,0
|
||||
2023-03-20 00:00:00+00:00,396.200012207031,425.399993896484,383.496002197266,408.299987792969,388.181427001953,60152666,0,0
|
||||
2023-03-27 00:00:00+01:00,416,422.049987792969,399.549987792969,404.200012207031,384.283477783203,81534829,20.7,0
|
||||
2023-04-03 00:00:00+01:00,405,434.100006103516,404.399993896484,417.100006103516,417.100006103516,43217151,0,0
|
||||
2023-04-10 00:00:00+01:00,419.100006103516,426.700012207031,419.100006103516,421.700012207031,421.700012207031,32435695,0,0
|
||||
2023-04-17 00:00:00+01:00,423.700012207031,427.635009765625,415.399993896484,420.299987792969,420.299987792969,37715986,0,0
|
||||
2023-04-24 00:00:00+01:00,418.100006103516,423,415.299987792969,423,423,34331974,0,0
|
||||
2023-05-01 00:00:00+01:00,423.399993896484,426.100006103516,406.399993896484,414.600006103516,414.600006103516,40446519,0,0
|
||||
2023-05-08 00:00:00+01:00,414.600006103516,419.100006103516,408,412.700012207031,412.700012207031,36950836,0,0
|
||||
2023-05-15 00:00:00+01:00,414,418.399993896484,407.399993896484,413.5,413.5,53109487,0,0
|
||||
2023-05-22 00:00:00+01:00,413.600006103516,424,394.700012207031,401.299987792969,401.299987792969,64363368,0,0
|
||||
2023-05-29 00:00:00+01:00,401.299987792969,409.477996826172,392.700012207031,409.100006103516,409.100006103516,47587959,0,0
|
||||
2023-06-05 00:00:00+01:00,406.299987792969,410.700012207031,400.100006103516,400.899993896484,400.899993896484,22494985,0,0
|
||||
2023-06-12 00:00:00+01:00,404.100006103516,406,394.5,396,396,41531163,0,0
|
||||
2023-06-19 00:00:00+01:00,394,399.899993896484,380.720001220703,386.200012207031,386.200012207031,40439880,0,0
|
||||
2023-06-26 00:00:00+01:00,387.200012207031,397,382.899993896484,395.200012207031,395.200012207031,27701915,0,0
|
||||
2023-07-03 00:00:00+01:00,396.5,399.799987792969,380.100006103516,381.799987792969,381.799987792969,26005305,0,0
|
||||
2023-07-10 00:00:00+01:00,380,392.299987792969,379.403991699219,386,386,29789300,0,0
|
||||
2023-07-17 00:00:00+01:00,385,389.5,384.251007080078,387.100006103516,387.100006103516,0,0,0
|
|
|
@ -0,0 +1,85 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2021-12-13 00:00:00+00:00,518.4210205078125,535.0,515.0,530.1314697265625,383.20037841796875,47663221,0.0,0.0
|
||||
2021-12-20 00:00:00+00:00,518.4210205078125,542.368408203125,516.4512939453125,539.3421020507812,389.85821533203125,35413455,0.0,0.0
|
||||
2021-12-27 00:00:00+00:00,539.3421020507812,548.0933837890625,537.351318359375,540.0,390.333740234375,8222047,0.0,0.0
|
||||
2022-01-03 00:00:00+00:00,540.0,568.6842041015625,540.0,568.5526123046875,410.97271728515625,33764769,0.0,0.0
|
||||
2022-01-10 00:00:00+00:00,567.5,577.8947143554688,564.605224609375,573.815673828125,414.7771301269531,22109464,0.0,0.0
|
||||
2022-01-17 00:00:00+00:00,576.315673828125,585.7894287109375,561.8421020507812,568.4210205078125,410.8776550292969,33278387,0.0,0.0
|
||||
2022-01-24 00:00:00+00:00,565.9210205078125,580.2631225585938,553.9473266601562,570.3947143554688,412.30426025390625,44450345,0.0,0.0
|
||||
2022-01-31 00:00:00+00:00,573.9473266601562,582.9605102539062,568.5526123046875,572.6314697265625,413.9211120605469,32935213,0.0,0.0
|
||||
2022-02-07 00:00:00+00:00,576.1842041015625,590.5263061523438,573.7526245117188,584.73681640625,422.67132568359375,30129487,0.0,0.0
|
||||
2022-02-14 00:00:00+00:00,575.9210205078125,581.5789184570312,561.4473266601562,568.6842041015625,411.0678405761719,37979247,0.0,0.0
|
||||
2022-02-21 00:00:00+00:00,573.0263061523438,576.9434204101562,537.23681640625,557.105224609375,402.6981201171875,49946893,0.0,0.0
|
||||
2022-02-28 00:00:00+00:00,546.1842041015625,563.1577758789062,508.1578063964844,508.9472961425781,367.8876037597656,71484032,4.1875,0.0
|
||||
2022-03-07 00:00:00+00:00,493.4209899902344,549.0789184570312,475.1341857910156,538.9473266601562,392.617431640625,54164517,0.0,0.0
|
||||
2022-03-14 00:00:00+00:00,543.5526123046875,561.4473266601562,538.0263061523438,555.7894287109375,404.8867492675781,42128265,0.0,0.0
|
||||
2022-03-21 00:00:00+00:00,556.1842041015625,582.5,555.7894287109375,576.0526123046875,419.6482849121094,30321228,0.0,0.0
|
||||
2022-03-28 00:00:00+01:00,582.23681640625,606.5789184570312,579.0762939453125,585.0,426.16632080078125,42874272,0.0,0.0
|
||||
2022-04-04 00:00:00+01:00,578.5526123046875,586.0526123046875,555.2631225585938,560.2631225585938,408.14581298828125,37556036,19.342106,0.0
|
||||
2022-04-11 00:00:00+01:00,559.73681640625,573.1577758789062,553.6842041015625,571.4473266601562,430.5413513183594,22705062,0.0,0.0
|
||||
2022-04-18 00:00:00+01:00,571.4473266601562,589.2105102539062,570.5263061523438,576.0526123046875,434.0110778808594,37459087,0.0,0.0
|
||||
2022-04-25 00:00:00+01:00,566.7105102539062,577.368408203125,557.8947143554688,570.1314697265625,429.5499572753906,33939150,0.0,0.0
|
||||
2022-05-02 00:00:00+01:00,570.1314697265625,593.4210205078125,545.3947143554688,545.9210205078125,411.3092346191406,22449007,0.0,0.0
|
||||
2022-05-09 00:00:00+01:00,543.6842041015625,549.2763061523438,484.5827941894531,537.105224609375,404.667236328125,56232105,0.0,0.0
|
||||
2022-05-16 00:00:00+01:00,384.0,423.6000061035156,384.0,412.1000061035156,310.4854736328125,81938261,101.69,0.76
|
||||
2022-05-23 00:00:00+01:00,416.1000061035156,442.3999938964844,341.9150085449219,440.8999938964844,409.7646789550781,45432941,0.0,0.0
|
||||
2022-05-30 00:00:00+01:00,442.70001220703125,444.20001220703125,426.6000061035156,428.70001220703125,398.4262390136719,37906659,0.0,0.0
|
||||
2022-06-06 00:00:00+01:00,425.29998779296875,434.010009765625,405.20001220703125,405.3999938964844,376.7716064453125,40648810,0.0,0.0
|
||||
2022-06-13 00:00:00+01:00,402.5,420.0,399.79998779296875,411.20001220703125,382.16204833984375,74196958,0.0,0.0
|
||||
2022-06-20 00:00:00+01:00,412.5,421.8999938964844,398.3999938964844,411.5,382.4408264160156,28679717,0.0,0.0
|
||||
2022-06-27 00:00:00+01:00,413.1000061035156,422.3999938964844,397.3999938964844,401.6000061035156,373.2399597167969,35468994,0.0,0.0
|
||||
2022-07-04 00:00:00+01:00,405.3999938964844,406.6000061035156,382.29998779296875,401.29998779296875,372.96112060546875,35304748,0.0,0.0
|
||||
2022-07-11 00:00:00+01:00,394.79998779296875,405.8500061035156,383.3999938964844,396.6000061035156,368.5930480957031,42308459,0.0,0.0
|
||||
2022-07-18 00:00:00+01:00,392.5,399.70001220703125,384.79998779296875,391.70001220703125,364.0390930175781,36656839,0.0,0.0
|
||||
2022-07-25 00:00:00+01:00,392.20001220703125,400.79998779296875,388.70001220703125,396.0,368.0354309082031,33124660,0.0,0.0
|
||||
2022-08-01 00:00:00+01:00,396.3999938964844,405.5,390.4150085449219,402.0,373.6117248535156,21753121,0.0,0.0
|
||||
2022-08-08 00:00:00+01:00,406.6000061035156,473.70001220703125,403.29998779296875,467.8999938964844,434.8580322265625,59155709,0.0,0.0
|
||||
2022-08-15 00:00:00+01:00,468.1000061035156,470.5,434.0,437.0,406.1401062011719,36989620,10.3,0.0
|
||||
2022-08-22 00:00:00+01:00,436.1000061035156,436.8699951171875,419.29998779296875,420.5,399.7803039550781,36492572,0.0,0.0
|
||||
2022-08-29 00:00:00+01:00,420.5,426.6000061035156,408.6000061035156,426.6000061035156,405.5797424316406,29573657,0.0,0.0
|
||||
2022-09-05 00:00:00+01:00,418.5,444.4169921875,416.1000061035156,443.1000061035156,421.2667236328125,34375126,0.0,0.0
|
||||
2022-09-12 00:00:00+01:00,444.6499938964844,448.8999938964844,435.20001220703125,440.1000061035156,418.4145202636719,39085960,0.0,0.0
|
||||
2022-09-19 00:00:00+01:00,440.1000061035156,447.20001220703125,419.29998779296875,422.8999938964844,402.0620422363281,27982081,0.0,0.0
|
||||
2022-09-26 00:00:00+01:00,421.20001220703125,421.20001220703125,373.31201171875,388.20001220703125,369.0718688964844,70408935,0.0,0.0
|
||||
2022-10-03 00:00:00+01:00,382.8999938964844,409.875,380.5559997558594,400.70001220703125,380.9559326171875,37581751,0.0,0.0
|
||||
2022-10-10 00:00:00+01:00,395.79998779296875,404.4700012207031,366.70001220703125,394.29998779296875,374.87127685546875,52952323,0.0,0.0
|
||||
2022-10-17 00:00:00+01:00,394.29998779296875,414.79998779296875,393.0,406.5,386.4701232910156,26441475,0.0,0.0
|
||||
2022-10-24 00:00:00+01:00,407.1000061035156,418.2279968261719,407.1000061035156,413.29998779296875,392.93505859375,26239756,0.0,0.0
|
||||
2022-10-31 00:00:00+00:00,413.8999938964844,430.20001220703125,412.0,429.29998779296875,408.14666748046875,23168047,0.0,0.0
|
||||
2022-11-07 00:00:00+00:00,427.29998779296875,445.8999938964844,420.6520080566406,438.3999938964844,416.79827880859375,36709117,0.0,0.0
|
||||
2022-11-14 00:00:00+00:00,438.29998779296875,458.489990234375,435.0,455.1000061035156,432.6754150390625,29106506,0.0,0.0
|
||||
2022-11-21 00:00:00+00:00,454.3999938964844,461.0,450.0,456.6000061035156,434.10150146484375,21667730,0.0,0.0
|
||||
2022-11-28 00:00:00+00:00,453.79998779296875,456.8999938964844,435.1000061035156,444.79998779296875,422.8829345703125,33326204,0.0,0.0
|
||||
2022-12-05 00:00:00+00:00,442.8999938964844,450.25,441.29998779296875,448.0,425.9252624511719,29147089,0.0,0.0
|
||||
2022-12-12 00:00:00+00:00,445.1000061035156,451.29998779296875,431.20001220703125,436.1000061035156,414.61163330078125,46593233,0.0,0.0
|
||||
2022-12-19 00:00:00+00:00,436.0,452.6000061035156,433.6000061035156,444.0,422.1223449707031,20982140,0.0,0.0
|
||||
2022-12-26 00:00:00+00:00,444.0,452.0580139160156,442.3999938964844,442.79998779296875,420.9814758300781,8249664,0.0,0.0
|
||||
2023-01-02 00:00:00+00:00,445.8999938964844,458.1499938964844,443.29998779296875,456.0,433.53106689453125,28687622,0.0,0.0
|
||||
2023-01-09 00:00:00+00:00,456.0,461.0660095214844,435.79998779296875,444.20001220703125,422.3125,39237336,0.0,0.0
|
||||
2023-01-16 00:00:00+00:00,444.29998779296875,447.20001220703125,434.3999938964844,439.0,417.36871337890625,35267336,0.0,0.0
|
||||
2023-01-23 00:00:00+00:00,440.0,459.29998779296875,439.5,457.3999938964844,434.8620910644531,37495012,0.0,0.0
|
||||
2023-01-30 00:00:00+00:00,454.3999938964844,459.3999938964844,447.79998779296875,450.29998779296875,428.1119079589844,48879358,0.0,0.0
|
||||
2023-02-06 00:00:00+00:00,448.0,449.20001220703125,436.29998779296875,440.0,418.3194580078125,38799772,0.0,0.0
|
||||
2023-02-13 00:00:00+00:00,441.20001220703125,450.29998779296875,440.0,447.6000061035156,425.54498291015625,30251441,0.0,0.0
|
||||
2023-02-20 00:00:00+00:00,448.5,450.79998779296875,434.29998779296875,440.0,418.3194580078125,26764528,0.0,0.0
|
||||
2023-02-27 00:00:00+00:00,442.8999938964844,450.5,441.6080017089844,447.20001220703125,425.1647033691406,29895454,0.0,0.0
|
||||
2023-03-06 00:00:00+00:00,447.3999938964844,467.29998779296875,443.1000061035156,449.70001220703125,427.54150390625,82322819,0.0,0.0
|
||||
2023-03-13 00:00:00+00:00,450.0,451.4179992675781,400.68701171875,402.20001220703125,382.38201904296875,85158023,0.0,0.0
|
||||
2023-03-20 00:00:00+00:00,396.20001220703125,425.3999938964844,383.4960021972656,408.29998779296875,388.1814270019531,60152666,0.0,0.0
|
||||
2023-03-27 00:00:00+01:00,416.0,422.04998779296875,399.54998779296875,404.20001220703125,384.2834777832031,81534829,20.7,0.0
|
||||
2023-04-03 00:00:00+01:00,405.0,434.1000061035156,404.3999938964844,417.1000061035156,417.1000061035156,43217151,0.0,0.0
|
||||
2023-04-10 00:00:00+01:00,419.1000061035156,426.70001220703125,419.1000061035156,421.70001220703125,421.70001220703125,32435695,0.0,0.0
|
||||
2023-04-17 00:00:00+01:00,423.70001220703125,427.635009765625,415.3999938964844,420.29998779296875,420.29998779296875,37715986,0.0,0.0
|
||||
2023-04-24 00:00:00+01:00,418.1000061035156,423.0,415.29998779296875,423.0,423.0,34331974,0.0,0.0
|
||||
2023-05-01 00:00:00+01:00,423.3999938964844,426.1000061035156,406.3999938964844,414.6000061035156,414.6000061035156,40446519,0.0,0.0
|
||||
2023-05-08 00:00:00+01:00,414.6000061035156,419.1000061035156,408.0,412.70001220703125,412.70001220703125,36950836,0.0,0.0
|
||||
2023-05-15 00:00:00+01:00,414.0,418.3999938964844,407.3999938964844,413.5,413.5,53109487,0.0,0.0
|
||||
2023-05-22 00:00:00+01:00,413.6000061035156,424.0,394.70001220703125,401.29998779296875,401.29998779296875,64363368,0.0,0.0
|
||||
2023-05-29 00:00:00+01:00,401.29998779296875,409.4779968261719,392.70001220703125,409.1000061035156,409.1000061035156,47587959,0.0,0.0
|
||||
2023-06-05 00:00:00+01:00,406.29998779296875,410.70001220703125,400.1000061035156,400.8999938964844,400.8999938964844,22494985,0.0,0.0
|
||||
2023-06-12 00:00:00+01:00,404.1000061035156,406.0,394.5,396.0,396.0,41531163,0.0,0.0
|
||||
2023-06-19 00:00:00+01:00,394.0,399.8999938964844,380.7200012207031,386.20001220703125,386.20001220703125,40439880,0.0,0.0
|
||||
2023-06-26 00:00:00+01:00,387.20001220703125,397.0,382.8999938964844,395.20001220703125,395.20001220703125,27701915,0.0,0.0
|
||||
2023-07-03 00:00:00+01:00,396.5,399.79998779296875,380.1000061035156,381.79998779296875,381.79998779296875,26005305,0.0,0.0
|
||||
2023-07-10 00:00:00+01:00,380.0,392.29998779296875,379.40399169921875,386.0,386.0,29789300,0.0,0.0
|
||||
2023-07-17 00:00:00+01:00,385.0,389.5,384.2510070800781,387.1000061035156,387.1000061035156,0,0.0,0.0
|
|
|
@ -0,0 +1,42 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2020-09-30 00:00:00-04:00,4.40000009536743,4.44999980926514,4.01999998092651,4.44999980926514,4.44999980926514,22600,0,0
|
||||
2020-09-29 00:00:00-04:00,4.3899998664856,4.40000009536743,4.13000011444092,4.30000019073486,4.30000019073486,10800,0,0
|
||||
2020-09-28 00:00:00-04:00,4.09000015258789,4.25,4.09000015258789,4.25,4.25,8000,0,0
|
||||
2020-09-25 00:00:00-04:00,3.95000004768372,4.09999990463257,3.95000004768372,4.05000019073486,4.05000019073486,13500,0,0
|
||||
2020-09-24 00:00:00-04:00,3.84999990463257,4,3.84999990463257,4,4,8800,0,0
|
||||
2020-09-23 00:00:00-04:00,3.99000000953674,4,3.99000000953674,4,4,5900,0,0
|
||||
2020-09-22 00:00:00-04:00,3.90000009536743,4.09999990463257,3.84999990463257,4.09999990463257,4.09999990463257,3100,0,0
|
||||
2020-09-21 00:00:00-04:00,4.09999990463257,4.09999990463257,4.09999990463257,4.09999990463257,4.09999990463257,1200,0,0
|
||||
2020-09-18 00:00:00-04:00,3.92000007629395,4.09999990463257,3.92000007629395,4.09999990463257,4.09999990463257,27200,0,0
|
||||
2020-09-17 00:00:00-04:00,3.90000009536743,3.99000000953674,3.8199999332428,3.99000000953674,3.99000000953674,3300,0,0
|
||||
2020-09-16 00:00:00-04:00,3.79999995231628,4,3.79999995231628,4,4,3300,0,0
|
||||
2020-09-15 00:00:00-04:00,3.95000004768372,4,3.95000004768372,4,4,2400,0,0
|
||||
2020-09-14 00:00:00-04:00,3.96000003814697,4,3.96000003814697,4,4,800,0,0
|
||||
2020-09-11 00:00:00-04:00,3.95000004768372,3.97000002861023,3.72000002861023,3.97000002861023,3.97000002861023,5700,0,0
|
||||
2020-09-10 00:00:00-04:00,4,4.09999990463257,4,4.09999990463257,4.09999990463257,7100,0,0
|
||||
2020-09-09 00:00:00-04:00,3.5699999332428,4,3.5699999332428,4,4,18100,0,0
|
||||
2020-09-08 00:00:00-04:00,3.40000009536743,3.59999990463257,3.40000009536743,3.59999990463257,3.59999990463257,19500,0,0
|
||||
2020-09-04 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,400,0,0
|
||||
2020-09-03 00:00:00-04:00,3.58999991416931,3.58999991416931,3.58999991416931,3.58999991416931,3.58999991416931,0,0,0
|
||||
2020-09-02 00:00:00-04:00,3.5,3.58999991416931,3.5,3.58999991416931,3.58999991416931,2000,0,0
|
||||
2020-09-01 00:00:00-04:00,3.5,3.59999990463257,3.5,3.59999990463257,3.59999990463257,1200,0,0
|
||||
2020-08-31 00:00:00-04:00,3.15000009536743,3.70000004768372,3.15000009536743,3.70000004768372,3.70000004768372,26500,0,0
|
||||
2020-08-28 00:00:00-04:00,3.76999998092651,3.76999998092651,3.70000004768372,3.70000004768372,3.70000004768372,1600,0,0
|
||||
2020-08-27 00:00:00-04:00,3.65000009536743,3.65000009536743,3.65000009536743,3.65000009536743,3.65000009536743,0,0,0
|
||||
2020-08-26 00:00:00-04:00,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,0,0,0.1
|
||||
2020-08-25 00:00:00-04:00,3.40000009536743,3.70000004768372,3.40000009536743,3.70000004768372,3.70000004768372,2900,0,0
|
||||
2020-08-24 00:00:00-04:00,3.29999995231628,3.5,3.29999995231628,3.5,3.5,10000,0,0
|
||||
2020-08-21 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,150,0,0
|
||||
2020-08-20 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-19 00:00:00-04:00,3.40000009536743,3.5,3.40000009536743,3.5,3.5,9050,0,0
|
||||
2020-08-18 00:00:00-04:00,3.5,3.79999995231628,3.5,3.5,3.5,2250,0,0
|
||||
2020-08-17 00:00:00-04:00,2.79999995231628,3.70000004768372,2.79999995231628,3.70000004768372,3.70000004768372,5050,0,0
|
||||
2020-08-14 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-13 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-12 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-11 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-10 00:00:00-04:00,3.5,3.70000004768372,3.5,3.5,3.5,3300,0,0
|
||||
2020-08-07 00:00:00-04:00,3.5,3.79999995231628,3.5,3.79999995231628,3.79999995231628,2500,0,0
|
||||
2020-08-06 00:00:00-04:00,3.5,3.70000004768372,3.40000009536743,3.70000004768372,3.70000004768372,3000,0,0
|
||||
2020-08-05 00:00:00-04:00,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,0,0,0
|
||||
2020-08-04 00:00:00-04:00,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,0,0,0
|
|
|
@ -0,0 +1,42 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2020-09-30 00:00:00-04:00,4.40000009536743,4.44999980926514,4.01999998092651,4.44999980926514,4.44999980926514,22600,0,0
|
||||
2020-09-29 00:00:00-04:00,4.3899998664856,4.40000009536743,4.13000011444092,4.30000019073486,4.30000019073486,10800,0,0
|
||||
2020-09-28 00:00:00-04:00,4.09000015258789,4.25,4.09000015258789,4.25,4.25,8000,0,0
|
||||
2020-09-25 00:00:00-04:00,3.95000004768372,4.09999990463257,3.95000004768372,4.05000019073486,4.05000019073486,13500,0,0
|
||||
2020-09-24 00:00:00-04:00,3.84999990463257,4,3.84999990463257,4,4,8800,0,0
|
||||
2020-09-23 00:00:00-04:00,3.99000000953674,4,3.99000000953674,4,4,5900,0,0
|
||||
2020-09-22 00:00:00-04:00,3.90000009536743,4.09999990463257,3.84999990463257,4.09999990463257,4.09999990463257,3100,0,0
|
||||
2020-09-21 00:00:00-04:00,4.09999990463257,4.09999990463257,4.09999990463257,4.09999990463257,4.09999990463257,1200,0,0
|
||||
2020-09-18 00:00:00-04:00,3.92000007629395,4.09999990463257,3.92000007629395,4.09999990463257,4.09999990463257,27200,0,0
|
||||
2020-09-17 00:00:00-04:00,3.90000009536743,3.99000000953674,3.8199999332428,3.99000000953674,3.99000000953674,3300,0,0
|
||||
2020-09-16 00:00:00-04:00,3.79999995231628,4,3.79999995231628,4,4,3300,0,0
|
||||
2020-09-15 00:00:00-04:00,3.95000004768372,4,3.95000004768372,4,4,2400,0,0
|
||||
2020-09-14 00:00:00-04:00,3.96000003814697,4,3.96000003814697,4,4,800,0,0
|
||||
2020-09-11 00:00:00-04:00,3.95000004768372,3.97000002861023,3.72000002861023,3.97000002861023,3.97000002861023,5700,0,0
|
||||
2020-09-10 00:00:00-04:00,4,4.09999990463257,4,4.09999990463257,4.09999990463257,7100,0,0
|
||||
2020-09-09 00:00:00-04:00,3.5699999332428,4,3.5699999332428,4,4,18100,0,0
|
||||
2020-09-08 00:00:00-04:00,3.40000009536743,3.59999990463257,3.40000009536743,3.59999990463257,3.59999990463257,19500,0,0
|
||||
2020-09-04 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,400,0,0
|
||||
2020-09-03 00:00:00-04:00,3.58999991416931,3.58999991416931,3.58999991416931,3.58999991416931,3.58999991416931,0,0,0
|
||||
2020-09-02 00:00:00-04:00,3.5,3.58999991416931,3.5,3.58999991416931,3.58999991416931,2000,0,0
|
||||
2020-09-01 00:00:00-04:00,3.5,3.59999990463257,3.5,3.59999990463257,3.59999990463257,1200,0,0
|
||||
2020-08-31 00:00:00-04:00,3.15000009536743,3.70000004768372,3.15000009536743,3.70000004768372,3.70000004768372,26500,0,0
|
||||
2020-08-28 00:00:00-04:00,3.76999998092651,3.76999998092651,3.70000004768372,3.70000004768372,3.70000004768372,1600,0,0
|
||||
2020-08-27 00:00:00-04:00,3.65000009536743,3.65000009536743,3.65000009536743,3.65000009536743,3.65000009536743,0,0,0
|
||||
2020-08-26 00:00:00-04:00,0.370000004768372,0.370000004768372,0.370000004768372,0.370000004768372,0.370000004768372,0,0,0.1
|
||||
2020-08-25 00:00:00-04:00,3.40000009536743,3.70000004768372,3.40000009536743,3.70000004768372,3.70000004768372,2900,0,0
|
||||
2020-08-24 00:00:00-04:00,3.29999995231628,3.5,3.29999995231628,3.5,3.5,10000,0,0
|
||||
2020-08-21 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,150,0,0
|
||||
2020-08-20 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-19 00:00:00-04:00,3.40000009536743,3.5,3.40000009536743,3.5,3.5,9050,0,0
|
||||
2020-08-18 00:00:00-04:00,3.5,3.79999995231628,3.5,3.5,3.5,2250,0,0
|
||||
2020-08-17 00:00:00-04:00,2.79999995231628,3.70000004768372,2.79999995231628,3.70000004768372,3.70000004768372,5050,0,0
|
||||
2020-08-14 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-13 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-12 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-11 00:00:00-04:00,3.5,3.5,3.5,3.5,3.5,0,0,0
|
||||
2020-08-10 00:00:00-04:00,3.5,3.70000004768372,3.5,3.5,3.5,3300,0,0
|
||||
2020-08-07 00:00:00-04:00,3.5,3.79999995231628,3.5,3.79999995231628,3.79999995231628,2500,0,0
|
||||
2020-08-06 00:00:00-04:00,3.5,3.70000004768372,3.40000009536743,3.70000004768372,3.70000004768372,3000,0,0
|
||||
2020-08-05 00:00:00-04:00,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,0,0,0
|
||||
2020-08-04 00:00:00-04:00,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,3.70000004768372,0,0,0
|
|
|
@ -0,0 +1,30 @@
|
|||
Date,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits
|
||||
2023-06-09 00:00:00+02:00,34.7000,34.7100,33.2400,33.6200,33.6200,7148409,0,0
|
||||
2023-06-08 00:00:00+02:00,34.9000,34.9900,34.0400,34.3600,34.3600,10406999,0,0
|
||||
2023-06-07 00:00:00+02:00,34.5500,35.6400,34.3200,35.0900,35.0900,10118918,0,0
|
||||
2023-06-06 00:00:00+02:00,34.5000,34.8200,34.0500,34.4600,34.4600,9109709,0,0
|
||||
2023-06-05 00:00:00+02:00,35.0000,35.3000,34.2000,34.7000,34.7000,8791993,0,0
|
||||
2023-06-02 00:00:00+02:00,35.6900,36.1800,34.6000,34.9700,34.9700,8844549,0,0
|
||||
2023-06-01 00:00:00+02:00,35.2300,35.3800,34.2400,35.3500,35.3500,6721030,0,0
|
||||
2023-05-31 00:00:00+02:00,34.8,35.48,34.26,35.01,35.01,32605833,0,0
|
||||
2023-05-30 00:00:00+02:00,34.39,35.37,33.85,34.23,34.23,8970804,0,0
|
||||
2023-05-29 00:00:00+02:00,34.66,35.06,34.02,34.32,34.32,3912803,0,0
|
||||
2023-05-26 00:00:00+02:00,34.75,35.99,34.33,34.53,34.53,6744718,0,0
|
||||
2023-05-25 00:00:00+02:00,35.4,36.09,34.63,35.07,35.07,16900221,0,0
|
||||
2023-05-24 00:00:00+02:00,36.2,36.5,35.26,35.4,35.4,9049505,0,0
|
||||
2023-05-23 00:00:00+02:00,36.9,36.67,35.56,36.1,36.1,10797373,0,0
|
||||
2023-05-22 00:00:00+02:00,37.05,37.36,36.09,36.61,36.61,7132641,0,0
|
||||
2023-05-19 00:00:00+02:00,36.2,37.15,36.25,36.9,36.9,12648518,0,0
|
||||
2023-05-18 00:00:00+02:00,36.57,36.99,35.84,36.46,36.46,10674542,0,0
|
||||
2023-05-17 00:00:00+02:00,36.87,37.31,36.56,36.71,36.71,9892791,0,0
|
||||
2023-05-16 00:00:00+02:00,37.15,37.73,36.96,37.03,37.03,4706789,0,0
|
||||
2023-05-15 00:00:00+02:00,37.74,38.05,36.96,37.27,37.27,7890969,0,0
|
||||
2023-05-12 00:00:00+02:00,37.5,38.44,36.71,37.74,37.74,8724303,0,0
|
||||
2023-05-11 00:00:00+02:00,38.8,38.88,37.01,37.32,37.32,14371855,0,0
|
||||
2023-05-10 00:00:00+02:00,38.93,38.8,36.42,38.1,38.1,30393389,0,0
|
||||
2023-05-09 00:00:00+02:00,44.41,44.41,39.39,39.66,39.66,19833428,0,0
|
||||
2023-05-08 00:00:00+02:00,44.63,45.78,44.56,44.71,44.71,11092519,0,0
|
||||
2023-05-05 00:00:00+02:00,42.99,44.9,42.87,44.58,44.58,28539048,0,0
|
||||
2023-05-04 00:00:00+02:00,41.49,43.3,41.23,42.83,42.83,15506868,0,0
|
||||
2023-05-03 00:00:00+02:00,39.75,40.98,39.68,40.95,40.95,14657028,0,0
|
||||
2023-05-02 00:00:00+02:00,40.37,40.32,39.17,39.65,39.65,11818133,0,0
|
|
220
tests/prices.py
220
tests/prices.py
|
@ -566,7 +566,7 @@ class TestPriceRepair(unittest.TestCase):
|
|||
"High": [476, 476.5, 477, 480],
|
||||
"Low": [470.5, 470, 465.5, 468.26],
|
||||
"Close": [475, 473.5, 472, 473.5],
|
||||
"Adj Close": [475, 473.5, 472, 473.5],
|
||||
"Adj Close": [470.1, 468.6, 467.1, 468.6],
|
||||
"Volume": [2295613, 2245604, 3000287, 2635611]},
|
||||
index=_pd.to_datetime([_dt.date(2022, 10, 24),
|
||||
_dt.date(2022, 10, 17),
|
||||
|
@ -583,7 +583,7 @@ class TestPriceRepair(unittest.TestCase):
|
|||
|
||||
# Run test
|
||||
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1wk", tz_exchange, prepost=False, silent=True)
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1wk", tz_exchange, prepost=False)
|
||||
|
||||
# First test - no errors left
|
||||
for c in data_cols:
|
||||
|
@ -616,11 +616,11 @@ class TestPriceRepair(unittest.TestCase):
|
|||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
data_cols = ["Low", "High", "Open", "Close", "Adj Close"]
|
||||
df = _pd.DataFrame(data={"Open": [400, 398, 392.5, 417],
|
||||
"High": [421, 425, 419, 420.5],
|
||||
"Low": [400, 380.5, 376.5, 396],
|
||||
"Close": [410, 409.5, 402, 399],
|
||||
"Adj Close": [398.02, 397.53, 390.25, 387.34],
|
||||
df = _pd.DataFrame(data={"Open": [400, 398, 392.5, 417],
|
||||
"High": [421, 425, 419, 420.5],
|
||||
"Low": [400, 380.5, 376.5, 396],
|
||||
"Close": [410, 409.5, 402, 399],
|
||||
"Adj Close": [393.91, 393.43, 386.22, 383.34],
|
||||
"Volume": [3232600, 3773900, 10835000, 4257900]},
|
||||
index=_pd.to_datetime([_dt.date(2020, 3, 30),
|
||||
_dt.date(2020, 3, 23),
|
||||
|
@ -640,7 +640,7 @@ class TestPriceRepair(unittest.TestCase):
|
|||
df.index = df.index.tz_localize(tz_exchange)
|
||||
df_bad.index = df_bad.index.tz_localize(tz_exchange)
|
||||
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1wk", tz_exchange, prepost=False, silent=True)
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1wk", tz_exchange, prepost=False)
|
||||
|
||||
# First test - no errors left
|
||||
for c in data_cols:
|
||||
|
@ -693,7 +693,7 @@ class TestPriceRepair(unittest.TestCase):
|
|||
df.index = df.index.tz_localize(tz_exchange)
|
||||
df_bad.index = df_bad.index.tz_localize(tz_exchange)
|
||||
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1d", tz_exchange, prepost=False, silent=True)
|
||||
df_repaired = dat._fix_unit_random_mixups(df_bad, "1d", tz_exchange, prepost=False)
|
||||
|
||||
# First test - no errors left
|
||||
for c in data_cols:
|
||||
|
@ -717,46 +717,55 @@ class TestPriceRepair(unittest.TestCase):
|
|||
# Some 100x errors are not sporadic.
|
||||
# Sometimes Yahoo suddenly shifts from cents->$ from some recent date.
|
||||
|
||||
tkr = "SSW.JO"
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
tkrs = ['AET.L', 'SSW.JO']
|
||||
for tkr in tkrs:
|
||||
for interval in ['1d', '1wk']:
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
data_cols = ["Low", "High", "Open", "Close", "Adj Close"]
|
||||
_dp = os.path.dirname(__file__)
|
||||
df_bad = _pd.read_csv(os.path.join(_dp, "data", tkr.replace('.', '-')+"-100x-error.csv"), index_col="Date")
|
||||
df_bad.index = _pd.to_datetime(df_bad.index)
|
||||
df_bad = df_bad.sort_index()
|
||||
data_cols = ["Low", "High", "Open", "Close", "Adj Close"]
|
||||
_dp = os.path.dirname(__file__)
|
||||
fp = os.path.join(_dp, "data", tkr.replace('.','-') + '-' + interval + "-100x-error.csv")
|
||||
if not os.path.isfile(fp):
|
||||
continue
|
||||
df_bad = _pd.read_csv(fp, index_col="Date")
|
||||
df_bad.index = _pd.to_datetime(df_bad.index, utc=True).tz_convert(tz_exchange)
|
||||
df_bad = df_bad.sort_index()
|
||||
|
||||
df = df_bad.copy()
|
||||
for d in data_cols:
|
||||
df.loc[:'2023-05-31', d] *= 0.01 # fix error
|
||||
df = df_bad.copy()
|
||||
fp = os.path.join(_dp, "data", tkr.replace('.','-') + '-' + interval + "-100x-error-fixed.csv")
|
||||
df = _pd.read_csv(fp, index_col="Date")
|
||||
df.index = _pd.to_datetime(df.index, utc=True).tz_convert(tz_exchange)
|
||||
df = df.sort_index()
|
||||
|
||||
df_repaired = dat._fix_unit_switch(df_bad, "1d", tz_exchange)
|
||||
df_repaired = df_repaired.sort_index()
|
||||
df_repaired = dat._fix_unit_switch(df_bad, interval, tz_exchange)
|
||||
df_repaired = df_repaired.sort_index()
|
||||
|
||||
# First test - no errors left
|
||||
for c in data_cols:
|
||||
try:
|
||||
self.assertTrue(_np.isclose(df_repaired[c], df[c], rtol=1e-2).all())
|
||||
except AssertionError:
|
||||
print(df_repaired[c])
|
||||
print(df[c])
|
||||
print(f"TEST FAIL on column '{c}")
|
||||
raise
|
||||
# First test - no errors left
|
||||
for c in data_cols:
|
||||
try:
|
||||
self.assertTrue(_np.isclose(df_repaired[c], df[c], rtol=1e-2).all())
|
||||
except:
|
||||
print("- repaired:")
|
||||
print(df_repaired[c])
|
||||
print("- correct:")
|
||||
print(df[c])
|
||||
print(f"TEST FAIL on column '{c}' (tkr={tkr} interval={interval})")
|
||||
raise
|
||||
|
||||
# Second test - all differences should be either ~1x or ~100x
|
||||
ratio = df_bad[data_cols].values / df[data_cols].values
|
||||
ratio = ratio.round(2)
|
||||
# - round near-100 ratio to 100:
|
||||
f = ratio > 90
|
||||
ratio[f] = (ratio[f] / 10).round().astype(int) * 10 # round ratio to nearest 10
|
||||
# - now test
|
||||
f_100 = ratio == 100
|
||||
f_1 = ratio == 1
|
||||
self.assertTrue((f_100 | f_1).all())
|
||||
# Second test - all differences should be either ~1x or ~100x
|
||||
ratio = df_bad[data_cols].values / df[data_cols].values
|
||||
ratio = ratio.round(2)
|
||||
# - round near-100 ratio to 100:
|
||||
f = ratio > 90
|
||||
ratio[f] = (ratio[f] / 10).round().astype(int) * 10 # round ratio to nearest 10
|
||||
# - now test
|
||||
f_100 = (ratio == 100) | (ratio == 0.01)
|
||||
f_1 = ratio == 1
|
||||
self.assertTrue((f_100 | f_1).all())
|
||||
|
||||
self.assertTrue("Repaired?" in df_repaired.columns)
|
||||
self.assertFalse(df_repaired["Repaired?"].isna().any())
|
||||
self.assertTrue("Repaired?" in df_repaired.columns)
|
||||
self.assertFalse(df_repaired["Repaired?"].isna().any())
|
||||
|
||||
def test_repair_zeroes_daily(self):
|
||||
tkr = "BBIL.L"
|
||||
|
@ -859,35 +868,6 @@ class TestPriceRepair(unittest.TestCase):
|
|||
self.assertFalse(repaired_df["Repaired?"].isna().any())
|
||||
|
||||
def test_repair_bad_stock_split(self):
|
||||
bad_tkrs = ['4063.T', 'ALPHA.PA', 'CNE.L', 'MOB.ST', 'SPM.MI']
|
||||
for tkr in bad_tkrs:
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
_dp = os.path.dirname(__file__)
|
||||
df_bad = _pd.read_csv(os.path.join(_dp, "data", tkr.replace('.', '-')+"-bad-stock-split.csv"), index_col="Date")
|
||||
df_bad.index = _pd.to_datetime(df_bad.index)
|
||||
|
||||
repaired_df = dat._fix_bad_stock_split(df_bad, "1d", tz_exchange)
|
||||
|
||||
correct_df = _pd.read_csv(os.path.join(_dp, "data", tkr.replace('.', '-')+"-bad-stock-split-fixed.csv"), index_col="Date")
|
||||
correct_df.index = _pd.to_datetime(correct_df.index)
|
||||
|
||||
repaired_df = repaired_df.sort_index()
|
||||
correct_df = correct_df.sort_index()
|
||||
for c in ["Open", "Low", "High", "Close", "Adj Close", "Volume"]:
|
||||
try:
|
||||
self.assertTrue(_np.isclose(repaired_df[c], correct_df[c], rtol=5e-6).all())
|
||||
except AssertionError:
|
||||
print(f"tkr={tkr} COLUMN={c}")
|
||||
print("- repaired_df")
|
||||
print(repaired_df)
|
||||
print("- correct_df[c]:")
|
||||
print(correct_df[c])
|
||||
print("- diff:")
|
||||
print(repaired_df[c] - correct_df[c])
|
||||
raise
|
||||
|
||||
# Stocks that split in 2022 but no problems in Yahoo data,
|
||||
# so repair should change nothing
|
||||
good_tkrs = ['AMZN', 'DXCM', 'FTNT', 'GOOG', 'GME', 'PANW', 'SHOP', 'TSLA']
|
||||
|
@ -900,7 +880,71 @@ class TestPriceRepair(unittest.TestCase):
|
|||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
_dp = os.path.dirname(__file__)
|
||||
df_good = dat.history(period='2y', interval=interval, auto_adjust=False)
|
||||
df_good = dat.history(start='2020-01-01', end=_dt.date.today(), interval=interval, auto_adjust=False)
|
||||
|
||||
repaired_df = dat._fix_bad_stock_split(df_good, interval, tz_exchange)
|
||||
|
||||
# Expect no change from repair
|
||||
df_good = df_good.sort_index()
|
||||
repaired_df = repaired_df.sort_index()
|
||||
for c in ["Open", "Low", "High", "Close", "Adj Close", "Volume"]:
|
||||
try:
|
||||
self.assertTrue((repaired_df[c].to_numpy() == df_good[c].to_numpy()).all())
|
||||
except:
|
||||
print(f"tkr={tkr} interval={interval} COLUMN={c}")
|
||||
df_dbg = df_good[[c]].join(repaired_df[[c]], lsuffix='.good', rsuffix='.repaired')
|
||||
f_diff = repaired_df[c].to_numpy() != df_good[c].to_numpy()
|
||||
print(df_dbg[f_diff | _np.roll(f_diff, 1) | _np.roll(f_diff, -1)])
|
||||
raise
|
||||
|
||||
bad_tkrs = ['4063.T', 'ALPHA.PA', 'AV.L', 'CNE.L', 'MOB.ST', 'SPM.MI']
|
||||
bad_tkrs.append('LA.V') # special case - stock split error is 3 years ago! why not fixed?
|
||||
for tkr in bad_tkrs:
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
_dp = os.path.dirname(__file__)
|
||||
interval = '1d'
|
||||
fp = os.path.join(_dp, "data", tkr.replace('.','-')+'-'+interval+"-bad-stock-split.csv")
|
||||
if not os.path.isfile(fp):
|
||||
interval = '1wk'
|
||||
fp = os.path.join(_dp, "data", tkr.replace('.','-')+'-'+interval+"-bad-stock-split.csv")
|
||||
df_bad = _pd.read_csv(fp, index_col="Date")
|
||||
df_bad.index = _pd.to_datetime(df_bad.index, utc=True)
|
||||
|
||||
repaired_df = dat._fix_bad_stock_split(df_bad, "1d", tz_exchange)
|
||||
|
||||
fp = os.path.join(_dp, "data", tkr.replace('.','-')+'-'+interval+"-bad-stock-split-fixed.csv")
|
||||
correct_df = _pd.read_csv(fp, index_col="Date")
|
||||
correct_df.index = _pd.to_datetime(correct_df.index)
|
||||
|
||||
repaired_df = repaired_df.sort_index()
|
||||
correct_df = correct_df.sort_index()
|
||||
for c in ["Open", "Low", "High", "Close", "Adj Close", "Volume"]:
|
||||
try:
|
||||
self.assertTrue(_np.isclose(repaired_df[c], correct_df[c], rtol=5e-6).all())
|
||||
except AssertionError:
|
||||
print(f"tkr={tkr} COLUMN={c}")
|
||||
# print("- repaired_df")
|
||||
# print(repaired_df)
|
||||
# print("- correct_df[c]:")
|
||||
# print(correct_df[c])
|
||||
# print("- diff:")
|
||||
# print(repaired_df[c] - correct_df[c])
|
||||
raise
|
||||
|
||||
# Had very high price volatility in Jan-2021 around split date that could
|
||||
# be mistaken for missing stock split adjustment. And old logic did think
|
||||
# column 'High' required fixing - wrong!
|
||||
sketchy_tkrs = ['FIZZ']
|
||||
intervals = ['1wk']
|
||||
for tkr in sketchy_tkrs:
|
||||
for interval in intervals:
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
_dp = os.path.dirname(__file__)
|
||||
df_good = dat.history(start='2020-11-30', end='2021-04-01', interval=interval, auto_adjust=False)
|
||||
|
||||
repaired_df = dat._fix_bad_stock_split(df_good, interval, tz_exchange)
|
||||
|
||||
|
@ -917,6 +961,36 @@ class TestPriceRepair(unittest.TestCase):
|
|||
print(df_dbg[f_diff | _np.roll(f_diff, 1) | _np.roll(f_diff, -1)])
|
||||
raise
|
||||
|
||||
def test_repair_missing_div_adjust(self):
|
||||
tkr = '8TRA.DE'
|
||||
|
||||
dat = yf.Ticker(tkr, session=self.session)
|
||||
tz_exchange = dat.fast_info["timezone"]
|
||||
|
||||
_dp = os.path.dirname(__file__)
|
||||
df_bad = _pd.read_csv(os.path.join(_dp, "data", tkr.replace('.','-')+"-1d-missing-div-adjust.csv"), index_col="Date")
|
||||
df_bad.index = _pd.to_datetime(df_bad.index)
|
||||
|
||||
repaired_df = dat._fix_missing_div_adjust(df_bad, "1d", tz_exchange)
|
||||
|
||||
correct_df = _pd.read_csv(os.path.join(_dp, "data", tkr.replace('.','-')+"-1d-missing-div-adjust-fixed.csv"), index_col="Date")
|
||||
correct_df.index = _pd.to_datetime(correct_df.index)
|
||||
|
||||
repaired_df = repaired_df.sort_index()
|
||||
correct_df = correct_df.sort_index()
|
||||
for c in ["Open", "Low", "High", "Close", "Adj Close", "Volume"]:
|
||||
try:
|
||||
self.assertTrue(_np.isclose(repaired_df[c], correct_df[c], rtol=5e-6).all())
|
||||
except:
|
||||
print(f"tkr={tkr} COLUMN={c}")
|
||||
print("- repaired_df")
|
||||
print(repaired_df)
|
||||
print("- correct_df[c]:")
|
||||
print(correct_df[c])
|
||||
print("- diff:")
|
||||
print(repaired_df[c] - correct_df[c])
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
389
yfinance/base.py
389
yfinance/base.py
|
@ -111,9 +111,8 @@ class TickerBase:
|
|||
Adjust all OHLC automatically? Default is True
|
||||
back_adjust: bool
|
||||
Back-adjusted data to mimic true historical prices
|
||||
repair: bool or "silent"
|
||||
repair: bool
|
||||
Detect currency unit 100x mixups and attempt repair.
|
||||
If True, fix & print summary. If "silent", just fix.
|
||||
Default is False
|
||||
keepna: bool
|
||||
Keep NaN rows returned by Yahoo?
|
||||
|
@ -274,6 +273,8 @@ class TickerBase:
|
|||
raise Exception(f'{self.ticker}: {err_msg}')
|
||||
else:
|
||||
logger.error(f'{self.ticker}: {err_msg}')
|
||||
if self._reconstruct_start_interval is not None and self._reconstruct_start_interval == interval:
|
||||
self._reconstruct_start_interval = None
|
||||
return utils.empty_df()
|
||||
|
||||
# parse quotes
|
||||
|
@ -291,6 +292,8 @@ class TickerBase:
|
|||
raise Exception(f'{self.ticker}: {err_msg}')
|
||||
else:
|
||||
logger.error(f'{self.ticker}: {err_msg}')
|
||||
if self._reconstruct_start_interval is not None and self._reconstruct_start_interval == interval:
|
||||
self._reconstruct_start_interval = None
|
||||
return shared._DFS[self.ticker]
|
||||
logger.debug(f'{self.ticker}: yfinance received OHLC data: {quotes.index[0]} -> {quotes.index[-1]}')
|
||||
|
||||
|
@ -395,13 +398,17 @@ class TickerBase:
|
|||
|
||||
df = df[~df.index.duplicated(keep='first')] # must do before repair
|
||||
|
||||
if repair in [True, "silent"]:
|
||||
if isinstance(repair, str) and repair=='silent':
|
||||
utils.log_once(logging.WARNING, f"yfinance: Ticker.history(repair='silent') value is deprecated and will be removed in future version. Repair now silent by default, use logging module to increase verbosity.")
|
||||
repair = True
|
||||
if repair:
|
||||
# Do this before auto/back adjust
|
||||
logger.debug(f'{self.ticker}: checking OHLC for repairs ...')
|
||||
df = self._fix_zeroes(df, interval, tz_exchange, prepost, silent=(repair == "silent"))
|
||||
df = self._fix_unit_mixups(df, interval, tz_exchange, prepost, silent=(repair == "silent"))
|
||||
df = self._fix_missing_div_adjust(df, interval, tz_exchange)
|
||||
df = self._fix_unit_mixups(df, interval, tz_exchange, prepost)
|
||||
df = self._fix_bad_stock_split(df, interval, tz_exchange)
|
||||
# Must repair 100x and split errors before price reconstruction
|
||||
df = self._fix_zeroes(df, interval, tz_exchange, prepost)
|
||||
df = self._fix_missing_div_adjust(df, interval, tz_exchange)
|
||||
df = df.sort_index()
|
||||
|
||||
# Auto/back adjust
|
||||
|
@ -442,12 +449,14 @@ class TickerBase:
|
|||
|
||||
logger.debug(f'{self.ticker}: yfinance returning OHLC: {df.index[0]} -> {df.index[-1]}')
|
||||
|
||||
if self._reconstruct_start_interval is not None and self._reconstruct_start_interval == interval:
|
||||
self._reconstruct_start_interval = None
|
||||
return df
|
||||
|
||||
# ------------------------
|
||||
|
||||
@utils.log_indent_decorator
|
||||
def _reconstruct_intervals_batch(self, df, interval, prepost, tag=-1, silent=False):
|
||||
def _reconstruct_intervals_batch(self, df, interval, prepost, tag=-1):
|
||||
# Reconstruct values in df using finer-grained price data. Delimiter marks what to reconstruct
|
||||
logger = utils.get_yf_logger()
|
||||
|
||||
|
@ -488,8 +497,8 @@ class TickerBase:
|
|||
# Limit max reconstruction depth to 2:
|
||||
if self._reconstruct_start_interval is None:
|
||||
self._reconstruct_start_interval = interval
|
||||
if interval not in [self._reconstruct_start_interval, nexts[self._reconstruct_start_interval]]:
|
||||
logger.debug(f"{self.ticker}: Price repair has hit max depth of 2 ('{self._reconstruct_start_interval}'->'{interval}'->'{sub_interval}')")
|
||||
if interval != self._reconstruct_start_interval:
|
||||
logger.debug(f"{self.ticker}: Price repair has hit max depth of 1 ('%s'->'%s')", self._reconstruct_start_interval, interval)
|
||||
return df
|
||||
|
||||
df = df.sort_index()
|
||||
|
@ -602,7 +611,7 @@ class TickerBase:
|
|||
else:
|
||||
msg += f" {start_d}"
|
||||
msg += ", too old, Yahoo will reject request for finer-grain data"
|
||||
logger.warning(msg)
|
||||
logger.info(msg)
|
||||
continue
|
||||
|
||||
td_1d = _datetime.timedelta(days=1)
|
||||
|
@ -627,29 +636,26 @@ class TickerBase:
|
|||
if min_dt is not None:
|
||||
fetch_start = max(min_dt.date(), fetch_start)
|
||||
logger.debug(f"Fetching {sub_interval} prepost={prepost} {fetch_start}->{fetch_end}")
|
||||
r = "silent" if silent else True
|
||||
df_fine = self.history(start=fetch_start, end=fetch_end, interval=sub_interval, auto_adjust=False, actions=True, prepost=prepost, repair=r, keepna=True)
|
||||
df_fine = self.history(start=fetch_start, end=fetch_end, interval=sub_interval, auto_adjust=False, actions=True, prepost=prepost, repair=True, keepna=True)
|
||||
if df_fine is None or df_fine.empty:
|
||||
if not silent:
|
||||
msg = f"Cannot reconstruct {interval} block starting"
|
||||
if intraday:
|
||||
msg += f" {start_dt}"
|
||||
else:
|
||||
msg += f" {start_d}"
|
||||
msg += ", too old, Yahoo is rejecting request for finer-grain data"
|
||||
logger.warning(msg)
|
||||
msg = f"Cannot reconstruct {interval} block starting"
|
||||
if intraday:
|
||||
msg += f" {start_dt}"
|
||||
else:
|
||||
msg += f" {start_d}"
|
||||
msg += ", too old, Yahoo is rejecting request for finer-grain data"
|
||||
logger.debug(msg)
|
||||
continue
|
||||
# Discard the buffer
|
||||
df_fine = df_fine.loc[g[0]: g[-1] + itds[sub_interval] - _datetime.timedelta(milliseconds=1)].copy()
|
||||
if df_fine.empty:
|
||||
if not silent:
|
||||
msg = f"Cannot reconstruct {interval} block range"
|
||||
if intraday:
|
||||
msg += f" {start_dt}->{end_dt}"
|
||||
else:
|
||||
msg += f" {start_d}->{end_d}"
|
||||
msg += ", Yahoo not returning finer-grain data within range"
|
||||
logger.warning(msg)
|
||||
msg = f"Cannot reconstruct {interval} block range"
|
||||
if intraday:
|
||||
msg += f" {start_dt}->{end_dt}"
|
||||
else:
|
||||
msg += f" {start_d}->{end_d}"
|
||||
msg += ", Yahoo not returning finer-grain data within range"
|
||||
logger.debug(msg)
|
||||
continue
|
||||
|
||||
df_fine["ctr"] = 0
|
||||
|
@ -683,12 +689,13 @@ class TickerBase:
|
|||
df_fine["diff"] = df_fine["intervalID"].diff()
|
||||
new_index = np.append([df_fine.index[0]], df_fine.index[df_fine["intervalID"].diff() > 0])
|
||||
df_new.index = new_index
|
||||
logger.debug('df_new:' + '\n' + str(df_new))
|
||||
|
||||
# Calibrate!
|
||||
common_index = np.intersect1d(df_block.index, df_new.index)
|
||||
if len(common_index) == 0:
|
||||
# Can't calibrate so don't attempt repair
|
||||
logger.warning(f"Can't calibrate {interval} block starting {start_d} so aborting repair")
|
||||
logger.info(f"Can't calibrate {interval} block starting {start_d} so aborting repair")
|
||||
continue
|
||||
# First, attempt to calibrate the 'Adj Close' column. OK if cannot.
|
||||
# Only necessary for 1d interval, because the 1h data is not div-adjusted.
|
||||
|
@ -733,15 +740,16 @@ class TickerBase:
|
|||
|
||||
# Check whether 'df_fine' has different split-adjustment.
|
||||
# If different, then adjust to match 'df'
|
||||
df_new_calib = df_new[df_new.index.isin(common_index)][price_cols].to_numpy()
|
||||
df_block_calib = df_block[df_block.index.isin(common_index)][price_cols].to_numpy()
|
||||
calib_cols = ['Open', 'Close']
|
||||
df_new_calib = df_new[df_new.index.isin(common_index)][calib_cols].to_numpy()
|
||||
df_block_calib = df_block[df_block.index.isin(common_index)][calib_cols].to_numpy()
|
||||
calib_filter = (df_block_calib != tag)
|
||||
if not calib_filter.any():
|
||||
# Can't calibrate so don't attempt repair
|
||||
logger.warning(f"Can't calibrate {interval} block starting {start_d} so aborting repair")
|
||||
logger.info(f"Can't calibrate {interval} block starting {start_d} so aborting repair")
|
||||
continue
|
||||
# Avoid divide-by-zero warnings:
|
||||
for j in range(len(price_cols)):
|
||||
for j in range(len(calib_cols)):
|
||||
f = ~calib_filter[:, j]
|
||||
if f.any():
|
||||
df_block_calib[f, j] = 1
|
||||
|
@ -751,7 +759,7 @@ class TickerBase:
|
|||
weights.index = df_new.index
|
||||
weights = weights[weights.index.isin(common_index)].to_numpy().astype(float)
|
||||
weights = weights[:, None] # transpose
|
||||
weights = np.tile(weights, len(price_cols)) # 1D -> 2D
|
||||
weights = np.tile(weights, len(calib_cols)) # 1D -> 2D
|
||||
weights = weights[calib_filter] # flatten
|
||||
ratio = np.average(ratios, weights=weights)
|
||||
logger.debug(f"Price calibration ratio (raw) = {ratio:6f}")
|
||||
|
@ -821,13 +829,13 @@ class TickerBase:
|
|||
return df_v2
|
||||
|
||||
@utils.log_indent_decorator
|
||||
def _fix_unit_mixups(self, df, interval, tz_exchange, prepost, silent=False):
|
||||
def _fix_unit_mixups(self, df, interval, tz_exchange, prepost):
|
||||
df2 = self._fix_unit_switch(df, interval, tz_exchange)
|
||||
df3 = self._fix_unit_random_mixups(df2, interval, tz_exchange, prepost, silent)
|
||||
df3 = self._fix_unit_random_mixups(df2, interval, tz_exchange, prepost)
|
||||
return df3
|
||||
|
||||
@utils.log_indent_decorator
|
||||
def _fix_unit_random_mixups(self, df, interval, tz_exchange, prepost, silent=False):
|
||||
def _fix_unit_random_mixups(self, df, interval, tz_exchange, prepost):
|
||||
# Sometimes Yahoo returns few prices in cents/pence instead of $/£
|
||||
# I.e. 100x bigger
|
||||
# 2 ways this manifests:
|
||||
|
@ -844,7 +852,7 @@ class TickerBase:
|
|||
return df
|
||||
if df.shape[0] == 1:
|
||||
# Need multiple rows to confidently identify outliers
|
||||
logger.warning("price-repair-100x: Cannot check single-row table for 100x price errors")
|
||||
logger.info("price-repair-100x: Cannot check single-row table for 100x price errors")
|
||||
if "Repaired?" not in df.columns:
|
||||
df["Repaired?"] = False
|
||||
return df
|
||||
|
@ -869,7 +877,7 @@ class TickerBase:
|
|||
else:
|
||||
df2_zeroes = None
|
||||
if df2.shape[0] <= 1:
|
||||
logger.warning("price-repair-100x: Insufficient good data for detecting 100x price errors")
|
||||
logger.info("price-repair-100x: Insufficient good data for detecting 100x price errors")
|
||||
if "Repaired?" not in df.columns:
|
||||
df["Repaired?"] = False
|
||||
return df
|
||||
|
@ -892,7 +900,7 @@ class TickerBase:
|
|||
df2.loc[fi, c] = tag
|
||||
|
||||
n_before = (df2_data == tag).sum()
|
||||
df2 = self._reconstruct_intervals_batch(df2, interval, prepost, tag, silent)
|
||||
df2 = self._reconstruct_intervals_batch(df2, interval, prepost, tag)
|
||||
df2_tagged = df2[data_cols].to_numpy() == tag
|
||||
n_after = (df2[data_cols].to_numpy() == tag).sum()
|
||||
|
||||
|
@ -938,7 +946,7 @@ class TickerBase:
|
|||
|
||||
n_fixed = n_before - n_after_crude
|
||||
n_fixed_crudely = n_after - n_after_crude
|
||||
if not silent and n_fixed > 0:
|
||||
if n_fixed > 0:
|
||||
report_msg = f"{self.ticker}: fixed {n_fixed}/{n_before} currency unit mixups "
|
||||
if n_fixed_crudely > 0:
|
||||
report_msg += f"({n_fixed_crudely} crudely) "
|
||||
|
@ -981,7 +989,7 @@ class TickerBase:
|
|||
return self._fix_prices_sudden_change(df, interval, tz_exchange, 100.0)
|
||||
|
||||
@utils.log_indent_decorator
|
||||
def _fix_zeroes(self, df, interval, tz_exchange, prepost, silent=False):
|
||||
def _fix_zeroes(self, df, interval, tz_exchange, prepost):
|
||||
# Sometimes Yahoo returns prices=0 or NaN when trades occurred.
|
||||
# But most times when prices=0 or NaN returned is because no trades.
|
||||
# Impossible to distinguish, so only attempt repair if few or rare.
|
||||
|
@ -1039,7 +1047,7 @@ class TickerBase:
|
|||
return df
|
||||
if f_prices_bad.sum() == len(price_cols) * len(df2):
|
||||
# Need some good data to calibrate
|
||||
logger.warning("price-repair-missing: No good data for calibration so cannot fix price=0 bad data")
|
||||
logger.info("price-repair-missing: No good data for calibration so cannot fix price=0 bad data")
|
||||
if "Repaired?" not in df.columns:
|
||||
df["Repaired?"] = False
|
||||
return df
|
||||
|
@ -1061,12 +1069,12 @@ class TickerBase:
|
|||
df2_tagged = df2[data_cols].to_numpy() == tag
|
||||
n_before = df2_tagged.sum()
|
||||
dts_tagged = df2.index[df2_tagged.any(axis=1)]
|
||||
df2 = self._reconstruct_intervals_batch(df2, interval, prepost, tag, silent)
|
||||
df2 = self._reconstruct_intervals_batch(df2, interval, prepost, tag)
|
||||
df2_tagged = df2[data_cols].to_numpy() == tag
|
||||
n_after = df2_tagged.sum()
|
||||
dts_not_repaired = df2.index[df2_tagged.any(axis=1)]
|
||||
n_fixed = n_before - n_after
|
||||
if not silent and n_fixed > 0:
|
||||
if n_fixed > 0:
|
||||
msg = f"{self.ticker}: fixed {n_fixed}/{n_before} value=0 errors in {interval} price data"
|
||||
if n_fixed < 4:
|
||||
dts_repaired = sorted(list(set(dts_tagged).difference(dts_not_repaired)))
|
||||
|
@ -1106,6 +1114,7 @@ class TickerBase:
|
|||
|
||||
f_div = (df["Dividends"] != 0.0).to_numpy()
|
||||
if not f_div.any():
|
||||
logger.debug('div-adjust-repair: No dividends to check')
|
||||
return df
|
||||
|
||||
df2 = df.copy()
|
||||
|
@ -1119,17 +1128,19 @@ class TickerBase:
|
|||
if last_div_idx == 0:
|
||||
# Not enough data to recalculate the div-adjustment,
|
||||
# because need close day before
|
||||
logger.debug('div-adjust-repair: Insufficient data to recalculate div-adjustment')
|
||||
return df
|
||||
|
||||
# To determine if Yahoo messed up, analyse price data between today's dividend and
|
||||
# the previous dividend
|
||||
if len(div_indices) == 1:
|
||||
# No other divs in data
|
||||
start_idx = 0
|
||||
prev_idx = 0
|
||||
prev_dt = None
|
||||
else:
|
||||
start_idx = div_indices[-2]
|
||||
start_dt = df2.index[start_idx]
|
||||
f_no_adj = (df2['Close'] == df2['Adj Close']).to_numpy()[start_idx:last_div_idx]
|
||||
prev_idx = div_indices[-2]
|
||||
prev_dt = df2.index[prev_idx]
|
||||
f_no_adj = (df2['Close'] == df2['Adj Close']).to_numpy()[prev_idx:last_div_idx]
|
||||
threshold_pct = 0.5
|
||||
Yahoo_failed = (np.sum(f_no_adj) / len(f_no_adj)) > threshold_pct
|
||||
|
||||
|
@ -1139,9 +1150,16 @@ class TickerBase:
|
|||
last_div_row = df2.loc[last_div_dt]
|
||||
close_day_before = df2['Close'].iloc[last_div_idx - 1]
|
||||
adj = 1.0 - df2['Dividends'].iloc[last_div_idx] / close_day_before
|
||||
div = last_div_row['Dividends']
|
||||
msg = f'Correcting missing div-adjustment preceding div = {div} @ {last_div_dt.date()} (prev_dt={prev_dt})'
|
||||
logger.debug('div-adjust-repair: ' + msg)
|
||||
|
||||
df2.loc[start_dt:last_div_dt, 'Adj Close'] = adj * df2.loc[start_dt:last_div_dt, 'Close']
|
||||
df2.loc[:start_dt - _datetime.timedelta(seconds=1), 'Adj Close'] *= adj
|
||||
if interval == '1d':
|
||||
# exclusive
|
||||
df2.loc[:last_div_dt - _datetime.timedelta(seconds=1), 'Adj Close'] *= adj
|
||||
else:
|
||||
# inclusive
|
||||
df2.loc[:last_div_dt, 'Adj Close'] *= adj
|
||||
|
||||
return df2
|
||||
|
||||
|
@ -1166,6 +1184,7 @@ class TickerBase:
|
|||
df = df.sort_index(ascending=False)
|
||||
split_f = df['Stock Splits'].to_numpy() != 0
|
||||
if not split_f.any():
|
||||
logger.debug('price-repair-split: No splits in data')
|
||||
return df
|
||||
most_recent_split_day = df.index[split_f].max()
|
||||
split = df.loc[most_recent_split_day, 'Stock Splits']
|
||||
|
@ -1187,7 +1206,17 @@ class TickerBase:
|
|||
split_rcp = 1.0 / split
|
||||
interday = interval in ['1d', '1wk', '1mo', '3mo']
|
||||
|
||||
OHLC = ['Open', 'Low', 'High', 'Close']
|
||||
if change in [100.0, 0.01]:
|
||||
fix_type = '100x error'
|
||||
start_min = None
|
||||
else:
|
||||
fix_type = 'bad split'
|
||||
# start_min = 1 year before oldest split
|
||||
f = df['Stock Splits'].to_numpy() != 0.0
|
||||
start_min = (df.index[f].min() - _dateutil.relativedelta.relativedelta(years=1)).date()
|
||||
logger.debug(f'price-repair-split: start_min={start_min}')
|
||||
|
||||
OHLC = ['Open', 'High', 'Low', 'Close']
|
||||
OHLCA = OHLC + ['Adj Close']
|
||||
|
||||
# Do not attempt repair of the split is small,
|
||||
|
@ -1203,29 +1232,55 @@ class TickerBase:
|
|||
df2.index = df2.index.tz_convert(tz_exchange)
|
||||
n = df2.shape[0]
|
||||
|
||||
# If stock is currently suspended and not in USA, then usually Yahoo introduces
|
||||
# 100x errors into suspended intervals. Clue is no price change and 0 volume.
|
||||
# Better to use last active trading interval as baseline.
|
||||
f_no_activity = (df2['Low'] == df2['High']) & (df2['Volume']==0)
|
||||
appears_suspended = f_no_activity.any() and np.where(f_no_activity)[0][0]==0
|
||||
f_active = ~f_no_activity
|
||||
idx_latest_active = np.where(f_active & np.roll(f_active, 1))[0]
|
||||
if len(idx_latest_active) == 0:
|
||||
idx_latest_active = None
|
||||
else:
|
||||
idx_latest_active = idx_latest_active[0]
|
||||
logger.debug(f'price-repair-split: appears_suspended={appears_suspended}, idx_latest_active={idx_latest_active}')
|
||||
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
df_debug = df2.copy()
|
||||
df_debug = df_debug.drop(['Adj Close', 'Low', 'High', 'Volume', 'Dividends', 'Repaired?'], axis=1, errors='ignore')
|
||||
debug_cols = ['Low', 'High']
|
||||
|
||||
# Calculate daily price % change. To reduce effect of price volatility,
|
||||
# calculate change for each OHLC column and select value nearest 1.0.
|
||||
_1d_change_x = np.full((n, 4), 1.0)
|
||||
price_data = df2[OHLC].replace(0.0, 1.0).to_numpy()
|
||||
# calculate change for each OHLC column.
|
||||
if interday and interval != '1d' and split not in [100.0, 100, 0.001]:
|
||||
# Avoid using 'Low' and 'High'. For multiday intervals, these can be
|
||||
# very volatile so reduce ability to detect genuine stock split errors
|
||||
_1d_change_x = np.full((n, 2), 1.0)
|
||||
price_data = df2[['Open','Close']].replace(0.0, 1.0).to_numpy()
|
||||
else:
|
||||
_1d_change_x = np.full((n, 4), 1.0)
|
||||
price_data = df2[OHLC].replace(0.0, 1.0).to_numpy()
|
||||
_1d_change_x[1:] = price_data[1:, ] / price_data[:-1, ]
|
||||
diff = np.abs(_1d_change_x - 1.0)
|
||||
j_indices = np.argmin(diff, axis=1)
|
||||
_1d_change_minx = _1d_change_x[np.arange(n), j_indices]
|
||||
if interday and interval != '1d':
|
||||
# average change
|
||||
_1d_change_minx = np.average(_1d_change_x, axis=1)
|
||||
else:
|
||||
# change nearest to 1.0
|
||||
diff = np.abs(_1d_change_x - 1.0)
|
||||
j_indices = np.argmin(diff, axis=1)
|
||||
_1d_change_minx = _1d_change_x[np.arange(n), j_indices]
|
||||
f_na = np.isnan(_1d_change_minx)
|
||||
if f_na.any():
|
||||
# Possible if data was too old for reconstruction.
|
||||
_1d_change_minx[f_na] = 1.0
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
df_debug['1D change X'] = _1d_change_minx
|
||||
df_debug['1D change X'] = df_debug['1D change X'].round(2).astype('str')
|
||||
|
||||
# If all 1D changes are closer to 1.0 than split, exit
|
||||
split_max = max(split, split_rcp)
|
||||
if np.max(_1d_change_minx) < (split_max - 1) * 0.5 + 1 and np.min(_1d_change_minx) > 1.0 / ((split_max - 1) * 0.5 + 1):
|
||||
logger.info(f"price-repair-split: No bad splits detected")
|
||||
logger.info(f"price-repair-split: No {fix_type}s detected")
|
||||
return df
|
||||
|
||||
# Calculate the true price variance, i.e. remove effect of bad split-adjustments.
|
||||
|
@ -1244,12 +1299,14 @@ class TickerBase:
|
|||
# Only proceed if split adjustment far exceeds normal 1D changes
|
||||
largest_change_pct = 5 * sd_pct
|
||||
if interday and interval != '1d':
|
||||
largest_change_pct *= 5
|
||||
largest_change_pct *= 3
|
||||
if interval in ['1mo', '3mo']:
|
||||
largest_change_pct *= 2
|
||||
if max(split, split_rcp) < 1.0 + largest_change_pct:
|
||||
logger.info("price-repair-split: Split ratio too close to normal price volatility. Won't repair")
|
||||
# if logger.isEnabledFor(logging.DEBUG):
|
||||
# logger.debug(f"price-repair-split: my workings:")
|
||||
# logger.debug('\n' + str(df_debug))
|
||||
logger.debug(f"sd_pct = {sd_pct:.4f} largest_change_pct = {largest_change_pct:.4f}")
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug(f"sd_pct = {sd_pct:.4f} largest_change_pct = {largest_change_pct:.4f}")
|
||||
return df
|
||||
|
||||
# Now can detect bad split adjustments
|
||||
|
@ -1279,41 +1336,109 @@ class TickerBase:
|
|||
_1d_change_x = _1d_change_minx
|
||||
|
||||
r = _1d_change_x / split_rcp
|
||||
f1 = _1d_change_x < 1.0 / threshold
|
||||
f2 = _1d_change_x > threshold
|
||||
f = f1 | f2
|
||||
f_down = _1d_change_x < 1.0 / threshold
|
||||
f_up = _1d_change_x > threshold
|
||||
f = f_down | f_up
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
if not correct_columns_individually:
|
||||
df_debug['r'] = r
|
||||
df_debug['f1'] = f1
|
||||
df_debug['f2'] = f2
|
||||
df_debug['f_down'] = f_down
|
||||
df_debug['f_up'] = f_up
|
||||
df_debug['r'] = df_debug['r'].round(2).astype('str')
|
||||
else:
|
||||
for j in range(len(OHLC)):
|
||||
c = OHLC[j]
|
||||
df_debug[c + '_r'] = r[:, j]
|
||||
df_debug[c + '_f1'] = f1[:, j]
|
||||
df_debug[c + '_f2'] = f2[:, j]
|
||||
if c in debug_cols:
|
||||
df_debug[c + '_r'] = r[:, j]
|
||||
df_debug[c + '_f_down'] = f_down[:, j]
|
||||
df_debug[c + '_f_up'] = f_up[:, j]
|
||||
df_debug[c + '_r'] = df_debug[c + '_r'].round(2).astype('str')
|
||||
|
||||
|
||||
if not f.any():
|
||||
logger.info('price-repair-split: No bad split adjustments detected')
|
||||
logger.info(f'price-repair-split: No {fix_type}s detected')
|
||||
return df
|
||||
|
||||
def map_signals_to_ranges(f, f1):
|
||||
# if logger.isEnabledFor(logging.DEBUG):
|
||||
# logger.debug(f"price-repair-split: my workings:")
|
||||
# logger.debug('\n' + str(df_debug))
|
||||
|
||||
def map_signals_to_ranges(f, f_up, f_down):
|
||||
if not f.any():
|
||||
return []
|
||||
|
||||
true_indices = np.where(f)[0]
|
||||
ranges = []
|
||||
for i in range(len(true_indices) - 1):
|
||||
if i % 2 == 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f1[true_indices[i]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f1[true_indices[i]] else 'split'
|
||||
ranges.append((true_indices[i], true_indices[i + 1], adj))
|
||||
if len(true_indices) % 2 != 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f1[true_indices[-1]] else '1.0/split'
|
||||
|
||||
idx_first_f = np.where(f)[0][0]
|
||||
logger.debug(f'idx_latest_active={idx_latest_active} idx_first_f={idx_first_f}')
|
||||
if appears_suspended and (idx_latest_active is None or idx_latest_active >= idx_first_f):
|
||||
# baseline = 2nd index, because no active trading since latest split error
|
||||
|
||||
# First, process prices older than idx_latest_active:
|
||||
if idx_latest_active is None:
|
||||
true_indices_old = []
|
||||
else:
|
||||
adj = '1.0/split' if f1[true_indices[-1]] else 'split'
|
||||
ranges.append((true_indices[-1], len(f), adj))
|
||||
true_indices_old = [i for i in true_indices if i > idx_latest_active]
|
||||
if len(true_indices_old) > 0:
|
||||
for i in range(len(true_indices_old) - 1):
|
||||
if i % 2 == 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_down[true_indices_old[i]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_down[true_indices_old[i]] else 'split'
|
||||
ranges.append((true_indices_old[i], true_indices_old[i+1], adj))
|
||||
|
||||
if len(true_indices_old) % 2 != 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_down[true_indices_old[-1]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_down[true_indices_old[-1]] else 'split'
|
||||
ranges.append((true_indices_old[-1], len(f), adj))
|
||||
|
||||
# Next, process prices more recent than idx_latest_active:
|
||||
true_indices_recent = [i for i in true_indices if i not in true_indices_old]
|
||||
if len(true_indices_recent) > 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_up[true_indices_recent[0]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_up[true_indices_recent[0]] else 'split'
|
||||
ranges.append((0, true_indices_recent[0], adj))
|
||||
|
||||
for i in range(1, len(true_indices_recent) - 1):
|
||||
if i % 2 == 1:
|
||||
if split > 1.0:
|
||||
adj = '1.0/split' if f_up[true_indices_recent[i]] else 'split'
|
||||
else:
|
||||
adj = 'split' if f_up[true_indices_recent[i]] else '1.0/split'
|
||||
ranges.append((true_indices_recent[i], true_indices_recent[i + 1], adj))
|
||||
|
||||
if len(true_indices_recent) % 2 == 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_down[true_indices_recent[-1]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_down[true_indices_recent[-1]] else 'split'
|
||||
ranges.append((true_indices_recent[-1], len(f), adj))
|
||||
|
||||
ranges = sorted(ranges, key=lambda x: x[0])
|
||||
|
||||
else:
|
||||
# baseline = 2nd index
|
||||
for i in range(len(true_indices) - 1):
|
||||
if i % 2 == 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_down[true_indices[i]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_down[true_indices[i]] else 'split'
|
||||
ranges.append((true_indices[i], true_indices[i + 1], adj))
|
||||
|
||||
if len(true_indices) % 2 != 0:
|
||||
if split > 1.0:
|
||||
adj = 'split' if f_down[true_indices[-1]] else '1.0/split'
|
||||
else:
|
||||
adj = '1.0/split' if f_down[true_indices[-1]] else 'split'
|
||||
ranges.append((true_indices[-1], len(f), adj))
|
||||
|
||||
return ranges
|
||||
|
||||
if correct_columns_individually:
|
||||
|
@ -1327,28 +1452,57 @@ class TickerBase:
|
|||
# - if only one of Open & Close are Nx bad => Volume is 0.5*Nx bad
|
||||
f_open_fixed = np.full(n, False)
|
||||
f_close_fixed = np.full(n, False)
|
||||
|
||||
OHLC_correct_ranges = [None, None, None, None]
|
||||
for j in range(len(OHLC)):
|
||||
c = OHLC[j]
|
||||
ranges = map_signals_to_ranges(f[:, j], f1[:, j])
|
||||
ranges = map_signals_to_ranges(f[:, j], f_up[:, j], f_down[:, j])
|
||||
logger.debug(f"column '{c}' ranges: {ranges}")
|
||||
if start_min is not None:
|
||||
# Prune ranges that are older than start_min
|
||||
for i in range(len(ranges)-1, -1, -1):
|
||||
r = ranges[i]
|
||||
if df.index[r[0]].date() < start_min:
|
||||
logger.debug(f'price-repair-split: Pruning {c} range {df.index[r[0]]}->{df.index[r[1]-1]} because too old.')
|
||||
del ranges[i]
|
||||
|
||||
for r in ranges:
|
||||
if r[2] == 'split':
|
||||
m = split ; m_rcp = split_rcp
|
||||
else:
|
||||
m = split_rcp ; m_rcp = split
|
||||
if interday:
|
||||
logger.debug(f"price-repair-split: col={c} range=[{df2.index[r[0]].date()}:{df2.index[r[1]-1].date()}] m={m:.4f}")
|
||||
else:
|
||||
logger.debug(f"price-repair-split: col={c} range=[{df2.index[r[0]]}:{df2.index[r[1]-1]}] m={m:.4f}")
|
||||
df2.iloc[r[0]:r[1], df2.columns.get_loc(c)] *= m
|
||||
if c == 'Close':
|
||||
df2.iloc[r[0]:r[1], df2.columns.get_loc('Adj Close')] *= m
|
||||
if correct_volume:
|
||||
if c == 'Open':
|
||||
f_open_fixed[r[0]:r[1]] = True
|
||||
elif c == 'Close':
|
||||
f_close_fixed[r[0]:r[1]] = True
|
||||
f_corrected[r[0]:r[1]] = True
|
||||
if len(ranges) > 0:
|
||||
OHLC_correct_ranges[j] = ranges
|
||||
|
||||
count = sum([1 if x is not None else 0 for x in OHLC_correct_ranges])
|
||||
if count == 0:
|
||||
pass
|
||||
elif count == 1:
|
||||
# If only 1 column then assume false positive
|
||||
idxs = [i if OHLC_correct_ranges[i] else -1 for i in range(len(OHLC))]
|
||||
idx = np.where(np.array(idxs) != -1)[0][0]
|
||||
col = OHLC[idx]
|
||||
logger.debug(f'price-repair-split: Potential {fix_type} detected only in column {col}, so treating as false positive (ignore)')
|
||||
else:
|
||||
# Only correct if at least 2 columns require correction.
|
||||
for j in range(len(OHLC)):
|
||||
c = OHLC[j]
|
||||
ranges = OHLC_correct_ranges[j]
|
||||
if ranges is None:
|
||||
ranges = []
|
||||
for r in ranges:
|
||||
if r[2] == 'split':
|
||||
m = split ; m_rcp = split_rcp
|
||||
else:
|
||||
m = split_rcp ; m_rcp = split
|
||||
if interday:
|
||||
logger.info(f"price-repair-split: Corrected {fix_type} on col={c} range=[{df2.index[r[1]-1].date()}:{df2.index[r[0]].date()}] m={m:.4f}")
|
||||
else:
|
||||
logger.info(f"price-repair-split: Corrected {fix_type} on col={c} range=[{df2.index[r[1]-1]}:{df2.index[r[0]]}] m={m:.4f}")
|
||||
df2.iloc[r[0]:r[1], df2.columns.get_loc(c)] *= m
|
||||
if c == 'Close':
|
||||
df2.iloc[r[0]:r[1], df2.columns.get_loc('Adj Close')] *= m
|
||||
if correct_volume:
|
||||
if c == 'Open':
|
||||
f_open_fixed[r[0]:r[1]] = True
|
||||
elif c == 'Close':
|
||||
f_close_fixed[r[0]:r[1]] = True
|
||||
f_corrected[r[0]:r[1]] = True
|
||||
|
||||
if correct_volume:
|
||||
f_open_and_closed_fixed = f_open_fixed & f_close_fixed
|
||||
|
@ -1361,7 +1515,14 @@ class TickerBase:
|
|||
df2.loc[f_corrected, 'Repaired?'] = True
|
||||
|
||||
else:
|
||||
ranges = map_signals_to_ranges(f, f1)
|
||||
ranges = map_signals_to_ranges(f, f_up, f_down)
|
||||
if start_min is not None:
|
||||
# Prune ranges that are older than start_min
|
||||
for i in range(len(ranges)-1, -1, -1):
|
||||
r = ranges[i]
|
||||
if df.index[r[0]].date() < start_min:
|
||||
logger.debug(f'price-repair-split: Pruning range {df.index[r[0]]}->{df.index[r[1]-1]} because too old.')
|
||||
del ranges[i]
|
||||
for r in ranges:
|
||||
if r[2] == 'split':
|
||||
m = split ; m_rcp = split_rcp
|
||||
|
@ -1375,25 +1536,25 @@ class TickerBase:
|
|||
df2.iloc[r[0]:r[1], df2.columns.get_loc('Repaired?')] = True
|
||||
if r[0] == r[1] - 1:
|
||||
if interday:
|
||||
msg = f"price-repair-split: Corrected bad split adjustment on interval {df2.index[r[0]].date()}"
|
||||
msg = f"price-repair-split: Corrected {fix_type} on interval {df2.index[r[0]].date()}"
|
||||
else:
|
||||
msg = f"price-repair-split: Corrected bad split adjustment on interval {df2.index[r[0]]}"
|
||||
msg = f"price-repair-split: Corrected {fix_type} on interval {df2.index[r[0]]}"
|
||||
else:
|
||||
# Note: df2 sorted with index descending
|
||||
start = df2.index[r[1] - 1]
|
||||
end = df2.index[r[0]]
|
||||
if interday:
|
||||
msg = f"price-repair-split: Corrected bad split adjustment across intervals {start.date()} -> {end.date()} (inclusive)"
|
||||
msg = f"price-repair-split: Corrected {fix_type} across intervals {start.date()} -> {end.date()} (inclusive)"
|
||||
else:
|
||||
msg = f"price-repair-split: Corrected bad split adjustment across intervals {start} -> {end} (inclusive)"
|
||||
msg = f"price-repair-split: Corrected {fix_type} across intervals {start} -> {end} (inclusive)"
|
||||
logger.info(msg)
|
||||
|
||||
if correct_volume:
|
||||
df2['Volume'] = df2['Volume'].round(0).astype('int')
|
||||
|
||||
# if logger.isEnabledFor(logging.DEBUG):
|
||||
# logger.debug(f"price-repair-split: my workings:")
|
||||
# logger.debug('\n' + str(df_debug))
|
||||
f_na = df2['Volume'].isna()
|
||||
if f_na.any():
|
||||
df2.loc[~f_na,'Volume'] = df2['Volume'][~f_na].round(0).astype('int')
|
||||
else:
|
||||
df2['Volume'] = df2['Volume'].round(0).astype('int')
|
||||
|
||||
return df2
|
||||
|
||||
|
|
Loading…
Reference in New Issue