Skip to content

Commit 9d34fb8

Browse files
committed
Adapt to T212 new App, fix candle stick
1 parent 219baa4 commit 9d34fb8

File tree

9 files changed

+172
-98
lines changed

9 files changed

+172
-98
lines changed

HISTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### v0.2.7
2+
* fix candle stick
3+
* adapt api with new T212 app
14
### v0.2.6
25
* removed depreacted driver manager
36
* fix cfd/equity switch

config.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[ACCOUNT]
2+
email=your@email.com
3+
password=your_password

examples/Instrument_pricing_history_example.ipynb

Lines changed: 81 additions & 46 deletions
Large diffs are not rendered by default.

examples/instrument_pricing_history.py renamed to examples/instrument_pricing_history_example.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,26 @@
22

33
from selenium import webdriver
44
from selenium.webdriver.chrome.service import Service
5-
from webdriver_manager.chrome import ChromeDriverManager
65

76
from pytrading212 import Equity, Company
8-
from pytrading212 import Mode, EquityOrder, OrderType
7+
from pytrading212 import Mode
98
from pytrading212.constants import ONE_WEEK
109

11-
1210
config = configparser.ConfigParser()
1311
config.read('../config.ini')
1412

15-
1613
if __name__ == '__main__':
17-
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
14+
driver = webdriver.Chrome(service=Service())
1815
equity = Equity(
1916
email=config['ACCOUNT']['email'], password=config['ACCOUNT']['password'],
2017
driver=driver, mode=Mode.DEMO
2118
)
2219

2320
# Create a new instrument
24-
instrument = Company(instrument_code="AAPLL_US_EQ", isin="")
21+
instrument = Company(instrument_code="AAPL_US_EQ", isin="")
2522

2623
# Request pricing history for the instrument, this requires a time interval
2724
# and a trading 212 instance
2825
print(
29-
instrument.get_pricing_history(interval=ONE_WEEK, trading_instance=equity)
26+
instrument.get_pricing_history(interval=ONE_WEEK, headers=equity.headers, trading_instance=equity)
3027
)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pytrading212"
3-
version = "0.2.5"
3+
version = "0.2.7"
44
description = "Unofficial Trading212 API"
55
authors = ["HellAmbro <frambrosini1998@gmail.com>"]
66
license = "MIT License"

pytrading212/constants.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,54 @@
66
CLASS_LOGIN_BUTTON = "SubmitButton_input__IV2dl"
77
CLASS_EQUITY_ICON = "equity-icon"
88
CLASS_CFD_ICON = "cfd-icon"
9-
PYTRADING212_VERSION = "0.2.5"
9+
PYTRADING212_VERSION = "0.2.6"
10+
SELECTOR_NEW_APP = ("#root > div > div > div > div > div > div > div:nth-child(1) > "
11+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > "
12+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > div > div > div > div "
13+
"> div > div > div > div.css-175oi2r.r-13awgt0 > div > "
14+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div:nth-child(2) > div "
15+
"> div.css-175oi2r.r-13awgt0.r-1udh08x > div > div.css-175oi2r.r-13awgt0 > div > div > div > div "
16+
"> div > div > div.css-175oi2r.r-13awgt0 > div > "
17+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div:nth-child(2) > div "
18+
"> div.css-175oi2r.r-13awgt0.r-1udh08x > div > div.css-175oi2r.r-13awgt0 > div > div > "
19+
"div.css-175oi2r.r-150rngu.r-eqz5dr.r-16y2uox.r-1wbh5a2.r-11yh6sk.r-1rnoaur.r-1sncvnh > div > "
20+
"div.css-175oi2r.r-1loqt21.r-1otgn73 > div > div")
21+
SELECTOR_MENU_BUTTON = ("#root > div > div > div > div > div > div > div:nth-child(1) > div > "
22+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div > div > "
23+
"div:nth-child(1) > div > div > div:nth-child(2) > div > div:nth-child(5) > div > span > div")
24+
SELECTOR_LIVE_ACCOUNT = ("#root > div > div > div > div > div > div > div:nth-child(1) > div > "
25+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div > div > "
26+
"div:nth-child(1) > div > div > div:nth-child(3) > div:nth-child(1) > div > div > div")
27+
SELECTOR_LIVE_EQUITY = ("#root > div > div > div > div > div > div > div:nth-child(1) > "
28+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > "
29+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > div:nth-child(3) > "
30+
"div > div.css-175oi2r.r-12vffkv > div > div > "
31+
"div.css-175oi2r.r-150rngu.r-eqz5dr.r-16y2uox.r-11yh6sk.r-1rnoaur.r-1sncvnh > div > "
32+
"div:nth-child(2) > div:nth-child(1) > div:nth-child(1) > div.css-175oi2r")
33+
SELECTOR_DEMO_EQUITY = ("#root > div > div > div > div > div > div > div:nth-child(1) > "
34+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > "
35+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-105ug2t > div:nth-child(3) > "
36+
"div > div.css-175oi2r.r-12vffkv > div > div > "
37+
"div.css-175oi2r.r-150rngu.r-eqz5dr.r-16y2uox.r-11yh6sk.r-1rnoaur.r-1sncvnh > div > "
38+
"div:nth-child(2) > div:nth-child(1) > div:nth-child(1)")
39+
SELECTOR_MENU_LIST = ("#root > div > div > div > div > div > div > div:nth-child(1) > div > "
40+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div > div > "
41+
"div:nth-child(2) > div > div > div:nth-child(2) > div > div > div > div > div > "
42+
"div.css-175oi2r.r-13awgt0 > div > "
43+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div:nth-child(2) > "
44+
"div > div > div > div.css-175oi2r.r-13awgt0 > div > div:nth-child(1)")
45+
SELECTOR_SWITCH_DEMO = ("#root > div > div > div > div > div > div > div:nth-child(1) > div > "
46+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div > div > "
47+
"div:nth-child(2) > div > div > div:nth-child(2) > div > div > div > div > div > "
48+
"div.css-175oi2r.r-13awgt0 > div > "
49+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div:nth-child(2) > "
50+
"div > div > div > div.css-175oi2r.r-13awgt0 > div > div:nth-child(1) > div > div > div > div "
51+
"> div.css-175oi2r.r-13awgt0 > div > "
52+
"div.css-175oi2r.r-1p0dtai.r-1d2f490.r-u8s1d.r-zchlnj.r-ipm5af.r-12vffkv > div:nth-child(2) > "
53+
"div > div.css-175oi2r.r-13awgt0.r-1udh08x > div > div.css-175oi2r.r-13awgt0 > div > "
54+
"div:nth-child(2) > div.css-175oi2r.r-150rngu.r-eqz5dr.r-16y2uox.r-1wbh5a2.r-11yh6sk.r"
55+
"-1rnoaur.r-1sncvnh > div > div:nth-child(3) > "
56+
"div.css-175oi2r.r-1otgn73.r-1loqt21.r-1awozwy.r-1777fci.r-utggzx")
1057

1158
ONE_WEEK = "ONE_WEEK"
1259

@@ -32,7 +79,6 @@ class Period(Enum):
3279
ALL = "ALL",
3380

3481

35-
3682
class OrderType(Enum):
3783
"""Order Type"""
3884
LIMIT = "LIMIT"

pytrading212/instrument.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
import datetime
2-
import typing
3-
import requests
42
import json
3+
import typing
54

6-
from constants import ONE_WEEK
7-
8-
from selenium import webdriver
9-
from selenium.webdriver.chrome.service import Service
10-
from webdriver_manager.chrome import ChromeDriverManager
11-
from selenium.webdriver.chrome.options import Options
5+
import requests
126

137

148
class CandleStick(object):
15-
169
"""
1710
The candlestick object is a representaion of the values used in a candlestick
1811
chart.
@@ -32,9 +25,12 @@ class CandleStick(object):
3225
timestamp: datetime.datetime
3326
unknown: int
3427

35-
def __init__(self, data: typing.List) -> None:
28+
def __init__(self, data: typing.List) -> None:
3629
self.timestamp, self.high, self.low, self.opening, self.closing, self.unknown = data
3730

31+
def __repr__(self) -> str:
32+
return (f"CandleStick(timestamp={self.timestamp}, high={self.high}, low={self.low},"
33+
f" opening={self.opening}, closing={self.closing}, unknown={self.unknown})")
3834

3935

4036
class Company:
@@ -50,9 +46,9 @@ def __init__(self, instrument_code: str, isin: str, language_code: str = 'en'):
5046
def get_pricing_history(
5147
self,
5248
interval: str,
49+
headers: dict,
5350
trading_instance: 'Trading212'
5451
) -> typing.List[CandleStick]:
55-
5652
ticker_data: str = json.dumps(
5753
{
5854
"candles":
@@ -61,15 +57,15 @@ def get_pricing_history(
6157
"ticker": self.instrument_code,
6258
"useAskPrice": True,
6359
"period": interval,
64-
"size":500
60+
"size": 500
6561
}
6662
]
6763
}
6864
)
6965

7066
response = requests.put(
7167
f"{trading_instance.base_url}{self.charting_url}?ticker={self.instrument_code}&languageCode={self.language_code}",
72-
headers=equity.headers,
68+
headers=headers,
7369
data=ticker_data
7470
)
7571
return [

pytrading212/trading212.py

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,18 @@ def __init__(
5858
# Click login button
5959
self.driver.find_element(By.CLASS_NAME, constants.CLASS_LOGIN_BUTTON).click()
6060

61-
# Wait until the site is fully loaded, 120 seconds is a lot, but the site sometimes is very slow
62-
WebDriverWait(self.driver, 120).until(expected_conditions.
63-
visibility_of_element_located((By.CLASS_NAME, "company-logo")))
61+
# Close new app button, should be removed later
62+
try:
63+
WebDriverWait(self.driver, 30).until(expected_conditions.visibility_of_element_located(
64+
(By.CSS_SELECTOR, constants.SELECTOR_NEW_APP)))
65+
self.driver.find_element(By.CSS_SELECTOR, constants.SELECTOR_NEW_APP).click()
66+
except NoSuchElementException:
67+
pass
6468

6569
self.user_agent = self.driver.execute_script("return navigator.userAgent;")
6670

67-
# Redirect to correct mode, DEMO or LIVE
68-
if mode.name not in self.driver.current_url:
69-
self.driver.get(self.base_url)
70-
WebDriverWait(self.driver, 120).until(expected_conditions.
71-
visibility_of_element_located((By.CLASS_NAME, "company-logo")))
72-
73-
# Switch to right trading session: CFD or EQUITY
74-
self.switch_to(trading=trading)
75-
71+
# Switch to get also DEMO token
72+
self.switch()
7673
# Get session cookie
7774
cookies = self.driver.get_cookies()
7875
if cookies is not None:
@@ -103,22 +100,19 @@ def finish(self):
103100
console.log("Closing session.")
104101
self.driver.close()
105102

106-
def switch_to(self, trading: constants.Trading):
107-
if not self.driver.find_elements(By.ID, "platform-loader"):
108-
self.driver.find_element(By.CLASS_NAME, "account-menu-info").click()
109-
WebDriverWait(self.driver, 10).until(expected_conditions.
110-
visibility_of_element_located((By.CLASS_NAME, "account-types")))
111-
element_account_types = self.driver.find_element(By.CLASS_NAME, "account-types")
112-
if trading == constants.Trading.CFD:
113-
element_account_types.find_element(By.CLASS_NAME, "cfd").click()
114-
WebDriverWait(self.driver, 60).until(expected_conditions.
115-
visibility_of_element_located((By.CLASS_NAME, "cfd-icon")))
116-
elif trading == constants.Trading.EQUITY:
117-
element_account_types.find_element(By.CLASS_NAME, "equity").click()
118-
WebDriverWait(self.driver, 60).until(expected_conditions.
119-
visibility_of_element_located((By.CLASS_NAME, "equity-icon")))
120-
else:
121-
self.switch_to(trading)
103+
def switch(self):
104+
WebDriverWait(self.driver, 30).until(expected_conditions.visibility_of_element_located(
105+
(By.CSS_SELECTOR, constants.SELECTOR_MENU_BUTTON)))
106+
self.driver.find_element(By.CSS_SELECTOR, constants.SELECTOR_MENU_BUTTON).click()
107+
108+
self.driver.execute_script("arguments[0].scroll(0, arguments[0].scrollHeight);",
109+
self.driver.find_element(By.CSS_SELECTOR, constants.SELECTOR_MENU_LIST))
110+
self.driver.find_element(By.CSS_SELECTOR, constants.SELECTOR_SWITCH_DEMO).click()
111+
WebDriverWait(self.driver, 30).until(expected_conditions.visibility_of_element_located(
112+
(By.CSS_SELECTOR, constants.SELECTOR_DEMO_EQUITY)))
113+
self.driver.find_element(By.CSS_SELECTOR, constants.SELECTOR_DEMO_EQUITY).click()
114+
# Wait some seconds to initialize cookies
115+
time.sleep(5)
122116

123117
def get_funds(self):
124118
"""Get your funds, free, available."""

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="pytrading212",
8-
version="0.2.6",
8+
version="0.2.7",
99
author="HellAmbro",
1010
author_email="frambrosini1998@gmail.com",
1111
description="Unofficial Trading212 API",

0 commit comments

Comments
 (0)