From 54b829f34ace4564df731e71b9b7eca7ecc7d1f0 Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Wed, 30 Mar 2022 11:49:10 -0400 Subject: [PATCH 1/8] Solve get_barset issue --- pylivetrader/_version.py | 2 +- pylivetrader/backend/alpaca.py | 41 +++++++++++++++++----------------- requirements/requirements.txt | 2 +- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/pylivetrader/_version.py b/pylivetrader/_version.py index 1f345e7..09b25bb 100644 --- a/pylivetrader/_version.py +++ b/pylivetrader/_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -VERSION = '0.6.0' +VERSION = '0.7.0' diff --git a/pylivetrader/backend/alpaca.py b/pylivetrader/backend/alpaca.py index 1fb1b96..6311223 100644 --- a/pylivetrader/backend/alpaca.py +++ b/pylivetrader/backend/alpaca.py @@ -15,7 +15,7 @@ import alpaca_trade_api as tradeapi from alpaca_trade_api import Stream -from alpaca_trade_api.rest import APIError, TimeFrame +from alpaca_trade_api.rest import APIError, TimeFrame, TimeFrameUnit from alpaca_trade_api.entity import Order from requests.exceptions import HTTPError import numpy as np @@ -645,25 +645,26 @@ def wrapper(): _from = params['_from'] to = params['to'] size = params['size'] - df = self._api.get_barset(symbols, - size, - limit=params['limit'], - start=_from.isoformat(), - end=to.isoformat()).df[symbols] - - if df.empty: - # we got an empty response. We will try to use the updated - # V2 api to get the data. we cannot do 1 api call for all - # symbols so we will iterate them - r = {} - for sym in symbols: - r[sym] = self._api.get_bars(sym, TimeFrame.Minute, - _from.isoformat(), - to.isoformat(), - adjustment='raw').df - df = pd.concat(r, axis=1) - # data is received in UTC tz but without tz (naive) - df.index = df.index.tz_localize("UTC") + + timeframe = TimeFrame(1, TimeFrameUnit.Minute) if size == "minute" \ + else TimeFrame(1, TimeFrameUnit.Day) + + # Using V2 api to get the data. we cannot do 1 api call for all + # symbols because the v1 `limit` was per symbol, where v2 it's for + # overall response size; so we will iterate over each symbol with + # the limit for each to replicate that behaviour + r = {} + for sym in symbols: + r[sym] = self._api.get_bars(sym, + limit=params['limit'], + timeframe=timeframe, + start=_from.isoformat(), + end=to.isoformat(), + adjustment='raw').df + df = pd.concat(r, axis=1) + # data is received in UTC tz but without tz (naive) + df.index = df.index.tz_localize("UTC") + if size == 'minute': df.index += pd.Timedelta('1min') diff --git a/requirements/requirements.txt b/requirements/requirements.txt index f165e8c..1f16d85 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,6 +10,6 @@ trading_calendars>=1.11 click==8.0.1 PyYAML>=5, <6 ipython>=7 -alpaca-trade-api>=1.2.2 +alpaca-trade-api==1.5.0 pandas>=0.18.1, <=0.22.0 # pyup: ignore # limit to work properly with zipline 1.3.0 pandas-datareader<=0.8.1 # pyup: ignore # higher requires pandas>=0.23, zipline limits to 0.22 From a8dd03e3798d7695a10915f6c13d6f608cd05d80 Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 11:02:57 -0400 Subject: [PATCH 2/8] Remove remaining usages of data v1 --- pylivetrader/backend/alpaca.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylivetrader/backend/alpaca.py b/pylivetrader/backend/alpaca.py index 6311223..6856818 100644 --- a/pylivetrader/backend/alpaca.py +++ b/pylivetrader/backend/alpaca.py @@ -446,7 +446,7 @@ def cancel_order(self, zp_order_id): return def get_last_traded_dt(self, asset): - trade = self._api.get_last_trade(asset.symbol) + trade = self._api.get_latest_trade(asset.symbol) return trade.timestamp def get_spot_value( @@ -496,7 +496,7 @@ def _get_symbols_last_trade_value(self, symbols): @skip_http_error((404, 504)) def fetch(symbol): - return self._api.get_last_trade(symbol) + return self._api.get_latest_trade(symbol) return parallelize(fetch)(symbols) From 0c5ca418280dcf0bc3aab53e1f7dc198edc7f175 Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 11:59:56 -0400 Subject: [PATCH 3/8] Attempt to fix circleci --- .circleci/config.yml | 14 +++++++++++--- pylivetrader/backend/alpaca.py | 2 +- requirements/requirements_test.txt | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aee006e..25f4229 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,11 @@ jobs: - run: command: | . venv/bin/activate - python3 setup.py flake8 test + python3 setup.py + pip install -R requirements/requirements.txt + pip install -R requirements/requirements_test.txt + flake8 ./pylivetrader + pytest build-python37: docker: @@ -43,10 +47,14 @@ jobs: - run: command: | . venv/bin/activate - python3 setup.py flake8 test + python3 setup.py + pip install -R requirements/requirements.txt + pip install -R requirements/requirements_test.txt + flake8 ./pylivetrader + pytest workflows: version: 2 build: jobs: - - build-python36 \ No newline at end of file + - build-python36 diff --git a/pylivetrader/backend/alpaca.py b/pylivetrader/backend/alpaca.py index 6856818..ced1d67 100644 --- a/pylivetrader/backend/alpaca.py +++ b/pylivetrader/backend/alpaca.py @@ -646,7 +646,7 @@ def wrapper(): to = params['to'] size = params['size'] - timeframe = TimeFrame(1, TimeFrameUnit.Minute) if size == "minute" \ + timeframe = TimeFrame(1, TimeFrameUnit.Minute) if size == "minute"\ else TimeFrame(1, TimeFrameUnit.Day) # Using V2 api to get the data. we cannot do 1 api call for all diff --git a/requirements/requirements_test.txt b/requirements/requirements_test.txt index adc14e3..2872acf 100644 --- a/requirements/requirements_test.txt +++ b/requirements/requirements_test.txt @@ -1,2 +1,3 @@ pytest>=5.0.0 -pytest-cov \ No newline at end of file +pytest-cov +flake8 From 1746a3905821006b52826e058b16f24ea6e08013 Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 12:01:38 -0400 Subject: [PATCH 4/8] Attempt to fix circleci round 2 --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 25f4229..64ae4e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,6 @@ jobs: - run: command: | . venv/bin/activate - python3 setup.py pip install -R requirements/requirements.txt pip install -R requirements/requirements_test.txt flake8 ./pylivetrader @@ -47,7 +46,6 @@ jobs: - run: command: | . venv/bin/activate - python3 setup.py pip install -R requirements/requirements.txt pip install -R requirements/requirements_test.txt flake8 ./pylivetrader From d4facf6aec310526a69603205ebbb381b5bf6564 Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 12:03:35 -0400 Subject: [PATCH 5/8] Attempt to fix circleci round 3 --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64ae4e8..6ff8b06 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,8 +21,8 @@ jobs: - run: command: | . venv/bin/activate - pip install -R requirements/requirements.txt - pip install -R requirements/requirements_test.txt + pip install -r requirements/requirements.txt + pip install -r requirements/requirements_test.txt flake8 ./pylivetrader pytest @@ -46,8 +46,8 @@ jobs: - run: command: | . venv/bin/activate - pip install -R requirements/requirements.txt - pip install -R requirements/requirements_test.txt + pip install -r requirements/requirements.txt + pip install -r requirements/requirements_test.txt flake8 ./pylivetrader pytest From c481cc47e77e55c7a5d1231e94ba359bbc16c8fc Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 12:05:40 -0400 Subject: [PATCH 6/8] Attempt to fix circleci round 4 --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ff8b06..72e5122 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,6 @@ jobs: - run: command: | . venv/bin/activate - pip install -r requirements/requirements.txt pip install -r requirements/requirements_test.txt flake8 ./pylivetrader pytest @@ -46,7 +45,6 @@ jobs: - run: command: | . venv/bin/activate - pip install -r requirements/requirements.txt pip install -r requirements/requirements_test.txt flake8 ./pylivetrader pytest From e193f218da0675253e987e20c9718a5625a66e2b Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Thu, 31 Mar 2022 12:10:39 -0400 Subject: [PATCH 7/8] Add flake8 confirmation message in ci --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 72e5122..a1474c5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ jobs: command: | . venv/bin/activate pip install -r requirements/requirements_test.txt - flake8 ./pylivetrader + flake8 ./pylivetrader && echo "Flake8 passed" pytest build-python37: @@ -46,7 +46,7 @@ jobs: command: | . venv/bin/activate pip install -r requirements/requirements_test.txt - flake8 ./pylivetrader + flake8 ./pylivetrader && echo "Flake8 passed" pytest workflows: From 5d951a3cb2188cd0cdc56ea9c90987ef38d7b75e Mon Sep 17 00:00:00 2001 From: Andrew Mcdonald Date: Fri, 1 Apr 2022 09:44:32 -0400 Subject: [PATCH 8/8] Use preconfigured timeframe units --- pylivetrader/backend/alpaca.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pylivetrader/backend/alpaca.py b/pylivetrader/backend/alpaca.py index ced1d67..b63698f 100644 --- a/pylivetrader/backend/alpaca.py +++ b/pylivetrader/backend/alpaca.py @@ -15,7 +15,7 @@ import alpaca_trade_api as tradeapi from alpaca_trade_api import Stream -from alpaca_trade_api.rest import APIError, TimeFrame, TimeFrameUnit +from alpaca_trade_api.rest import APIError, TimeFrame from alpaca_trade_api.entity import Order from requests.exceptions import HTTPError import numpy as np @@ -646,8 +646,7 @@ def wrapper(): to = params['to'] size = params['size'] - timeframe = TimeFrame(1, TimeFrameUnit.Minute) if size == "minute"\ - else TimeFrame(1, TimeFrameUnit.Day) + timeframe = TimeFrame.Minute if size == "minute" else TimeFrame.Day # Using V2 api to get the data. we cannot do 1 api call for all # symbols because the v1 `limit` was per symbol, where v2 it's for