firstrade 0.0.13__py3-none-any.whl → 0.0.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- firstrade/account.py +19 -11
- firstrade/order.py +2 -0
- {firstrade-0.0.13.dist-info → firstrade-0.0.15.dist-info}/METADATA +48 -34
- firstrade-0.0.15.dist-info/RECORD +10 -0
- {firstrade-0.0.13.dist-info → firstrade-0.0.15.dist-info}/WHEEL +1 -1
- firstrade-0.0.13.dist-info/RECORD +0 -10
- {firstrade-0.0.13.dist-info → firstrade-0.0.15.dist-info}/LICENSE +0 -0
- {firstrade-0.0.13.dist-info → firstrade-0.0.15.dist-info}/top_level.txt +0 -0
firstrade/account.py
CHANGED
|
@@ -70,8 +70,7 @@ class FTSession:
|
|
|
70
70
|
self.session.post(
|
|
71
71
|
url=urls.pin(), headers=headers, cookies=self.session.cookies, data=data
|
|
72
72
|
)
|
|
73
|
-
|
|
74
|
-
self.save_cookies()
|
|
73
|
+
self.save_cookies()
|
|
75
74
|
if (
|
|
76
75
|
"/cgi-bin/sessionfailed?reason=6"
|
|
77
76
|
in self.session.get(
|
|
@@ -88,15 +87,16 @@ class FTSession:
|
|
|
88
87
|
Dict: Dictionary of cookies. Nom Nom
|
|
89
88
|
"""
|
|
90
89
|
cookies = {}
|
|
91
|
-
if self.profile_path is not None
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
directory = os.path.abspath(self.profile_path) if self.profile_path is not None else "."
|
|
91
|
+
|
|
92
|
+
if not os.path.exists(directory):
|
|
93
|
+
os.makedirs(directory)
|
|
94
|
+
|
|
95
|
+
for filename in os.listdir(directory):
|
|
96
|
+
if filename.endswith(f"{self.username}.pkl"):
|
|
97
|
+
filepath = os.path.join(directory, filename)
|
|
98
|
+
with open(filepath, "rb") as f:
|
|
99
|
+
cookies = pickle.load(f)
|
|
100
100
|
return cookies
|
|
101
101
|
|
|
102
102
|
def save_cookies(self):
|
|
@@ -110,6 +110,14 @@ class FTSession:
|
|
|
110
110
|
path = f"ft_cookies{self.username}.pkl"
|
|
111
111
|
with open(path, "wb") as f:
|
|
112
112
|
pickle.dump(self.session.cookies.get_dict(), f)
|
|
113
|
+
|
|
114
|
+
def delete_cookies(self):
|
|
115
|
+
"""Deletes the session cookies."""
|
|
116
|
+
if self.profile_path is not None:
|
|
117
|
+
path = os.path.join(self.profile_path, f"ft_cookies{self.username}.pkl")
|
|
118
|
+
else:
|
|
119
|
+
path = f"ft_cookies{self.username}.pkl"
|
|
120
|
+
os.remove(path)
|
|
113
121
|
|
|
114
122
|
def __getattr__(self, name):
|
|
115
123
|
"""
|
firstrade/order.py
CHANGED
|
@@ -68,6 +68,7 @@ class Order:
|
|
|
68
68
|
duration: Duration,
|
|
69
69
|
price=0.00,
|
|
70
70
|
dry_run=True,
|
|
71
|
+
notional=False,
|
|
71
72
|
):
|
|
72
73
|
"""
|
|
73
74
|
Builds and places an order.
|
|
@@ -100,6 +101,7 @@ class Order:
|
|
|
100
101
|
"submiturl": "/cgi-bin/orderbar",
|
|
101
102
|
"orderbar_clordid": "",
|
|
102
103
|
"orderbar_accountid": "",
|
|
104
|
+
"notional": "yes" if notional else "",
|
|
103
105
|
"stockorderpage": "yes",
|
|
104
106
|
"submitOrders": "1",
|
|
105
107
|
"previewOrders": previewOrders,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: firstrade
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Summary: An unofficial API for Firstrade
|
|
5
5
|
Home-page: https://github.com/MaxxRK/firstrade-api
|
|
6
|
-
Download-URL: https://github.com/MaxxRK/firstrade-api/archive/refs/tags/
|
|
6
|
+
Download-URL: https://github.com/MaxxRK/firstrade-api/archive/refs/tags/0015.tar.gz
|
|
7
7
|
Author: MaxxRK
|
|
8
8
|
Author-email: maxxrk@pm.me
|
|
9
9
|
License: MIT
|
|
@@ -24,42 +24,48 @@ Requires-Dist: beautifulsoup4
|
|
|
24
24
|
Requires-Dist: lxml
|
|
25
25
|
|
|
26
26
|
# firstrade-api
|
|
27
|
-
A reverse-engineered python API to interact with the Firstrade Trading platform.
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
A reverse-engineered python API to interact with the Firstrade Trading platform.
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
This is not an official api! This api's functionality may change at any time.
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
This api provides a means of buying and selling stocks through Firstrade. It uses the Session class from requests to get authorization cookies. The rest is done with reverse engineered requests to Firstrade's API.
|
|
33
|
+
|
|
34
|
+
In order to use Fractional shares you must accept the agreement on the website before using it in this API.
|
|
35
|
+
|
|
36
|
+
---
|
|
34
37
|
|
|
35
38
|
## Contribution
|
|
39
|
+
|
|
36
40
|
I am new to coding and new to open-source. I would love any help and suggestions!
|
|
37
41
|
|
|
38
42
|
## Setup
|
|
43
|
+
|
|
39
44
|
Install using pypi:
|
|
45
|
+
|
|
40
46
|
```
|
|
41
47
|
pip install firstrade
|
|
42
48
|
```
|
|
43
49
|
|
|
44
50
|
## Quikstart
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
|
|
52
|
+
The code below will:
|
|
53
|
+
|
|
54
|
+
- Login and print account info.
|
|
47
55
|
- Get a quote for 'INTC' and print out the information
|
|
48
56
|
- Place a market order for 'INTC' on the first account in the `account_numbers` list
|
|
49
57
|
- Print out the order confirmation
|
|
50
58
|
|
|
51
59
|
```
|
|
52
|
-
from firstrade import account
|
|
53
|
-
from firstrade import symbols
|
|
54
|
-
from firstrade import order
|
|
60
|
+
from firstrade import account, order, symbols
|
|
55
61
|
|
|
56
62
|
# Create a session
|
|
57
|
-
ft_ss = account.FTSession(username=
|
|
63
|
+
ft_ss = account.FTSession(username="", password="", pin="")
|
|
58
64
|
|
|
59
65
|
# Get account data
|
|
60
66
|
ft_accounts = account.FTAccountData(ft_ss)
|
|
61
67
|
if len(ft_accounts.account_numbers) < 1:
|
|
62
|
-
raise Exception(
|
|
68
|
+
raise Exception("No accounts found or an error occured exiting...")
|
|
63
69
|
|
|
64
70
|
# Print ALL account data
|
|
65
71
|
print(ft_accounts.all_accounts)
|
|
@@ -71,7 +77,7 @@ print(ft_accounts.account_numbers[0])
|
|
|
71
77
|
print(ft_accounts.account_balances)
|
|
72
78
|
|
|
73
79
|
# Get quote for INTC
|
|
74
|
-
quote = symbols.SymbolQuote(ft_ss,
|
|
80
|
+
quote = symbols.SymbolQuote(ft_ss, "INTC")
|
|
75
81
|
print(f"Symbol: {quote.symbol}")
|
|
76
82
|
print(f"Exchange: {quote.exchange}")
|
|
77
83
|
print(f"Bid: {quote.bid}")
|
|
@@ -86,50 +92,58 @@ print(f"Company Name: {quote.company_name}")
|
|
|
86
92
|
# Get positions and print them out for an account.
|
|
87
93
|
positions = ft_accounts.get_positions(account=ft_accounts.account_numbers[1])
|
|
88
94
|
for key in ft_accounts.securities_held:
|
|
89
|
-
print(
|
|
95
|
+
print(
|
|
96
|
+
f"Quantity {ft_accounts.securities_held[key]['quantity']} of security {key} held in account {ft_accounts.account_numbers[1]}"
|
|
97
|
+
)
|
|
90
98
|
|
|
91
|
-
# Create an order object.
|
|
99
|
+
# Create an order object.
|
|
92
100
|
ft_order = order.Order(ft_ss)
|
|
93
101
|
|
|
94
102
|
# Place order and print out order confirmation data.
|
|
95
103
|
ft_order.place_order(
|
|
96
104
|
ft_accounts.account_numbers[0],
|
|
97
|
-
symbol=
|
|
105
|
+
symbol="INTC",
|
|
98
106
|
price_type=order.PriceType.MARKET,
|
|
99
107
|
order_type=order.OrderType.BUY,
|
|
100
|
-
quantity=1,
|
|
108
|
+
quantity=1, # number of shares or amount of dollar, depends on the value of notional
|
|
101
109
|
duration=order.Duration.DAY,
|
|
102
|
-
dry_run=True
|
|
110
|
+
dry_run=True,
|
|
111
|
+
notional=False, # set to True if quantity above is "dollar"
|
|
103
112
|
)
|
|
104
113
|
|
|
105
114
|
# Print Order data Dict
|
|
106
115
|
print(ft_order.order_confirmation)
|
|
107
116
|
|
|
108
117
|
# Check if order was successful
|
|
109
|
-
if ft_order.order_confirmation[
|
|
110
|
-
print(
|
|
118
|
+
if ft_order.order_confirmation["success"] == "Yes":
|
|
119
|
+
print("Order placed successfully.")
|
|
111
120
|
# Print Order ID
|
|
112
121
|
print(f"Order ID: {ft_order.order_confirmation['orderid']}.")
|
|
113
122
|
else:
|
|
114
|
-
print(
|
|
123
|
+
print("Failed to place order.")
|
|
115
124
|
# Print errormessage
|
|
116
|
-
print(ft_order.order_confirmation[
|
|
125
|
+
print(ft_order.order_confirmation["actiondata"])
|
|
126
|
+
# Delete cookies
|
|
127
|
+
ft_ss.delete_cookies()
|
|
117
128
|
```
|
|
129
|
+
|
|
118
130
|
This code is also in test.py
|
|
119
131
|
|
|
120
132
|
---
|
|
121
133
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
## Implemented Features
|
|
135
|
+
|
|
136
|
+
- [x] Login
|
|
137
|
+
- [x] Get Quotes
|
|
138
|
+
- [x] Get Account Data
|
|
139
|
+
- [x] Place Orders and Receive order confirmation
|
|
140
|
+
- [x] Get Currently Held Positions
|
|
128
141
|
|
|
129
142
|
## TO DO
|
|
130
|
-
- [ ] Check on placed order status.
|
|
131
|
-
- [ ] Cancel placed orders
|
|
132
|
-
- [ ] Options
|
|
133
|
-
- [ ] Give me some Ideas!
|
|
134
143
|
|
|
135
|
-
[
|
|
144
|
+
- [ ] Check on placed order status.
|
|
145
|
+
- [ ] Cancel placed orders
|
|
146
|
+
- [ ] Options
|
|
147
|
+
- [ ] Give me some Ideas!
|
|
148
|
+
|
|
149
|
+
[](https://ko-fi.com/O5O6PTOYG)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
firstrade/__init__.py,sha256=fNiWYgSTjElY1MNv0Ug-sVLMTR2z_Ngri_FY7Pekdrw,95
|
|
2
|
+
firstrade/account.py,sha256=xDgTMXDy2UWUNi4kboXAKKBrbmZGpXLJ11MCHlMvzB0,9218
|
|
3
|
+
firstrade/order.py,sha256=S9fg_pfYN_sDOerzxcoeC6Gyp4IXttHgnEZw4aD1l60,5205
|
|
4
|
+
firstrade/symbols.py,sha256=m5v1QeY2crtNw7mymoV6wpD_J_M-avWK5Lz9DUZJpNE,2315
|
|
5
|
+
firstrade/urls.py,sha256=nAKbOw30cediYI6JDaGc4gL7-m-7WKP3A--BEVrL_cI,1167
|
|
6
|
+
firstrade-0.0.15.dist-info/LICENSE,sha256=wPEQjDqm5zMBmEcZp219Labmq_YIjhudpZiUzyVKaFA,1057
|
|
7
|
+
firstrade-0.0.15.dist-info/METADATA,sha256=cGG02YGpwixRWyn-11IVie30zN5ScPDPHJu2JyAs0Lw,4312
|
|
8
|
+
firstrade-0.0.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
9
|
+
firstrade-0.0.15.dist-info/top_level.txt,sha256=tdA8v-KDxU1u4VV6soiNWGBlni4ojv_t_j2wFn5nZcs,10
|
|
10
|
+
firstrade-0.0.15.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
firstrade/__init__.py,sha256=fNiWYgSTjElY1MNv0Ug-sVLMTR2z_Ngri_FY7Pekdrw,95
|
|
2
|
-
firstrade/account.py,sha256=bQf9IHatrzsyzkZfpmhV5-eNuj85s8T2i7C3xNKM0S0,8991
|
|
3
|
-
firstrade/order.py,sha256=qHVTufY3UbRakrjFPd6hv8fxknATSoHFy2E20zl4PGE,5130
|
|
4
|
-
firstrade/symbols.py,sha256=m5v1QeY2crtNw7mymoV6wpD_J_M-avWK5Lz9DUZJpNE,2315
|
|
5
|
-
firstrade/urls.py,sha256=nAKbOw30cediYI6JDaGc4gL7-m-7WKP3A--BEVrL_cI,1167
|
|
6
|
-
firstrade-0.0.13.dist-info/LICENSE,sha256=wPEQjDqm5zMBmEcZp219Labmq_YIjhudpZiUzyVKaFA,1057
|
|
7
|
-
firstrade-0.0.13.dist-info/METADATA,sha256=jqwjimrVDp6AAAssZdzxtCZ6Qt376P9fCtc18bECZi8,4066
|
|
8
|
-
firstrade-0.0.13.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
9
|
-
firstrade-0.0.13.dist-info/top_level.txt,sha256=tdA8v-KDxU1u4VV6soiNWGBlni4ojv_t_j2wFn5nZcs,10
|
|
10
|
-
firstrade-0.0.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|