Skip to content

Commit c7d6ddd

Browse files
authored
Merge pull request #43 from EtWnn/develop
Release v0.1.3
2 parents 824daf4 + f81b859 commit c7d6ddd

File tree

13 files changed

+248
-45
lines changed

13 files changed

+248
-45
lines changed

BinanceWatch/BinanceManager.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ class BinanceManager:
2222

2323
def __init__(self, api_key: str, api_secret: str, account_name: str = 'default'):
2424
"""
25-
initialise the binance manager.
25+
Initialise the binance manager.
2626
2727
:param api_key: key for the Binance api
2828
:type api_key: str
2929
:param api_secret: secret for the Binance api
3030
:type api_secret: str
3131
:param account_name: if you have several accounts to monitor, you need to give them different names or the
32-
database will collide
32+
database will collide
3333
:type account_name: str
3434
"""
3535
self.account_name = account_name
@@ -231,7 +231,7 @@ def update_margin_asset_repay(self, asset: str, isolated_symbol=''):
231231
while True:
232232
client_params = {
233233
'asset': asset,
234-
'current':current,
234+
'current': current,
235235
'startTime': latest_time + 1000,
236236
'archived': archived,
237237
'isolatedSymbol': isolated_symbol,
@@ -611,7 +611,7 @@ def update_spot_dividends(self, day_jump: float = 90, limit: int = 500):
611611
)
612612
pbar.update()
613613
if len(dividends) < limit:
614-
start_time += delta_jump
614+
start_time += delta_jump + 1 # endTime is included in the previous return, so we have to add 1
615615
else: # limit was reached before the end of the time windows
616616
start_time = int(dividends[0]['divTime']) + 1
617617
if len(dividends):
@@ -658,7 +658,7 @@ def update_spot_withdraws(self, day_jump: float = 90):
658658
auto_commit=False
659659
)
660660
pbar.update()
661-
start_time += delta_jump
661+
start_time += delta_jump + 1 # endTime is included in the previous return, so we have to add 1
662662
if len(withdraws):
663663
self.db.commit()
664664
pbar.close()
@@ -700,7 +700,7 @@ def update_spot_deposits(self, day_jump: float = 90):
700700
amount=float(deposit['amount']),
701701
auto_commit=False)
702702
pbar.update()
703-
start_time += delta_jump
703+
start_time += delta_jump + 1 # endTime is included in the previous return, so we have to add 1
704704
if len(deposits):
705705
self.db.commit()
706706
pbar.close()
@@ -795,11 +795,13 @@ def _call_binance_client(self, method_name: str, params: Optional[Dict] = None,
795795
return getattr(self.client, method_name)(**params)
796796
except BinanceAPIException as err:
797797
if err.code == -1003: # API rate Limits
798-
wait_time = float(err.response.headers['Retry-After'])
798+
# wait_time = float(err.response.headers['Retry-After']) it seems to be always 0, so unusable
799+
wait_time = 1 + 60 - datetime.datetime.now().timestamp() % 60 # number of seconds until next minute
799800
if err.response.status_code == 418: # ban
800801
self.logger.error(f"API calls resulted in a ban, retry in {wait_time} seconds")
801802
raise err
802-
self.logger.info(f"API calls resulted in a breach of rate limits, will retry after {wait_time} seconds")
803-
time.sleep(wait_time + 1)
803+
self.logger.info(f"API calls resulted in a breach of rate limits,"
804+
f" will retry after {wait_time:.2f} seconds")
805+
time.sleep(wait_time)
804806
return self._call_binance_client(method_name, params, retry_count + 1)
805807
raise err

BinanceWatch/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.1.2"
1+
__version__ = "0.1.3"
22
__author__ = 'EtWnn'

BinanceWatch/storage/BinanceDataBase.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ class BinanceDataBase(DataBase):
1212
"""
1313

1414
def __init__(self, name: str = 'binance_db'):
15+
"""
16+
Initialise a binance database instance
17+
18+
:param name: name of the database
19+
:type name: str
20+
"""
1521
super().__init__(name)
1622

1723
def add_universal_transfer(self, transfer_id: int, transfer_type: str, transfer_time: int, asset: str,

BinanceWatch/storage/DataBase.py

Lines changed: 142 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
class SQLConditionEnum(Enum):
1111
"""
12+
Enumeration for SQL comparison operator
13+
1214
https://www.techonthenet.com/sqlite/comparison_operators.php
1315
"""
1416
equal = '='
@@ -25,17 +27,46 @@ class DataBase:
2527
"""
2628

2729
def __init__(self, name: str):
30+
"""
31+
Initialise a DataBase instance
32+
33+
:param name: name of the database
34+
:type name: str
35+
"""
2836
self.name = name
2937
self.logger = LoggerGenerator.get_logger(self.name)
3038
self.save_path = get_data_path() / f"{name}.db"
39+
self.db_conn = None
40+
self.db_cursor = None
41+
self.connect()
42+
43+
def connect(self):
44+
"""
45+
Connect to the sqlite3 database
46+
47+
:return: None
48+
:rtype: None
49+
"""
3150
self.db_conn = sqlite3.connect(self.save_path)
3251
self.db_cursor = self.db_conn.cursor()
3352

34-
def _fetch_rows(self, execution_cmd: str):
53+
def close(self):
54+
"""
55+
Close the connection with the sqlite3 database
56+
57+
:return: None
58+
:rtype: None
59+
"""
60+
self.db_conn.close()
61+
62+
def _fetch_rows(self, execution_cmd: str) -> List[Tuple]:
3563
"""
36-
execute a command to fetch some rows and return them
64+
Execute a command to fetch some rows and return them
65+
3766
:param execution_cmd: the command to execute
38-
:return:
67+
:type execution_cmd: str
68+
:return: list of the table's rows selected by the command
69+
:rtype: List[Tuple]
3970
"""
4071
rows = []
4172
try:
@@ -51,10 +82,14 @@ def _fetch_rows(self, execution_cmd: str):
5182

5283
def get_row_by_key(self, table: Table, key_value) -> Optional[Tuple]:
5384
"""
54-
get the row identified by a primary key value from a table
55-
:param table: table to fetch the row from
56-
:param key_value: key value of the row
57-
:return: None or the row of value
85+
Get the row identified by a primary key value from a table
86+
87+
:param table: table to fetch the key from
88+
:type table: Table
89+
:param key_value: value of the primary key
90+
:type key_value: Any
91+
:return: the raw row of of the table
92+
:rtype: Optional[Tuple]
5893
"""
5994
if table.primary_key is None:
6095
raise ValueError(f"table {table.name} has no explicit primary key")
@@ -64,12 +99,24 @@ def get_row_by_key(self, table: Table, key_value) -> Optional[Tuple]:
6499
return rows[0]
65100

66101
def get_conditions_rows(self, table: Table,
67-
selection: Optional[Union[str, List[str]]] = None,
102+
selection: Union[str, List[str]] = '*',
68103
conditions_list: Optional[List[Tuple[str, SQLConditionEnum, Any]]] = None,
69-
order_list: Optional[List[str]] = None) -> List:
70-
if selection is None:
71-
selection = '*'
72-
elif isinstance(selection, List):
104+
order_list: Optional[List[str]] = None) -> List[Tuple]:
105+
"""
106+
Select rows with optional conditions and optional order
107+
108+
:param table: table to select the rows from
109+
:type table: Table
110+
:param selection: list of column or SQL type selection
111+
:type selection: Union[str, List[str]]
112+
:param conditions_list: list of conditions to select the row
113+
:type conditions_list: Optional[List[Tuple[str, SQLConditionEnum, Any]]]
114+
:param order_list: List of SQL type order by
115+
:type order_list: Optional[List[str]]
116+
:return: the selected rows
117+
:rtype: List[Tuple]
118+
"""
119+
if isinstance(selection, List):
73120
selection = ','.join(selection)
74121
if conditions_list is None:
75122
conditions_list = []
@@ -80,10 +127,33 @@ def get_conditions_rows(self, table: Table,
80127
execution_cmd = self._add_order(execution_cmd, order_list=order_list)
81128
return self._fetch_rows(execution_cmd)
82129

83-
def get_all_rows(self, table: Table) -> List:
130+
def get_all_rows(self, table: Table) -> List[Tuple]:
131+
"""
132+
Get all the rows of a table
133+
134+
:param table: table to get the rows from
135+
:type table: Table
136+
:return: all the rows of the table
137+
:rtype: List[Tuple]
138+
"""
84139
return self.get_conditions_rows(table)
85140

86141
def add_row(self, table: Table, row: Tuple, auto_commit: bool = True, update_if_exists: bool = False):
142+
"""
143+
Add a row to a table
144+
145+
:param table: table to add a row to
146+
:type table: Table
147+
:param row: values to add to the database
148+
:type row: Tuple
149+
:param auto_commit: if the database state should be saved after the changes
150+
:type auto_commit: bool
151+
:param update_if_exists: if an integrity error is raised and this parameter is true,
152+
will update the existing row
153+
:type update_if_exists: bool
154+
:return: None
155+
:rtype: None
156+
"""
87157
row_s = ", ".join(f"'{v}'" for v in row)
88158
row_s = f'({row_s})'
89159
execution_order = f"INSERT INTO {table.name} VALUES {row_s}"
@@ -100,15 +170,45 @@ def add_row(self, table: Table, row: Tuple, auto_commit: bool = True, update_if_
100170
if update_if_exists:
101171
self.update_row(table, row, auto_commit)
102172
else:
173+
existing_row = self.get_row_by_key(table, row[0])
174+
msg = f"tried to insert {row} in the table {table.name} but the row is occupied: {existing_row}"
175+
self.logger.error(msg)
103176
raise err
104177

105178
def add_rows(self, table: Table, rows: List[Tuple], auto_commit: bool = True, update_if_exists: bool = False):
179+
"""
180+
Add several rows to a table
181+
182+
:param table: table to add a row to
183+
:type table: Table
184+
:param rows: list of values to add to the database
185+
:type rows: List[Tuple]
186+
:param auto_commit: if the database state should be saved after the changes
187+
:type auto_commit: bool
188+
:param update_if_exists: if an integrity error is raised and this parameter is true,
189+
will update the existing row
190+
:type update_if_exists: bool
191+
:return: None
192+
:rtype: None
193+
"""
106194
for row in rows:
107195
self.add_row(table, row, auto_commit=False, update_if_exists=update_if_exists)
108196
if auto_commit:
109197
self.commit()
110198

111199
def update_row(self, table: Table, row: Tuple, auto_commit=True):
200+
"""
201+
Update the value of a row in a table
202+
203+
:param table: table to get updated
204+
:type table: Table
205+
:param row: values to update
206+
:type row: Tuple
207+
:param auto_commit: if the database state should be saved after the changes
208+
:type auto_commit: bool
209+
:return: None
210+
:rtype: None
211+
"""
112212
row_s = ", ".join(f"{n} = {v}" for n, v in zip(table.columns_names, row))
113213
execution_order = f"UPDATE {table.name} SET {row_s} WHERE {table.primary_key} = {row[0]}"
114214
self.db_cursor.execute(execution_order)
@@ -117,20 +217,23 @@ def update_row(self, table: Table, row: Tuple, auto_commit=True):
117217

118218
def create_table(self, table: Table):
119219
"""
120-
create a table in the database
220+
Create a table in the database
221+
121222
:param table: Table instance with the config of the table to create
122-
:return:
223+
:type table: Table
224+
:return: None
225+
:rtype: None
123226
"""
124227
create_cmd = self.get_create_cmd(table)
125228
self.db_cursor.execute(create_cmd)
126229
self.db_conn.commit()
127230

128231
def drop_table(self, table: Union[Table, str]):
129232
"""
130-
delete a table from the database
233+
Delete a table from the database
131234
132235
:param table: table or table name to drop
133-
:type table: str or Table instance
236+
:type table: Union[Table, str]
134237
:return: None
135238
:rtype: None
136239
"""
@@ -142,7 +245,7 @@ def drop_table(self, table: Union[Table, str]):
142245

143246
def drop_all_tables(self):
144247
"""
145-
drop all the tables existing in the database
248+
Drop all the tables existing in the database
146249
147250
:return: None
148251
:rtype: None
@@ -154,7 +257,7 @@ def drop_all_tables(self):
154257

155258
def get_all_tables(self) -> List[Tuple]:
156259
"""
157-
return all the tables existing in the database
260+
Return all the tables existing in the database
158261
159262
:return: tables descriptions
160263
:rtype: List[Tuple]
@@ -164,19 +267,24 @@ def get_all_tables(self) -> List[Tuple]:
164267

165268
def commit(self):
166269
"""
167-
submit and save the database state
168-
:return:
270+
Submit and save the database state
271+
272+
:return: None
273+
:rtype: None
169274
"""
170275
self.db_conn.commit()
171276

172277
@staticmethod
173278
def _add_conditions(execution_cmd: str, conditions_list: List[Tuple[str, SQLConditionEnum, Any]]):
174279
"""
175-
add a list of condition to an SQL command
280+
Add a list of condition to an SQL command
281+
176282
:param execution_cmd: SQL command without 'WHERE' statement
177283
:type execution_cmd: str
178-
:param conditions_list:
179-
:return:
284+
:param conditions_list: List of condition to add to the SQL command
285+
:type conditions_list: List[Tuple[str, SQLConditionEnum, Any]]
286+
:return: the augmented command
287+
:rtype: str
180288
"""
181289
if len(conditions_list):
182290
add_cmd = ' WHERE'
@@ -189,14 +297,14 @@ def _add_conditions(execution_cmd: str, conditions_list: List[Tuple[str, SQLCond
189297
@staticmethod
190298
def _add_order(execution_cmd: str, order_list: List[str]):
191299
"""
192-
add an order specification to an SQL command
300+
Add an order specification to an SQL command
193301
194302
:param execution_cmd: SQL command without 'ORDER BY' statement
195303
:type execution_cmd: str
196-
:param order_list:
197-
:type order_list:
198-
:return:
199-
:rtype:
304+
:param order_list: SQL order
305+
:type order_list: List[str]
306+
:return: the augmented command
307+
:rtype: str
200308
"""
201309
if len(order_list):
202310
add_cmd = ' ORDER BY'
@@ -207,11 +315,14 @@ def _add_order(execution_cmd: str, order_list: List[str]):
207315
return execution_cmd
208316

209317
@staticmethod
210-
def get_create_cmd(table: Table):
318+
def get_create_cmd(table: Table) -> str:
211319
"""
212-
return the command in string format to create a table in the database
320+
Return the command in string format to create a table in the database
321+
213322
:param table: Table instance with the config if the table to create
323+
:type table: Table
214324
:return: execution command for the table creation
325+
:rtype: str
215326
"""
216327
cmd = ""
217328
if table.primary_key is not None:

0 commit comments

Comments
 (0)