kwess 0.0.7__py3-none-any.whl → 0.1.0__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.
- kwess/__init__.py +18 -18
- kwess/__main__.py +7 -0
- kwess/kwess_acb.py +176 -0
- {kwess-0.0.7.dist-info → kwess-0.1.0.dist-info}/METADATA +87 -14
- kwess-0.1.0.dist-info/RECORD +10 -0
- {kwess-0.0.7.dist-info → kwess-0.1.0.dist-info}/WHEEL +1 -1
- kwess-0.1.0.dist-info/entry_points.txt +2 -0
- kwess-0.0.7.dist-info/RECORD +0 -7
- {kwess-0.0.7.dist-info → kwess-0.1.0.dist-info/licenses}/LICENSE.txt +0 -0
- {kwess-0.0.7.dist-info → kwess-0.1.0.dist-info}/top_level.txt +0 -0
- {kwess-0.0.7.dist-info → kwess-0.1.0.dist-info}/zip-safe +0 -0
kwess/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import requests
|
|
3
3
|
import sys
|
|
4
|
-
from pprint import pprint
|
|
4
|
+
from pprint import pprint as pp
|
|
5
5
|
from datetime import datetime as dt, timezone as tz, timedelta as td
|
|
6
6
|
import time
|
|
7
7
|
import json
|
|
@@ -179,7 +179,7 @@ class Trader:
|
|
|
179
179
|
print(f"Accounts for user id {self.userid}:")
|
|
180
180
|
for account in self.accounts:
|
|
181
181
|
if verbose:
|
|
182
|
-
|
|
182
|
+
pp(account)
|
|
183
183
|
yield account
|
|
184
184
|
|
|
185
185
|
|
|
@@ -262,7 +262,7 @@ class Trader:
|
|
|
262
262
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account activities.", f"{self.server_type} server returned {resp.status_code} on get_account_activities().", ex)
|
|
263
263
|
|
|
264
264
|
if verbosity > 1:
|
|
265
|
-
|
|
265
|
+
pp(resp.json())
|
|
266
266
|
return resp.json()
|
|
267
267
|
|
|
268
268
|
|
|
@@ -413,7 +413,7 @@ class Trader:
|
|
|
413
413
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account orders.", f"{self.server_type} server returned {resp.status_code} on get_account_orders().", ex)
|
|
414
414
|
|
|
415
415
|
if verbosity > 1:
|
|
416
|
-
|
|
416
|
+
pp(resp.json())
|
|
417
417
|
return resp.json()
|
|
418
418
|
|
|
419
419
|
|
|
@@ -449,7 +449,7 @@ class Trader:
|
|
|
449
449
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account orders by ids.", f"{self.server_type} server returned {resp.status_code} on get_account_orders_by_ids().", ex)
|
|
450
450
|
|
|
451
451
|
if verbosity > 0:
|
|
452
|
-
|
|
452
|
+
pp(resp.json())
|
|
453
453
|
return resp.json()
|
|
454
454
|
|
|
455
455
|
|
|
@@ -494,7 +494,7 @@ class Trader:
|
|
|
494
494
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account executions.", f"{self.server_type} server returned {resp.status_code} on get_account_executions().", ex)
|
|
495
495
|
|
|
496
496
|
if verbosity > 1:
|
|
497
|
-
|
|
497
|
+
pp(resp.json())
|
|
498
498
|
return resp.json()
|
|
499
499
|
|
|
500
500
|
|
|
@@ -525,7 +525,7 @@ class Trader:
|
|
|
525
525
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account balances.", f"{self.server_type} server returned {resp.status_code} on get_account_balances().", ex)
|
|
526
526
|
|
|
527
527
|
if verbosity > 0:
|
|
528
|
-
|
|
528
|
+
pp(resp.json())
|
|
529
529
|
return resp.json()
|
|
530
530
|
|
|
531
531
|
|
|
@@ -556,7 +556,7 @@ class Trader:
|
|
|
556
556
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for account positions.", f"{self.server_type} server returned {resp.status_code} on get_account_positions().", ex)
|
|
557
557
|
|
|
558
558
|
if verbosity > 0:
|
|
559
|
-
|
|
559
|
+
pp(resp.json())
|
|
560
560
|
return resp.json()
|
|
561
561
|
|
|
562
562
|
|
|
@@ -583,7 +583,7 @@ class Trader:
|
|
|
583
583
|
|
|
584
584
|
rd = resp.json()
|
|
585
585
|
if verbosity > 0:
|
|
586
|
-
|
|
586
|
+
pp(dt.strptime(rd["time"][:-13], '%Y-%m-%dT%X'))
|
|
587
587
|
return dt.strptime(rd["time"][:-13], '%Y-%m-%dT%X'), rd
|
|
588
588
|
|
|
589
589
|
|
|
@@ -623,7 +623,7 @@ class Trader:
|
|
|
623
623
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for market candles.", f"{self.server_type} server returned {resp.status_code} on get_market_candles().", ex)
|
|
624
624
|
|
|
625
625
|
if verbosity > 0:
|
|
626
|
-
|
|
626
|
+
pp(resp.json())
|
|
627
627
|
return resp.json()
|
|
628
628
|
|
|
629
629
|
|
|
@@ -652,7 +652,7 @@ class Trader:
|
|
|
652
652
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for market quote strategies.", f"{self.server_type} server returned {resp.status_code} on get_market_quotes_strategies().", ex)
|
|
653
653
|
|
|
654
654
|
if verbosity > 0:
|
|
655
|
-
|
|
655
|
+
pp(resp.json())
|
|
656
656
|
return resp.json()
|
|
657
657
|
|
|
658
658
|
|
|
@@ -684,7 +684,7 @@ class Trader:
|
|
|
684
684
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for market quote options.", f"{self.server_type} server returned {resp.status_code} on get_market_quotes_options().", ex)
|
|
685
685
|
|
|
686
686
|
if verbosity > 0:
|
|
687
|
-
|
|
687
|
+
pp(resp.json())
|
|
688
688
|
return resp.json()
|
|
689
689
|
|
|
690
690
|
|
|
@@ -729,7 +729,7 @@ class Trader:
|
|
|
729
729
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for market quotes.", f"{self.server_type} server returned {resp.status_code} on get_market_quotes().", ex)
|
|
730
730
|
|
|
731
731
|
if verbosity > 0:
|
|
732
|
-
|
|
732
|
+
pp(resp.json())
|
|
733
733
|
return resp.json()
|
|
734
734
|
|
|
735
735
|
|
|
@@ -756,7 +756,7 @@ class Trader:
|
|
|
756
756
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for markets.", f"{self.server_type} server returned {resp.status_code} on get_markets().", ex)
|
|
757
757
|
|
|
758
758
|
if verbosity > 0:
|
|
759
|
-
|
|
759
|
+
pp(resp.json())
|
|
760
760
|
return resp.json()
|
|
761
761
|
|
|
762
762
|
|
|
@@ -784,7 +784,7 @@ class Trader:
|
|
|
784
784
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for symbol options.", f"{self.server_type} server returned {resp.status_code} on get_symbol_options().", ex)
|
|
785
785
|
|
|
786
786
|
if verbosity > 0:
|
|
787
|
-
|
|
787
|
+
pp(resp.json())
|
|
788
788
|
return resp.json()
|
|
789
789
|
|
|
790
790
|
|
|
@@ -814,7 +814,7 @@ class Trader:
|
|
|
814
814
|
self._report_and_exit(resp.request.url, resp.text, "Failed to search server for symbols.", f"{self.server_type} server returned {resp.status_code} on search_symbols().", ex)
|
|
815
815
|
|
|
816
816
|
if verbosity > 0:
|
|
817
|
-
|
|
817
|
+
pp(resp.json())
|
|
818
818
|
return resp.json()
|
|
819
819
|
|
|
820
820
|
|
|
@@ -855,7 +855,7 @@ class Trader:
|
|
|
855
855
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for symbols by ids.", f"{self.server_type} server returned {resp.status_code} on get_symbols_by_ids().", ex)
|
|
856
856
|
|
|
857
857
|
if verbosity > 0:
|
|
858
|
-
|
|
858
|
+
pp(resp.json())
|
|
859
859
|
return resp.json()
|
|
860
860
|
|
|
861
861
|
|
|
@@ -889,6 +889,6 @@ class Trader:
|
|
|
889
889
|
self._report_and_exit(resp.request.url, resp.text, "Failed to query server for symbols by names.", f"{self.server_type} server returned {resp.status_code} on get_symbols_by_names().", ex)
|
|
890
890
|
|
|
891
891
|
if verbosity > 0:
|
|
892
|
-
|
|
892
|
+
pp(resp.json())
|
|
893
893
|
return resp.json()
|
|
894
894
|
|
kwess/__main__.py
ADDED
kwess/kwess_acb.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# kwess_acb.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from pprint import pprint as pp
|
|
6
|
+
from datetime import datetime as dt
|
|
7
|
+
import argparse
|
|
8
|
+
import math
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Activities:
|
|
13
|
+
def __init__(self, cut_off_year=0, path="."):
|
|
14
|
+
"""
|
|
15
|
+
Description:
|
|
16
|
+
Initializer of an Activities object.
|
|
17
|
+
Parameters:
|
|
18
|
+
- cut_off_year the ACB will be calculated up until (but not including) the cut_off_year.
|
|
19
|
+
- path directory path in which your Questrade investment activities logs are located.
|
|
20
|
+
Returns:
|
|
21
|
+
Activities object.
|
|
22
|
+
"""
|
|
23
|
+
self.data = []
|
|
24
|
+
self.all_symbols = set()
|
|
25
|
+
self.path = path
|
|
26
|
+
self.symbol = ""
|
|
27
|
+
if cut_off_year == 0:
|
|
28
|
+
self.cut_off_year = dt.today().year
|
|
29
|
+
else:
|
|
30
|
+
self.cut_off_year = cut_off_year
|
|
31
|
+
self.load_from_json_files()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def load_from_json_files(self):
|
|
35
|
+
"""
|
|
36
|
+
Description:
|
|
37
|
+
Loads activities logs. It is called during Activities object initialization.
|
|
38
|
+
"""
|
|
39
|
+
p = Path(self.path)
|
|
40
|
+
if not p.exists():
|
|
41
|
+
print(f"Invalid path: {self.path}")
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
data = []
|
|
44
|
+
for e in p.glob("*activities*.json"):
|
|
45
|
+
with e.open(mode="rt") as f:
|
|
46
|
+
t = f.read()
|
|
47
|
+
t = t.replace("}{", "},{")
|
|
48
|
+
s = "[" + t + "]"
|
|
49
|
+
l = json.loads(s)
|
|
50
|
+
for d in l:
|
|
51
|
+
for v in d.values():
|
|
52
|
+
for a in v:
|
|
53
|
+
#pp(a)
|
|
54
|
+
if (dt.fromisoformat(a["settlementDate"]).year < self.cut_off_year) and (a["action"] in ("Buy", "Sell")):
|
|
55
|
+
data.append(a)
|
|
56
|
+
self.all_symbols.add(a["symbol"])
|
|
57
|
+
self.data = sorted(data, key=lambda x: dt.fromisoformat(x["settlementDate"]))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def generate_adjusted_cost_base(self, symbol, include_fees=True):
|
|
61
|
+
"""
|
|
62
|
+
Description:
|
|
63
|
+
Calculates the ACB and prints profit/loss of Sell transactions for the given symbol.
|
|
64
|
+
Parameters:
|
|
65
|
+
- symbol the ticker symbol.
|
|
66
|
+
- include_fees whether or not to include the commission fees in the calculation. Defaults to True.
|
|
67
|
+
"""
|
|
68
|
+
prev_shares = 0
|
|
69
|
+
prev_cost_base = 0
|
|
70
|
+
prev_cost_base_per_share = 1
|
|
71
|
+
add_newline = False
|
|
72
|
+
for e in self.data:
|
|
73
|
+
if e["symbol"] == symbol.upper():
|
|
74
|
+
if e["action"] == "Buy":
|
|
75
|
+
shares = e["quantity"] + prev_shares
|
|
76
|
+
if include_fees:
|
|
77
|
+
cost_base = math.fabs(e["netAmount"]) + prev_cost_base # includes commission and fees
|
|
78
|
+
else:
|
|
79
|
+
cost_base = math.fabs(e["grossAmount"]) + prev_cost_base # does not include commission and fees
|
|
80
|
+
e["total_shares"] = shares
|
|
81
|
+
e["total_cost_base"] = cost_base
|
|
82
|
+
e["cost_base_per_share"] = cost_base / shares
|
|
83
|
+
prev_shares = shares
|
|
84
|
+
prev_cost_base = cost_base
|
|
85
|
+
prev_cost_base_per_share = e["cost_base_per_share"]
|
|
86
|
+
elif e["action"] == "Sell":
|
|
87
|
+
cost_base_per_share = prev_cost_base_per_share
|
|
88
|
+
if include_fees:
|
|
89
|
+
#print(f"e[grossAmount] {e["grossAmount"]}\ne[commission] {e["commission"]}\ne[quantity] {e["quantity"]}\nprev_cost_base {prev_cost_base}\n prev_shares {prev_shares}")
|
|
90
|
+
capital_gain_loss = e["grossAmount"] + e["commission"] + e["quantity"] * cost_base_per_share
|
|
91
|
+
else:
|
|
92
|
+
capital_gain_loss = e["grossAmount"] + e["quantity"] * cost_base_per_share
|
|
93
|
+
prev_cost_base += e["quantity"] * cost_base_per_share
|
|
94
|
+
prev_shares += e["quantity"]
|
|
95
|
+
e["capital_gain_loss"] = capital_gain_loss
|
|
96
|
+
e["total_shares"] = prev_shares
|
|
97
|
+
e["total_cost_base"] = prev_cost_base # for debugging
|
|
98
|
+
e["cost_base_per_share"] = cost_base_per_share # for debugging
|
|
99
|
+
if capital_gain_loss > 0:
|
|
100
|
+
print(f'{symbol} capital gain of {capital_gain_loss} on {e["settlementDate"]}')
|
|
101
|
+
add_newline = True
|
|
102
|
+
elif capital_gain_loss < 0:
|
|
103
|
+
print(f'{symbol} capital loss of {capital_gain_loss} on {e["settlementDate"]}')
|
|
104
|
+
add_newline = True
|
|
105
|
+
if add_newline:
|
|
106
|
+
print()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def generate_all_ACBs(self, include_fees=True):
|
|
110
|
+
"""
|
|
111
|
+
Description:
|
|
112
|
+
Calculates the ACB and prints profit/loss of Sell transactions for all the symbols present in the activities logs.
|
|
113
|
+
Parameters:
|
|
114
|
+
- include_fees whether or not to include the commission fees in the calculation. Defaults to True.
|
|
115
|
+
"""
|
|
116
|
+
for symbol in self.all_symbols:
|
|
117
|
+
self.generate_adjusted_cost_base(symbol, include_fees)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def print_by_symbol(self, symbol):
|
|
121
|
+
"""
|
|
122
|
+
Description:
|
|
123
|
+
Prints the activities logs relating to symbol.
|
|
124
|
+
Parameters:
|
|
125
|
+
- symbol the ticker symbol.
|
|
126
|
+
"""
|
|
127
|
+
for e in self.data:
|
|
128
|
+
if e["symbol"] == symbol.upper():
|
|
129
|
+
pp(e)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def __str__(self):
|
|
133
|
+
"""
|
|
134
|
+
Description:
|
|
135
|
+
Used for printing the activities logs.
|
|
136
|
+
Returns:
|
|
137
|
+
String representation of the activities logs.
|
|
138
|
+
"""
|
|
139
|
+
s = ""
|
|
140
|
+
for e in self.data:
|
|
141
|
+
s = "\n".join([s, str(e)])
|
|
142
|
+
return s
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def __repr__(self):
|
|
146
|
+
"""
|
|
147
|
+
Description:
|
|
148
|
+
Used for printing the activities object.
|
|
149
|
+
Returns:
|
|
150
|
+
String representation of the Activities object.
|
|
151
|
+
"""
|
|
152
|
+
return f"Activities(data: {self.data}\nsymbol: {self.symbol}\nall_symbols: {self.all_symbols}\npath: {self.path}\ncut_off_year: {self.cut_off_year})"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def main():
|
|
156
|
+
"""
|
|
157
|
+
Description:
|
|
158
|
+
Calculates the ACB and prints the profit/loss of Sell transactions for the symbol(s) present in the activities logs.
|
|
159
|
+
"""
|
|
160
|
+
parser = argparse.ArgumentParser(prog="kwess_acb.py", description="Computes the ACB (Average/Adjusted Cost Base) from kwess activity logs, and prints profit/loss of Sell transactions.")
|
|
161
|
+
parser.add_argument("-s", "--symbol", nargs="+", help="ticker symbol(s).")
|
|
162
|
+
parser.add_argument("-y", "--cut_off_year", default=0, help="cut off year. defaults to the current year.")
|
|
163
|
+
parser.add_argument("-p", "--path", default=".", help="path of the directory containing the logs. defaults to the current directory.")
|
|
164
|
+
args = parser.parse_args()
|
|
165
|
+
|
|
166
|
+
acts = Activities(cut_off_year=int(args.cut_off_year), path=args.path)
|
|
167
|
+
if args.symbol:
|
|
168
|
+
for symbol in args.symbol:
|
|
169
|
+
acts.generate_adjusted_cost_base(symbol)
|
|
170
|
+
else:
|
|
171
|
+
acts.generate_all_ACBs()
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
main()
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kwess
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: Questrade API wrapper.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Project-URL: Bug Tracker, https://github.com/kaiyoux/kwess/issues
|
|
12
|
-
Keywords: Questrade,api,REST,wrapper
|
|
5
|
+
Author-email: Issa Lompo <kaiyoux@gmail.com>
|
|
6
|
+
Maintainer-email: Issa Lompo <kaiyoux@gmail.com>
|
|
7
|
+
License-Expression: GPL-3.0-or-later
|
|
8
|
+
Project-URL: Homepage, https://github.com/pypa/kwess
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com
|
|
10
|
+
Keywords: questrade,api,REST,wrapper,ACB,profit,loss,average cost base,adjusted cost base,logs,kwess
|
|
13
11
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
15
12
|
Classifier: Operating System :: OS Independent
|
|
16
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
17
14
|
Classifier: Intended Audience :: Developers
|
|
18
15
|
Requires-Python: >=3.6
|
|
19
16
|
Description-Content-Type: text/markdown
|
|
20
17
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist: requests
|
|
18
|
+
Requires-Dist: requests>=2.28.1
|
|
19
|
+
Dynamic: license-file
|
|
22
20
|
|
|
23
21
|
# Introduction
|
|
24
22
|
|
|
25
23
|
Yet another Questrade API wrapper.
|
|
26
|
-
|
|
27
24
|
For details about the input parameters and output results, please visit
|
|
28
25
|
the [Questrade API documentation](https://www.questrade.com/api/home).
|
|
29
26
|
|
|
27
|
+
Also includes an executable module that determines the ACB
|
|
28
|
+
(Average/Adjusted Cost Base) of buy and sell activities from
|
|
29
|
+
saved logs, and prints the profit/loss amounts of sell transactions
|
|
30
|
+
up till, but not including, a given cut-off year.
|
|
31
|
+
|
|
30
32
|
### To install:
|
|
31
33
|
**python -m pip install kwess**
|
|
32
34
|
|
|
@@ -99,7 +101,7 @@ print(accs)
|
|
|
99
101
|
sim = qs.search_symbols("vfv", verbose="88")
|
|
100
102
|
print(sim)
|
|
101
103
|
|
|
102
|
-
sim = qs.get_symbols_by_names("xdiv.to,xuu.to,
|
|
104
|
+
sim = qs.get_symbols_by_names("xdiv.to,xuu.to,qqc.to", verbose="**")
|
|
103
105
|
print(sim)
|
|
104
106
|
|
|
105
107
|
sim = qs.get_symbols_by_names("hom.un.to")
|
|
@@ -128,6 +130,50 @@ pprint(ops)
|
|
|
128
130
|
|
|
129
131
|
```
|
|
130
132
|
|
|
133
|
+
# Sample Script To Pull Your Questrade Logs
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
from kwess import Trader
|
|
137
|
+
from datetime import datetime as dt
|
|
138
|
+
import json
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_logs(qt, startdate, enddate=None, accounttype="TFSA"):
|
|
142
|
+
"""
|
|
143
|
+
Parameters:
|
|
144
|
+
- qt Trader object.
|
|
145
|
+
- startdate datetime object for beginning period.
|
|
146
|
+
- enddate datetime object for end period. Defaults to None, which will be treated as now.
|
|
147
|
+
- accounttype type of account for which activities will be obtained. Defaults to TFSA.
|
|
148
|
+
"""
|
|
149
|
+
if enddate == None:
|
|
150
|
+
enddate = dt.now()
|
|
151
|
+
for filename in ["activities", "orders", "executions"]:
|
|
152
|
+
filename = accounttype + "_account_" + filename + "_from_" + str(startdate.date()) + "_to_" + str(enddate.date()) + ".json"
|
|
153
|
+
with open(filename, mode="at", encoding="utf-8") as jfp:
|
|
154
|
+
if "activities" in filename:
|
|
155
|
+
accs = qt.get_account_activities(accounttype=accounttype, startdatetime=startdate, enddatetime=enddate, verbose="nnn")
|
|
156
|
+
elif "orders" in filename:
|
|
157
|
+
accs = qt.get_account_orders(accounttype=accounttype, startdatetime=startdate, enddatetime=enddate, verbose="nnn")
|
|
158
|
+
else:
|
|
159
|
+
accs = qt.get_account_executions(accounttype=accounttype, startdatetime=startdate, enddatetime=enddate, verbose='nnn')
|
|
160
|
+
|
|
161
|
+
for acc in accs:
|
|
162
|
+
json.dump(acc, jfp, ensure_ascii=False, indent=2)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
if __name__ == "__main__":
|
|
168
|
+
#account_types = ["TFSA", "Cash", "Margin"]
|
|
169
|
+
#account_types = ["Cash"]
|
|
170
|
+
account_types = ["Margin"]
|
|
171
|
+
qt = Trader(verbose='n')
|
|
172
|
+
|
|
173
|
+
for acc_type in account_types:
|
|
174
|
+
get_logs(qt=qt, accounttype=acc_type, startdate=dt(year=2025, month=9, day=17))
|
|
175
|
+
|
|
176
|
+
```
|
|
131
177
|
|
|
132
178
|
# API Class And Methods
|
|
133
179
|
|
|
@@ -501,5 +547,32 @@ Returns:
|
|
|
501
547
|
If gmt is True, the returned time will be considered as gmt time.
|
|
502
548
|
```
|
|
503
549
|
|
|
550
|
+
# Example of Executable Module
|
|
551
|
+
|
|
552
|
+
Open a command line in the directory containing your logs, and run the module:
|
|
553
|
+
```
|
|
554
|
+
kwess_acb
|
|
555
|
+
(or)
|
|
556
|
+
python -m kwess.kwess_acb
|
|
557
|
+
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### To run the scrpit:
|
|
561
|
+
**kwess_acb [-h] [-s SYMBOL [SYMBOL ...]] [-y CUT_OFF_YEAR] [-p PATH]**
|
|
562
|
+
```
|
|
563
|
+
Computes the ACB (Average/Adjusted Cost Base) from kwess activity logs, and
|
|
564
|
+
prints profit/loss of Sell transactions.
|
|
565
|
+
|
|
566
|
+
options:
|
|
567
|
+
-h, --help show this help message and exit.
|
|
568
|
+
-s SYMBOL [SYMBOL ...], --symbol SYMBOL [SYMBOL ...]
|
|
569
|
+
ticker symbol(s).
|
|
570
|
+
-y CUT_OFF_YEAR, --cut_off_year CUT_OFF_YEAR
|
|
571
|
+
cut off year. defaults to the current year.
|
|
572
|
+
-p PATH, --path PATH path of the directory containing the logs.
|
|
573
|
+
defaults to the current directory.
|
|
574
|
+
|
|
575
|
+
```
|
|
576
|
+
|
|
504
577
|
|
|
505
578
|
Let me know if you have any questions: <kaiyoux@gmail.com>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
kwess/__init__.py,sha256=ma5qr504ZX-5aB3pSJz6OIXncDpdv-j0L7GyeDAOLe8,43905
|
|
2
|
+
kwess/__main__.py,sha256=Y3IEU-vW_vbl_cpabJfofkyJPvjrZM-AnEKWitFUdeQ,86
|
|
3
|
+
kwess/kwess_acb.py,sha256=fIEwBgygiYbSdmvwcq-utDIS4wJa7iJv9FcJT72PZJI,7239
|
|
4
|
+
kwess-0.1.0.dist-info/licenses/LICENSE.txt,sha256=gcuuhKKc5-dwvyvHsXjlC9oM6N5gZ6umYbC8ewW1Yvg,35821
|
|
5
|
+
kwess-0.1.0.dist-info/METADATA,sha256=y7LMOdHx1DcSIhalWYfANCuDL73bOLbRCnsiZFF7z24,22714
|
|
6
|
+
kwess-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
7
|
+
kwess-0.1.0.dist-info/entry_points.txt,sha256=jzERIdOqYeuefJsph3YQRGdUZYVdN1uo4SAQq17SNMI,51
|
|
8
|
+
kwess-0.1.0.dist-info/top_level.txt,sha256=jdYzcYQHwnZajr9CyHMIRBi6MrEGYTJ-uaAT3M50kP0,6
|
|
9
|
+
kwess-0.1.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
10
|
+
kwess-0.1.0.dist-info/RECORD,,
|
kwess-0.0.7.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
kwess/__init__.py,sha256=hG0J_zyNPRCVd-_VEbg9a26HvtfcbdnkUHpRJ0PhyGI,43967
|
|
2
|
-
kwess-0.0.7.dist-info/LICENSE.txt,sha256=gcuuhKKc5-dwvyvHsXjlC9oM6N5gZ6umYbC8ewW1Yvg,35821
|
|
3
|
-
kwess-0.0.7.dist-info/METADATA,sha256=MbNWz6np_171fBoycthEz60AQ7kqj3APbDS7sykUpH0,19940
|
|
4
|
-
kwess-0.0.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
5
|
-
kwess-0.0.7.dist-info/top_level.txt,sha256=jdYzcYQHwnZajr9CyHMIRBi6MrEGYTJ-uaAT3M50kP0,6
|
|
6
|
-
kwess-0.0.7.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
7
|
-
kwess-0.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|