financegy 0.1.0__tar.gz → 1.5__tar.gz

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.
financegy-1.5/PKG-INFO ADDED
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: financegy
3
+ Version: 1.5
4
+ Summary: Unofficial Python library for accessing GSE (Guyana Stock Exchange) financial data
5
+ Author-email: Ezra Minty <ezranminty@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/xbze3/financegy
8
+ Project-URL: Issues, https://github.com/xbze3/financegy/issues
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: requests
12
+ Requires-Dist: beautifulsoup4
13
+ Requires-Dist: pandas
14
+ Requires-Dist: openpyxl
15
+ Dynamic: license-file
16
+
17
+ # 🏦 FinanceGY
18
+
19
+ **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
20
+
21
+ ---
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install financegy
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Quick Start
32
+
33
+ ```python
34
+ import financegy
35
+
36
+ # Get a list of all traded securities
37
+ securities = financegy.get_securities()
38
+
39
+ # Get the name of a security by its ticker symbol
40
+ security_name = financegy.get_security_by_symbol("DDL")
41
+
42
+ # Get the most recent trade data for a security
43
+ recent_trade = financegy.get_recent_trade("DDL")
44
+
45
+ # Get all trade data for the most recent year
46
+ recent_year = financegy.get_security_recent_year("DDL")
47
+
48
+ # Get trade data for a specific trading session
49
+ session_trades = financegy.get_session_trades("1136")
50
+
51
+ # Get session trade data for a specific security
52
+ security_session_trade = financegy.get_security_session_trade("DDL", "1136")
53
+
54
+ # Search for securities by name or symbol
55
+ search_results = financegy.search_securities("DDL")
56
+
57
+ # Get all trades for a given year
58
+ year_trades = financegy.get_trades_for_year("DDL", "2019")
59
+
60
+ # Get historical trades within a date range - (yyyy) / (mm/yyyy) / (dd/mm/yyyy)
61
+ historical_trades = financegy.get_historical_trades(
62
+ symbol="DDL",
63
+ start_date="01/06/2020",
64
+ end_date="01/2022"
65
+ )
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Data Retrieval
71
+
72
+ | Function | Description |
73
+ | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
74
+ | `get_securities()` | Returns a list of all currently traded securities on the GSE. |
75
+ | `get_security_by_symbol(symbol: str)` | Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`). |
76
+ | `get_recent_trade(symbol: str)` | Returns the most recent trade information for the given security. |
77
+ | `get_security_recent_year(symbol: str)` | Fetches all trade data for the most recent year of the selected security. |
78
+ | `get_session_trades(session: str)` | Retrieves trade data for all securities during a specific trading session. |
79
+ | `get_security_session_trade(symbol: str, session: str)` | Retrieves trade data for a specific security in a given trading session. |
80
+ | `search_securities(query: str)` | Searches for securities whose names or ticker symbols match the given query. |
81
+ | `get_trades_for_year(symbol: str, year: str)` | Returns all trade records for a specific security during a given year. |
82
+ | `get_historical_trades(symbol: str, start_date: str, end_date: str)` | Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy`, `mm/yyyy`, `yyyy` format). |
83
+
84
+ ---
85
+
86
+ ### Data Utilities
87
+
88
+ | Function | Description |
89
+ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
+ | `to_dataframe(data)` | Converts a list (or dictionary) of trade data into a Pandas DataFrame for easy analysis. Raises `TypeError` if the data is not properly formatted. |
91
+ | `save_to_csv(data, filename: str = "output.csv", path: str = None)` | Saves the given data to a CSV file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
92
+ | `save_to_excel(data, filename: str = "output.xlsx", path: str = None)` | Saves the given data to an Excel `.xlsx` file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
93
+
94
+ ---
95
+
96
+ ## Caching System
97
+
98
+ FinanceGY includes a lightweight local caching system designed to speed up repeated requests and reduce unnecessary calls.
99
+
100
+ Whenever you call a data retrieval function (such as `get_securities()` or `get_recent_trade()`), FinanceGY automatically checks whether a cached response already exists for that specific query:
101
+
102
+ - If a valid cache file (less than 7 days old since sessions are held once per week) is found, the result is returned instantly from the cache.
103
+ - If the cache is missing, disabled, or older than one week, FinanceGY fetches fresh data from the GSE and updates the cache automatically.
104
+
105
+ All cache files are stored in a local `cache/` directory as small JSON files containing the retrieved data and a timestamp.
106
+
107
+ You can manually clear all cached data at any time:
108
+
109
+ ```python
110
+ import financegy
111
+
112
+ financegy.clear_cache()
113
+ ```
114
+
115
+ This will delete all cached files and force the next data request to fetch fresh data directly from the source.
116
+
117
+ If you prefer to bypass the cache for a specific call, simply pass `use_cache=False` to any function. For example:
118
+
119
+ ```python
120
+ # Force a fresh fetch from the GSE, ignoring cached data
121
+ recent_trade = financegy.get_recent_trade("DDL", use_cache=False)
122
+ ```
123
+
124
+ By default, caching is enabled for all supported functions unless explicitly turned off.
125
+
126
+ ---
127
+
128
+ ## License
129
+
130
+ This project is licensed under the **MIT License**
131
+
132
+ ---
133
+
134
+ ## Example Use Case
135
+
136
+ ```python
137
+ import financegy
138
+
139
+ ddl_recent = financegy.get_security_recent("DDL")
140
+ print(ddl_recent)
141
+ ```
@@ -0,0 +1,125 @@
1
+ # 🏦 FinanceGY
2
+
3
+ **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install financegy
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Quick Start
16
+
17
+ ```python
18
+ import financegy
19
+
20
+ # Get a list of all traded securities
21
+ securities = financegy.get_securities()
22
+
23
+ # Get the name of a security by its ticker symbol
24
+ security_name = financegy.get_security_by_symbol("DDL")
25
+
26
+ # Get the most recent trade data for a security
27
+ recent_trade = financegy.get_recent_trade("DDL")
28
+
29
+ # Get all trade data for the most recent year
30
+ recent_year = financegy.get_security_recent_year("DDL")
31
+
32
+ # Get trade data for a specific trading session
33
+ session_trades = financegy.get_session_trades("1136")
34
+
35
+ # Get session trade data for a specific security
36
+ security_session_trade = financegy.get_security_session_trade("DDL", "1136")
37
+
38
+ # Search for securities by name or symbol
39
+ search_results = financegy.search_securities("DDL")
40
+
41
+ # Get all trades for a given year
42
+ year_trades = financegy.get_trades_for_year("DDL", "2019")
43
+
44
+ # Get historical trades within a date range - (yyyy) / (mm/yyyy) / (dd/mm/yyyy)
45
+ historical_trades = financegy.get_historical_trades(
46
+ symbol="DDL",
47
+ start_date="01/06/2020",
48
+ end_date="01/2022"
49
+ )
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Data Retrieval
55
+
56
+ | Function | Description |
57
+ | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
58
+ | `get_securities()` | Returns a list of all currently traded securities on the GSE. |
59
+ | `get_security_by_symbol(symbol: str)` | Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`). |
60
+ | `get_recent_trade(symbol: str)` | Returns the most recent trade information for the given security. |
61
+ | `get_security_recent_year(symbol: str)` | Fetches all trade data for the most recent year of the selected security. |
62
+ | `get_session_trades(session: str)` | Retrieves trade data for all securities during a specific trading session. |
63
+ | `get_security_session_trade(symbol: str, session: str)` | Retrieves trade data for a specific security in a given trading session. |
64
+ | `search_securities(query: str)` | Searches for securities whose names or ticker symbols match the given query. |
65
+ | `get_trades_for_year(symbol: str, year: str)` | Returns all trade records for a specific security during a given year. |
66
+ | `get_historical_trades(symbol: str, start_date: str, end_date: str)` | Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy`, `mm/yyyy`, `yyyy` format). |
67
+
68
+ ---
69
+
70
+ ### Data Utilities
71
+
72
+ | Function | Description |
73
+ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
+ | `to_dataframe(data)` | Converts a list (or dictionary) of trade data into a Pandas DataFrame for easy analysis. Raises `TypeError` if the data is not properly formatted. |
75
+ | `save_to_csv(data, filename: str = "output.csv", path: str = None)` | Saves the given data to a CSV file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
76
+ | `save_to_excel(data, filename: str = "output.xlsx", path: str = None)` | Saves the given data to an Excel `.xlsx` file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
77
+
78
+ ---
79
+
80
+ ## Caching System
81
+
82
+ FinanceGY includes a lightweight local caching system designed to speed up repeated requests and reduce unnecessary calls.
83
+
84
+ Whenever you call a data retrieval function (such as `get_securities()` or `get_recent_trade()`), FinanceGY automatically checks whether a cached response already exists for that specific query:
85
+
86
+ - If a valid cache file (less than 7 days old since sessions are held once per week) is found, the result is returned instantly from the cache.
87
+ - If the cache is missing, disabled, or older than one week, FinanceGY fetches fresh data from the GSE and updates the cache automatically.
88
+
89
+ All cache files are stored in a local `cache/` directory as small JSON files containing the retrieved data and a timestamp.
90
+
91
+ You can manually clear all cached data at any time:
92
+
93
+ ```python
94
+ import financegy
95
+
96
+ financegy.clear_cache()
97
+ ```
98
+
99
+ This will delete all cached files and force the next data request to fetch fresh data directly from the source.
100
+
101
+ If you prefer to bypass the cache for a specific call, simply pass `use_cache=False` to any function. For example:
102
+
103
+ ```python
104
+ # Force a fresh fetch from the GSE, ignoring cached data
105
+ recent_trade = financegy.get_recent_trade("DDL", use_cache=False)
106
+ ```
107
+
108
+ By default, caching is enabled for all supported functions unless explicitly turned off.
109
+
110
+ ---
111
+
112
+ ## License
113
+
114
+ This project is licensed under the **MIT License**
115
+
116
+ ---
117
+
118
+ ## Example Use Case
119
+
120
+ ```python
121
+ import financegy
122
+
123
+ ddl_recent = financegy.get_security_recent("DDL")
124
+ print(ddl_recent)
125
+ ```
@@ -14,6 +14,9 @@ from financegy.modules.securities import(
14
14
  get_historical_trades
15
15
  )
16
16
 
17
+ from financegy.cache.cache_manager import clear_cache
18
+ from financegy.utils.utils import save_to_csv, to_dataframe, save_to_excel
19
+
17
20
  __all__ = [
18
21
  "get_securities",
19
22
  "get_security_by_symbol",
@@ -23,5 +26,9 @@ __all__ = [
23
26
  "get_security_session_trade",
24
27
  "search_securities",
25
28
  "get_trades_for_year",
26
- "get_historical_trades"
29
+ "get_historical_trades",
30
+ "clear_cache",
31
+ "save_to_csv",
32
+ "to_dataframe",
33
+ "save_to_excel"
27
34
  ]
@@ -0,0 +1,62 @@
1
+ import os, json, hashlib
2
+ from datetime import datetime, timedelta
3
+ import shutil
4
+
5
+ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
6
+ CACHE_DIR = os.path.join(SCRIPT_DIR, "cache")
7
+
8
+ def make_cache_key(func_name, *args, **kwargs):
9
+ """Create a unique hash for the given function call."""
10
+
11
+ key_data = {
12
+ "func": func_name,
13
+ "args": args,
14
+ "kwargs": kwargs
15
+ }
16
+
17
+ key_string = json.dumps(key_data, sort_keys=True, default=str)
18
+ hashed = hashlib.md5(key_string.encode()).hexdigest()
19
+
20
+ return f"{func_name}_{hashed}.json"
21
+
22
+ def load_cache(func_name, *args, max_age_days=7, **kwargs):
23
+ os.makedirs(CACHE_DIR, exist_ok=True)
24
+ cache_file = make_cache_key(func_name, *args, **kwargs)
25
+ cache_path = os.path.join(CACHE_DIR, cache_file)
26
+
27
+ if not os.path.exists(cache_path):
28
+ return None
29
+
30
+ with open(cache_path, "r") as f:
31
+ data = json.load(f)
32
+
33
+ timestamp = datetime.fromisoformat(data["timestamp"])
34
+ if datetime.now() - timestamp > timedelta(days=max_age_days):
35
+ return None
36
+
37
+ return data["value"]
38
+
39
+ def save_cache(func_name, value, *args, **kwargs):
40
+ os.makedirs(CACHE_DIR, exist_ok=True)
41
+ cache_file = make_cache_key(func_name, *args, **kwargs)
42
+ cache_path = os.path.join(CACHE_DIR, cache_file)
43
+
44
+ with open(cache_path, "w") as f:
45
+ json.dump({
46
+ "timestamp": datetime.now().isoformat(),
47
+ "value": value
48
+ }, f)
49
+
50
+ def clear_cache():
51
+ """Completely clears the FinanceGY cache directory."""
52
+ if not os.path.exists(CACHE_DIR):
53
+ print("No cache directory found.")
54
+ return False
55
+
56
+ try:
57
+ shutil.rmtree(CACHE_DIR)
58
+ print("Cache cleared successfully.")
59
+ return True
60
+
61
+ except Exception as e:
62
+ print(f"Failed to clear cache: {e}")
@@ -217,16 +217,37 @@ def parse_get_trades_for_year(year: str, html: str):
217
217
  print(f"[parse_get_security_recent_year] Error parsing HTML: {e}")
218
218
  return None
219
219
 
220
+ from datetime import datetime
221
+ from bs4 import BeautifulSoup
220
222
 
221
223
  def parse_get_historical_trades(start_date: str, end_date: str, html: str):
222
224
  """Parse historical trade data from HTML between given dates (DD/MM/YYYY)"""
223
225
 
226
+ def normalize_date(date_str: str) -> str:
227
+ parts = date_str.split("/")
228
+ if len(parts) == 1:
229
+ day, month, year = "01", "01", parts[0]
230
+ elif len(parts) == 2:
231
+ day, month, year = "01", parts[0], parts[1]
232
+ elif len(parts) == 3:
233
+ day, month, year = parts
234
+ else:
235
+ raise ValueError(f"Invalid date format: {date_str}")
236
+
237
+ try:
238
+ datetime(int(year), int(month), int(day))
239
+ except ValueError as e:
240
+ raise ValueError(f"Invalid date generated from {date_str}: {e}")
241
+
242
+ return f"{day.zfill(2)}/{month.zfill(2)}/{year}"
243
+
224
244
  try:
245
+ start_date = normalize_date(start_date)
246
+ end_date = normalize_date(end_date)
225
247
  start = datetime.strptime(start_date, "%d/%m/%Y")
226
248
  end = datetime.strptime(end_date, "%d/%m/%Y")
227
249
 
228
250
  soup = BeautifulSoup(html, "html.parser")
229
-
230
251
  year_sections = soup.find_all("div", class_="year slide")
231
252
  if not year_sections:
232
253
  raise ValueError("No 'div.year.slide' sections found in HTML.")
@@ -242,8 +263,8 @@ def parse_get_historical_trades(start_date: str, end_date: str, html: str):
242
263
  if not year_id or not year_id.isdigit():
243
264
  continue
244
265
 
245
- year = int(year_id)
246
- if year < start.year or year > end.year:
266
+ year_int = int(year_id)
267
+ if year_int < start.year or year_int > end.year:
247
268
  continue
248
269
 
249
270
  trades = section.find_all("tr", class_="trade")
@@ -270,7 +291,6 @@ def parse_get_historical_trades(start_date: str, end_date: str, html: str):
270
291
  })
271
292
 
272
293
  trade_data.sort(key=lambda x: datetime.strptime(x["date"], "%d/%m/%Y"))
273
-
274
294
  return trade_data
275
295
 
276
296
  except Exception as e:
@@ -1,13 +1,26 @@
1
1
  from financegy.core import request_handler, parser
2
+ from financegy.cache import cache_manager
2
3
 
3
- def get_securities():
4
+ def get_securities(use_cache=True):
4
5
  """Get names of all currently traded securities"""
6
+
7
+ func_name = "get_securities"
8
+
9
+ if use_cache:
10
+ cached = cache_manager.load_cache(func_name)
11
+ if cached:
12
+ return parser.parse_get_securities(cached)
13
+
5
14
  path = "/securities/"
6
15
  html = request_handler.fetch_page(path)
16
+
17
+ cache_manager.save_cache(func_name, html)
18
+
7
19
  return parser.parse_get_securities(html);
8
20
 
9
- def get_security_by_symbol(symbol: str):
21
+ def get_security_by_symbol(symbol: str, use_cache=True):
10
22
  """Get the security details by its ticker symbol"""
23
+
11
24
  securities = get_securities()
12
25
 
13
26
  symbol = symbol.strip().upper()
@@ -17,70 +30,127 @@ def get_security_by_symbol(symbol: str):
17
30
  None,
18
31
  )
19
32
 
20
- def get_security_recent_year(symbol:str):
33
+ def get_security_recent_year(symbol:str, use_cache=True):
21
34
  """Get the most recent year's trade data for any of the traded securities"""
22
35
 
36
+ func_name = "get_security_recent_year"
37
+
23
38
  security_name = get_security_by_symbol(symbol)
24
39
  security_name = security_name.lower().replace(" ", "-")
25
40
 
41
+ if use_cache:
42
+ cached = cache_manager.load_cache(func_name, symbol)
43
+ if cached:
44
+ return parser.parse_get_security_recent_year(cached)
45
+
26
46
  path = "/security/" + security_name
27
47
  html = request_handler.fetch_page(path)
48
+
49
+ cache_manager.save_cache(func_name, html, symbol)
50
+
28
51
  return parser.parse_get_security_recent_year(html)
29
52
 
30
- def get_recent_trade(symbol: str):
53
+ def get_recent_trade(symbol: str, use_cache=True):
31
54
  """Get the most recent trade data for any of the traded securities"""
55
+
56
+ func_name = "get_recent_trade"
32
57
 
33
58
  security_name = get_security_by_symbol(symbol)
34
59
  security_name = security_name.lower().replace(" ", "-")
35
60
 
61
+ if use_cache:
62
+ cached = cache_manager.load_cache(func_name, symbol)
63
+ if cached:
64
+ return parser.parse_get_recent_trade(cached)
65
+
36
66
  path = "/security/" + security_name
37
67
  html = request_handler.fetch_page(path)
68
+
69
+ cache_manager.save_cache(func_name, html, symbol)
70
+
38
71
  return parser.parse_get_recent_trade(html)
39
72
 
40
- def get_session_trades(session: str):
73
+ def get_session_trades(session: str, use_cache=True):
41
74
  """Get the session trade data for all the available securities"""
42
75
 
76
+ func_name = "get_session_trades"
77
+
78
+ if use_cache:
79
+ cached = cache_manager.load_cache(func_name, session)
80
+ if cached:
81
+ return parser.parse_get_session_trades(cached)
82
+
43
83
  path = f"/financial_session/{session}/"
44
84
  html = request_handler.fetch_page(path)
85
+
86
+ cache_manager.save_cache(func_name, html, session)
87
+
45
88
  return parser.parse_get_session_trades(html)
46
89
 
47
- def get_security_session_trade(symbol: str, session: str):
90
+ def get_security_session_trade(symbol: str, session: str, use_cache=True):
48
91
  """Get the session trade data for a given security"""
49
92
 
93
+ func_name = "get_security_session_trade"
94
+
50
95
  symbol = symbol.strip().upper()
51
96
 
97
+ if use_cache:
98
+ cached = cache_manager.load_cache(func_name, symbol, session)
99
+ if cached:
100
+ return parser.parse_get_security_session_trade(symbol, cached)
101
+
52
102
  path = f"/financial_session/{session}/"
53
103
  html = request_handler.fetch_page(path)
54
- return parser.parse_get_security_session_trade(symbol, html)
55
104
 
105
+ cache_manager.save_cache(func_name, html, symbol, session)
106
+
107
+ return parser.parse_get_security_session_trade(symbol, html)
56
108
 
57
- def get_trades_for_year(symbol: str, year: str):
109
+ def get_trades_for_year(symbol: str, year: str, use_cache=True):
58
110
  """Get security trade information from a specific year"""
59
111
 
112
+ func_name = "get_trades_for_year"
113
+
60
114
  symbol = symbol.strip().upper()
61
115
 
116
+ if use_cache:
117
+ cached = cache_manager.load_cache(func_name, symbol, year)
118
+ if cached:
119
+ return parser.parse_get_trades_for_year(year, cached)
120
+
62
121
  security_name = get_security_by_symbol(symbol)
63
122
  security_name = security_name.lower().replace(" ", "-")
64
123
 
65
124
  path = f"/security/{security_name}/"
66
125
  html = request_handler.fetch_page(path)
67
126
 
127
+ cache_manager.save_cache(func_name, html, symbol, year)
128
+
68
129
  return parser.parse_get_trades_for_year(year, html)
69
130
 
70
- def get_historical_trades(symbol: str, start_date: str, end_date: str):
131
+ def get_historical_trades(symbol: str, start_date: str, end_date: str, use_cache=True):
71
132
  """Get historical trade data for a date range"""
72
133
 
134
+ func_name = "get_historical_trades"
135
+
73
136
  symbol = symbol.strip().upper()
74
137
 
138
+ if use_cache:
139
+ cached = cache_manager.load_cache(func_name, symbol, start_date, end_date)
140
+ if cached:
141
+ return parser.parse_get_historical_trades(start_date, end_date, cached)
142
+
75
143
  security_name = get_security_by_symbol(symbol)
76
144
  security_name = security_name.lower().replace(" ", "-")
77
145
 
78
146
  path = f"/security/{security_name}/"
79
147
  html = request_handler.fetch_page(path)
80
148
 
149
+ cache_manager.save_cache(func_name, html, symbol, start_date, end_date)
150
+
81
151
  return parser.parse_get_historical_trades(start_date, end_date, html)
82
152
 
83
- def search_securities(query: str):
153
+ def search_securities(query: str, use_cache=True):
84
154
  """Search securities by symbol or name (partial match)"""
85
155
 
86
156
  query = query.lower().strip()
@@ -0,0 +1,52 @@
1
+ import os
2
+ import pandas as pd
3
+
4
+ def to_dataframe(data: dict | list[dict]):
5
+ """Output as Dataframe"""
6
+
7
+ if isinstance(data, list) and not all(isinstance(item, dict) for item in data):
8
+ raise TypeError("All items in the list must be dictionaries")
9
+ elif not isinstance(data, (dict, list)):
10
+ raise TypeError("data must be a dict or a list of dicts")
11
+
12
+ if isinstance(data, dict):
13
+ data = [data]
14
+
15
+ return pd.DataFrame(data)
16
+
17
+ def save_to_csv(data, filename: str = "output.csv", path: str = None):
18
+ """Save a list of dicts to CSV"""
19
+
20
+ if path is None:
21
+ path = os.getcwd()
22
+ else:
23
+ path = os.path.abspath(path)
24
+
25
+ full_path = os.path.join(path, filename)
26
+
27
+ df = to_dataframe(data)
28
+
29
+ df.to_csv(full_path, index=False)
30
+
31
+ print(f"Saved CSV to: {full_path}")
32
+
33
+ return True
34
+
35
+ def save_to_excel(data: dict | list[dict], filename: str = "output.xlsx", path: str = None):
36
+ """Save data to an Excel spreadsheet."""
37
+
38
+ if path is None:
39
+ path = os.getcwd()
40
+ else:
41
+ path = os.path.abspath(path)
42
+
43
+ full_path = os.path.join(path, filename)
44
+ df = to_dataframe(data)
45
+ df.to_excel(full_path, index=False)
46
+
47
+ print(f"Saved Excel Document to: {full_path}")
48
+
49
+ return True
50
+
51
+
52
+
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: financegy
3
+ Version: 1.5
4
+ Summary: Unofficial Python library for accessing GSE (Guyana Stock Exchange) financial data
5
+ Author-email: Ezra Minty <ezranminty@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/xbze3/financegy
8
+ Project-URL: Issues, https://github.com/xbze3/financegy/issues
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: requests
12
+ Requires-Dist: beautifulsoup4
13
+ Requires-Dist: pandas
14
+ Requires-Dist: openpyxl
15
+ Dynamic: license-file
16
+
17
+ # 🏦 FinanceGY
18
+
19
+ **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
20
+
21
+ ---
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install financegy
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Quick Start
32
+
33
+ ```python
34
+ import financegy
35
+
36
+ # Get a list of all traded securities
37
+ securities = financegy.get_securities()
38
+
39
+ # Get the name of a security by its ticker symbol
40
+ security_name = financegy.get_security_by_symbol("DDL")
41
+
42
+ # Get the most recent trade data for a security
43
+ recent_trade = financegy.get_recent_trade("DDL")
44
+
45
+ # Get all trade data for the most recent year
46
+ recent_year = financegy.get_security_recent_year("DDL")
47
+
48
+ # Get trade data for a specific trading session
49
+ session_trades = financegy.get_session_trades("1136")
50
+
51
+ # Get session trade data for a specific security
52
+ security_session_trade = financegy.get_security_session_trade("DDL", "1136")
53
+
54
+ # Search for securities by name or symbol
55
+ search_results = financegy.search_securities("DDL")
56
+
57
+ # Get all trades for a given year
58
+ year_trades = financegy.get_trades_for_year("DDL", "2019")
59
+
60
+ # Get historical trades within a date range - (yyyy) / (mm/yyyy) / (dd/mm/yyyy)
61
+ historical_trades = financegy.get_historical_trades(
62
+ symbol="DDL",
63
+ start_date="01/06/2020",
64
+ end_date="01/2022"
65
+ )
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Data Retrieval
71
+
72
+ | Function | Description |
73
+ | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
74
+ | `get_securities()` | Returns a list of all currently traded securities on the GSE. |
75
+ | `get_security_by_symbol(symbol: str)` | Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`). |
76
+ | `get_recent_trade(symbol: str)` | Returns the most recent trade information for the given security. |
77
+ | `get_security_recent_year(symbol: str)` | Fetches all trade data for the most recent year of the selected security. |
78
+ | `get_session_trades(session: str)` | Retrieves trade data for all securities during a specific trading session. |
79
+ | `get_security_session_trade(symbol: str, session: str)` | Retrieves trade data for a specific security in a given trading session. |
80
+ | `search_securities(query: str)` | Searches for securities whose names or ticker symbols match the given query. |
81
+ | `get_trades_for_year(symbol: str, year: str)` | Returns all trade records for a specific security during a given year. |
82
+ | `get_historical_trades(symbol: str, start_date: str, end_date: str)` | Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy`, `mm/yyyy`, `yyyy` format). |
83
+
84
+ ---
85
+
86
+ ### Data Utilities
87
+
88
+ | Function | Description |
89
+ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
+ | `to_dataframe(data)` | Converts a list (or dictionary) of trade data into a Pandas DataFrame for easy analysis. Raises `TypeError` if the data is not properly formatted. |
91
+ | `save_to_csv(data, filename: str = "output.csv", path: str = None)` | Saves the given data to a CSV file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
92
+ | `save_to_excel(data, filename: str = "output.xlsx", path: str = None)` | Saves the given data to an Excel `.xlsx` file. By default, the file is saved to the current working directory. Returns `True` after saving successfully. |
93
+
94
+ ---
95
+
96
+ ## Caching System
97
+
98
+ FinanceGY includes a lightweight local caching system designed to speed up repeated requests and reduce unnecessary calls.
99
+
100
+ Whenever you call a data retrieval function (such as `get_securities()` or `get_recent_trade()`), FinanceGY automatically checks whether a cached response already exists for that specific query:
101
+
102
+ - If a valid cache file (less than 7 days old since sessions are held once per week) is found, the result is returned instantly from the cache.
103
+ - If the cache is missing, disabled, or older than one week, FinanceGY fetches fresh data from the GSE and updates the cache automatically.
104
+
105
+ All cache files are stored in a local `cache/` directory as small JSON files containing the retrieved data and a timestamp.
106
+
107
+ You can manually clear all cached data at any time:
108
+
109
+ ```python
110
+ import financegy
111
+
112
+ financegy.clear_cache()
113
+ ```
114
+
115
+ This will delete all cached files and force the next data request to fetch fresh data directly from the source.
116
+
117
+ If you prefer to bypass the cache for a specific call, simply pass `use_cache=False` to any function. For example:
118
+
119
+ ```python
120
+ # Force a fresh fetch from the GSE, ignoring cached data
121
+ recent_trade = financegy.get_recent_trade("DDL", use_cache=False)
122
+ ```
123
+
124
+ By default, caching is enabled for all supported functions unless explicitly turned off.
125
+
126
+ ---
127
+
128
+ ## License
129
+
130
+ This project is licensed under the **MIT License**
131
+
132
+ ---
133
+
134
+ ## Example Use Case
135
+
136
+ ```python
137
+ import financegy
138
+
139
+ ddl_recent = financegy.get_security_recent("DDL")
140
+ print(ddl_recent)
141
+ ```
@@ -8,7 +8,9 @@ financegy.egg-info/SOURCES.txt
8
8
  financegy.egg-info/dependency_links.txt
9
9
  financegy.egg-info/requires.txt
10
10
  financegy.egg-info/top_level.txt
11
+ financegy/cache/cache_manager.py
11
12
  financegy/core/parser.py
12
13
  financegy/core/request_handler.py
13
14
  financegy/modules/securities.py
15
+ financegy/utils/utils.py
14
16
  tests/test_securities.py
@@ -1,2 +1,4 @@
1
1
  requests
2
2
  beautifulsoup4
3
+ pandas
4
+ openpyxl
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "financegy"
7
- version = "0.1.0"
7
+ version = "1.5"
8
8
  description = "Unofficial Python library for accessing GSE (Guyana Stock Exchange) financial data"
9
9
  authors = [{ name = "Ezra Minty", email = "ezranminty@gmail.com" }]
10
- dependencies = ["requests", "beautifulsoup4"]
10
+ dependencies = ["requests", "beautifulsoup4", "pandas", "openpyxl"]
11
11
  readme = "README.md"
12
12
  license = { text = "MIT" }
13
13
 
@@ -0,0 +1,57 @@
1
+ from financegy import *
2
+ import pandas as pd
3
+
4
+ # def test_get_securities():
5
+ # result = get_securities()
6
+ # assert isinstance(result, list)
7
+
8
+ # def test_get_security_by_symbol():
9
+ # result = get_security_by_symbol(symbol="ddl")
10
+ # assert isinstance(result, (str, type(None)))
11
+
12
+ # def test_get_recent_trade():
13
+ # result = get_recent_trade(symbol="ddl")
14
+ # assert isinstance(result, (dict, type(None)))
15
+
16
+ # def test_get_security_recent_year():
17
+ # result = get_security_recent_year(symbol="RBL")
18
+ # assert isinstance(result, (list, type(None)))
19
+
20
+ # def test_get_session_trades():
21
+ # result = get_session_trades(session="1135")
22
+ # assert isinstance(result, (list, type(None)))
23
+
24
+ # def test_get_security_session_trade():
25
+ # result = get_security_session_trade(symbol="ddl", session="1136")
26
+ # assert isinstance(result, (dict, type(None)))
27
+
28
+ # def test_get_trades_for_year():
29
+ # result = get_trades_for_year(symbol="ddl", year="2020")
30
+ # assert isinstance(result, (list, type(None)))
31
+
32
+ # def test_get_historical_trades():
33
+ # result = get_historical_trades(symbol="ddl", start_date="06/2020", end_date="01/2022")
34
+ # assert isinstance(result, (list, type(None)))
35
+
36
+ # def test_search_securities():
37
+ # result = search_securities(query="ddl")
38
+ # assert isinstance(result, list)
39
+
40
+ # def test_to_dataframe():
41
+ # result = to_dataframe(get_securities())
42
+ # assert isinstance(result, pd.DataFrame)
43
+
44
+ # def test_save_to_csv():
45
+ # result = get_securities()
46
+ # save_to_csv(result)
47
+ # assert isinstance(result, list)
48
+
49
+ # def test_save_excel():
50
+ # result = get_securities()
51
+ # save_to_excel(result)
52
+ # assert isinstance(result, list)
53
+
54
+
55
+ # def test_clear_cache():
56
+ # result = clear_cache()
57
+ # assert isinstance(result, bool)
financegy-0.1.0/PKG-INFO DELETED
@@ -1,121 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: financegy
3
- Version: 0.1.0
4
- Summary: Unofficial Python library for accessing GSE (Guyana Stock Exchange) financial data
5
- Author-email: Ezra Minty <ezranminty@gmail.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/xbze3/financegy
8
- Project-URL: Issues, https://github.com/xbze3/financegy/issues
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: requests
12
- Requires-Dist: beautifulsoup4
13
- Dynamic: license-file
14
-
15
- # 🏦 FinanceGY
16
-
17
- **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
18
-
19
- ---
20
-
21
- ## Installation
22
-
23
- ```bash
24
- pip install financegy
25
- ```
26
-
27
- ---
28
-
29
- ## Quick Start
30
-
31
- ```python
32
- import financegy
33
-
34
- # Get a list of all traded securities
35
- securities = financegy.get_securities()
36
-
37
- # Get the name of a security by its ticker symbol
38
- security_name = financegy.get_security_by_symbol("DDL")
39
-
40
- # Get the most recent trade data for a security
41
- recent_trade = financegy.get_recent_trade("DDL")
42
-
43
- # Get all trade data for the most recent year
44
- recent_year = financegy.get_security_recent_year("DDL")
45
-
46
- # Get trade data for a specific trading session
47
- session_trades = financegy.get_session_trades("1136")
48
-
49
- # Get session trade data for a specific security
50
- security_session_trade = financegy.get_security_session_trade("DDL", "1136")
51
-
52
- # Search for securities by name or symbol
53
- search_results = financegy.search_securities("DDL")
54
-
55
- # Get all trades for a given year
56
- year_trades = financegy.get_trades_for_year("DDL", "2019")
57
-
58
- # Get historical trades within a date range (dd/mm/yyyy)
59
- historical_trades = financegy.get_historical_trades(
60
- symbol="DDL",
61
- start_date="01/06/2020",
62
- end_date="01/01/2022"
63
- )
64
- ```
65
-
66
- ---
67
-
68
- ## Function Overview
69
-
70
- #### `get_securities()`
71
-
72
- Returns a list of all currently traded securities on the Guyana Stock Exchange.
73
-
74
- #### `get_security_by_symbol(symbol: str)`
75
-
76
- Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`).
77
-
78
- #### `get_recent_trade(symbol: str)`
79
-
80
- Returns the most recent trade information for the given security.
81
-
82
- #### `get_security_recent_year(symbol: str)`
83
-
84
- Fetches all trade data for the most recent year of the selected security.
85
-
86
- #### `get_session_trades(session: str)`
87
-
88
- Retrieves trade data for _all_ securities during a specific trading session.
89
-
90
- #### `get_security_session_trade(symbol: str, session: str)`
91
-
92
- Retrieves trade data for a specific security in a given trading session.
93
-
94
- #### `search_securities(query: str)`
95
-
96
- Searches for securities whose names or ticker symbols match the given query.
97
-
98
- #### `get_trades_for_year(symbol: str, year: str)`
99
-
100
- Returns all trade records for a specific security during a given year.
101
-
102
- #### `get_historical_trades(symbol: str, start_date: str, end_date: str)`
103
-
104
- Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy` format).
105
-
106
- ---
107
-
108
- ## License
109
-
110
- This project is licensed under the **MIT License**
111
-
112
- ---
113
-
114
- ## Example Use Case
115
-
116
- ```python
117
- import financegy
118
-
119
- ddl_recent = financegy.get_security_recent("DDL")
120
- print(ddl_recent)
121
- ```
financegy-0.1.0/README.md DELETED
@@ -1,107 +0,0 @@
1
- # 🏦 FinanceGY
2
-
3
- **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
4
-
5
- ---
6
-
7
- ## Installation
8
-
9
- ```bash
10
- pip install financegy
11
- ```
12
-
13
- ---
14
-
15
- ## Quick Start
16
-
17
- ```python
18
- import financegy
19
-
20
- # Get a list of all traded securities
21
- securities = financegy.get_securities()
22
-
23
- # Get the name of a security by its ticker symbol
24
- security_name = financegy.get_security_by_symbol("DDL")
25
-
26
- # Get the most recent trade data for a security
27
- recent_trade = financegy.get_recent_trade("DDL")
28
-
29
- # Get all trade data for the most recent year
30
- recent_year = financegy.get_security_recent_year("DDL")
31
-
32
- # Get trade data for a specific trading session
33
- session_trades = financegy.get_session_trades("1136")
34
-
35
- # Get session trade data for a specific security
36
- security_session_trade = financegy.get_security_session_trade("DDL", "1136")
37
-
38
- # Search for securities by name or symbol
39
- search_results = financegy.search_securities("DDL")
40
-
41
- # Get all trades for a given year
42
- year_trades = financegy.get_trades_for_year("DDL", "2019")
43
-
44
- # Get historical trades within a date range (dd/mm/yyyy)
45
- historical_trades = financegy.get_historical_trades(
46
- symbol="DDL",
47
- start_date="01/06/2020",
48
- end_date="01/01/2022"
49
- )
50
- ```
51
-
52
- ---
53
-
54
- ## Function Overview
55
-
56
- #### `get_securities()`
57
-
58
- Returns a list of all currently traded securities on the Guyana Stock Exchange.
59
-
60
- #### `get_security_by_symbol(symbol: str)`
61
-
62
- Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`).
63
-
64
- #### `get_recent_trade(symbol: str)`
65
-
66
- Returns the most recent trade information for the given security.
67
-
68
- #### `get_security_recent_year(symbol: str)`
69
-
70
- Fetches all trade data for the most recent year of the selected security.
71
-
72
- #### `get_session_trades(session: str)`
73
-
74
- Retrieves trade data for _all_ securities during a specific trading session.
75
-
76
- #### `get_security_session_trade(symbol: str, session: str)`
77
-
78
- Retrieves trade data for a specific security in a given trading session.
79
-
80
- #### `search_securities(query: str)`
81
-
82
- Searches for securities whose names or ticker symbols match the given query.
83
-
84
- #### `get_trades_for_year(symbol: str, year: str)`
85
-
86
- Returns all trade records for a specific security during a given year.
87
-
88
- #### `get_historical_trades(symbol: str, start_date: str, end_date: str)`
89
-
90
- Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy` format).
91
-
92
- ---
93
-
94
- ## License
95
-
96
- This project is licensed under the **MIT License**
97
-
98
- ---
99
-
100
- ## Example Use Case
101
-
102
- ```python
103
- import financegy
104
-
105
- ddl_recent = financegy.get_security_recent("DDL")
106
- print(ddl_recent)
107
- ```
@@ -1,121 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: financegy
3
- Version: 0.1.0
4
- Summary: Unofficial Python library for accessing GSE (Guyana Stock Exchange) financial data
5
- Author-email: Ezra Minty <ezranminty@gmail.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/xbze3/financegy
8
- Project-URL: Issues, https://github.com/xbze3/financegy/issues
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: requests
12
- Requires-Dist: beautifulsoup4
13
- Dynamic: license-file
14
-
15
- # 🏦 FinanceGY
16
-
17
- **FinanceGY** is an unofficial Python library for accessing financial data from the **Guyana Stock Exchange (GSE)**. It provides a simple and consistent interface for retrieving information on traded securities, recent trade data, and session details, all programmatically.
18
-
19
- ---
20
-
21
- ## Installation
22
-
23
- ```bash
24
- pip install financegy
25
- ```
26
-
27
- ---
28
-
29
- ## Quick Start
30
-
31
- ```python
32
- import financegy
33
-
34
- # Get a list of all traded securities
35
- securities = financegy.get_securities()
36
-
37
- # Get the name of a security by its ticker symbol
38
- security_name = financegy.get_security_by_symbol("DDL")
39
-
40
- # Get the most recent trade data for a security
41
- recent_trade = financegy.get_recent_trade("DDL")
42
-
43
- # Get all trade data for the most recent year
44
- recent_year = financegy.get_security_recent_year("DDL")
45
-
46
- # Get trade data for a specific trading session
47
- session_trades = financegy.get_session_trades("1136")
48
-
49
- # Get session trade data for a specific security
50
- security_session_trade = financegy.get_security_session_trade("DDL", "1136")
51
-
52
- # Search for securities by name or symbol
53
- search_results = financegy.search_securities("DDL")
54
-
55
- # Get all trades for a given year
56
- year_trades = financegy.get_trades_for_year("DDL", "2019")
57
-
58
- # Get historical trades within a date range (dd/mm/yyyy)
59
- historical_trades = financegy.get_historical_trades(
60
- symbol="DDL",
61
- start_date="01/06/2020",
62
- end_date="01/01/2022"
63
- )
64
- ```
65
-
66
- ---
67
-
68
- ## Function Overview
69
-
70
- #### `get_securities()`
71
-
72
- Returns a list of all currently traded securities on the Guyana Stock Exchange.
73
-
74
- #### `get_security_by_symbol(symbol: str)`
75
-
76
- Retrieves the full name of a security using its ticker symbol (e.g., `"DDL"` → `"Demerara Distillers Limited"`).
77
-
78
- #### `get_recent_trade(symbol: str)`
79
-
80
- Returns the most recent trade information for the given security.
81
-
82
- #### `get_security_recent_year(symbol: str)`
83
-
84
- Fetches all trade data for the most recent year of the selected security.
85
-
86
- #### `get_session_trades(session: str)`
87
-
88
- Retrieves trade data for _all_ securities during a specific trading session.
89
-
90
- #### `get_security_session_trade(symbol: str, session: str)`
91
-
92
- Retrieves trade data for a specific security in a given trading session.
93
-
94
- #### `search_securities(query: str)`
95
-
96
- Searches for securities whose names or ticker symbols match the given query.
97
-
98
- #### `get_trades_for_year(symbol: str, year: str)`
99
-
100
- Returns all trade records for a specific security during a given year.
101
-
102
- #### `get_historical_trades(symbol: str, start_date: str, end_date: str)`
103
-
104
- Fetches historical trade data for a security within the specified date range (`dd/mm/yyyy` format).
105
-
106
- ---
107
-
108
- ## License
109
-
110
- This project is licensed under the **MIT License**
111
-
112
- ---
113
-
114
- ## Example Use Case
115
-
116
- ```python
117
- import financegy
118
-
119
- ddl_recent = financegy.get_security_recent("DDL")
120
- print(ddl_recent)
121
- ```
@@ -1,37 +0,0 @@
1
- from financegy import *
2
-
3
- def test_get_securities():
4
- result = get_securities()
5
- assert isinstance(result, list)
6
-
7
- def test_get_security_by_symbol():
8
- result = get_security_by_symbol(symbol="ddl")
9
- assert isinstance(result, (str, type(None)))
10
-
11
- def test_get_recent_trade():
12
- result = get_recent_trade(symbol="ddl")
13
- assert isinstance(result, (dict, type(None)))
14
-
15
- def test_get_security_recent_year():
16
- result = get_security_recent_year(symbol="ddl")
17
- assert isinstance(result, (list, type(None)))
18
-
19
- def test_get_session_trades():
20
- result = get_session_trades(session="1136")
21
- assert isinstance(result, (list, type(None)))
22
-
23
- def test_get_security_session_trade():
24
- result = get_security_session_trade(symbol="ddl", session="1136")
25
- assert isinstance(result, (dict, type(None)))
26
-
27
- def test_search_securities():
28
- result = search_securities(query="ddl")
29
- assert isinstance(result, list)
30
-
31
- def test_get_trades_for_year():
32
- result = get_trades_for_year(symbol="ddl", year="2019")
33
- assert isinstance(result, (list, type(None)))
34
-
35
- def test_get_historical_trades():
36
- result = get_historical_trades(symbol="ddl", start_date="01/06/2020", end_date="01/01/2022")
37
- assert isinstance(result, (list, type(None)))
File without changes
File without changes
File without changes