diff --git a/v2realbot/common/db.py b/v2realbot/common/db.py index 91ffa32..1805f74 100644 --- a/v2realbot/common/db.py +++ b/v2realbot/common/db.py @@ -2,6 +2,7 @@ from v2realbot.config import DATA_DIR import sqlite3 import queue import threading +from datetime import time sqlite_db_file = DATA_DIR + "/v2trading.db" # Define the connection pool @@ -26,6 +27,29 @@ class ConnectionPool: connection = sqlite3.connect(sqlite_db_file, check_same_thread=False) return connection + +def execute_with_retry(cursor: sqlite3.Cursor, statement: str, retry_interval: int = 1) -> sqlite3.Cursor: + """get connection from pool and execute SQL statement with retry logic if required. + + Args: + cursor: The database cursor to use. + statement: The SQL statement to execute. + retry_interval: The number of seconds to wait before retrying the statement. + + Returns: + The database cursor. + """ + while True: + try: + return cursor.execute(statement) + except sqlite3.OperationalError as e: + if str(e) == "database is locked": + time.sleep(retry_interval) + continue + else: + raise e + + #for pool of connections if necessary pool = ConnectionPool(10) #for one shared connection (used for writes only in WAL mode) diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index a8ca3a2..9186c64 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -24,7 +24,8 @@ import pandas as pd from traceback import format_exc from datetime import timedelta, time from threading import Lock -from v2realbot.common.db import pool +from v2realbot.common.db import pool, execute_with_retry +from sqlite3 import OperationalError #from pyinstrument import Profiler #adding lock to ensure thread safety of TinyDB (in future will be migrated to proper db) lock = Lock() @@ -624,10 +625,10 @@ def populate_metrics_output_directory(strat: StrategyInstance, inter_batch_param res["profit"]["short_cnt"] = short_cnt res["profit"]["long_profit"] = round(long_profit,2) res["profit"]["short_profit"] = round(short_profit,2) - res["profit"]["long_losses"] = round(long_losses,2) - res["profit"]["short_losses"] = round(short_losses,2) res["profit"]["long_wins"] = round(long_wins,2) + res["profit"]["long_losses"] = round(long_losses,2) res["profit"]["short_wins"] = round(short_wins,2) + res["profit"]["short_losses"] = round(short_losses,2) res["profit"]["max_profit"] = round(max_profit,2) res["profit"]["max_profit_time"] = str(max_profit_time) #vlozeni celeho listu @@ -814,7 +815,8 @@ def insert_archive_header(archeader: RunArchive): statement = f"INSERT INTO runner_header (runner_id, batch_id, data) VALUES ('{str(archeader.id)}','{str(archeader.batch_id)}','{json_string}')" else: statement = f"INSERT INTO runner_header (runner_id, data) VALUES ('{str(archeader.id)}','{json_string}')" - res = c.execute(statement) + + res = execute_with_retry(c,statement) conn.commit() finally: pool.release_connection(conn) @@ -832,7 +834,7 @@ def edit_archived_runners(runner_id: UUID, archChange: RunArchiveChange): c = conn.cursor() json_string = json.dumps(archOriginal, default=json_serial) statement = f"UPDATE runner_header SET data = '{json_string}' WHERE runner_id='{str(runner_id)}'" - res = c.execute(statement) + res = execute_with_retry(c,statement) #print(res) conn.commit() finally: @@ -877,7 +879,8 @@ def delete_archive_header_byID(id: UUID): conn = pool.get_connection() try: c = conn.cursor() - res = c.execute(f"DELETE from runner_header WHERE runner_id='{str(id)}';") + statement=f"DELETE from runner_header WHERE runner_id='{str(id)}';" + res = execute_with_retry(c,statement) conn.commit() print("deleted", res.rowcount) finally: @@ -892,7 +895,8 @@ def delete_archive_detail_byID(id: UUID): conn = pool.get_connection() try: c = conn.cursor() - res = c.execute(f"DELETE from runner_detail WHERE runner_id='{str(id)}';") + statement=f"DELETE from runner_detail WHERE runner_id='{str(id)}';" + res = execute_with_retry(c,statement) conn.commit() print("deleted", res.rowcount) finally: @@ -939,7 +943,8 @@ def update_archive_detail(id: UUID, archdetail: RunArchiveDetail): try: c = conn.cursor() json_string = json.dumps(archdetail, default=json_serial) - res = c.execute(f"UPDATE runner_detail SET data = '{json_string}' WHERE runner_id='{str(id)}'") + statement = f"UPDATE runner_detail SET data = '{json_string}' WHERE runner_id='{str(id)}'" + res = execute_with_retry(c,statement) conn.commit() finally: pool.release_connection(conn) @@ -950,7 +955,8 @@ def insert_archive_detail(archdetail: RunArchiveDetail): try: c = conn.cursor() json_string = json.dumps(archdetail, default=json_serial) - res = c.execute("INSERT INTO runner_detail VALUES (?,?)",[str(archdetail.id), json_string]) + statement = f"INSERT INTO runner_detail VALUES ('{str(archdetail.id)}','{json_string}')" + res = execute_with_retry(c,statement) conn.commit() finally: pool.release_connection(conn) diff --git a/v2realbot/loader/aggregator.py b/v2realbot/loader/aggregator.py index 3446294..f466f78 100644 --- a/v2realbot/loader/aggregator.py +++ b/v2realbot/loader/aggregator.py @@ -84,10 +84,10 @@ class TradeAggregator: ## 22.3. - dal jsem pryc i contingency trades [' ', '7', 'V'] - nasel jsem obchod o 30c mimo ## dán pryč P - prior reference time + 25centu mimo, {'t': '2023-04-12T19:45:08.63257344Z', 'x': 'D', 'p': 28.68, 's': 1000, 'c': [' ', 'P'], 'i': 71693108525109, 'z': 'A'}, ## Q - jsou v pohode, oteviraci trady, ale O jsou jejich duplikaty - ## přidán W - average price trade, U - Extended hours - sold out of sequence + ## přidán W - average price trade, U - Extended hours - sold out of sequence, Z - Sold(Out of sequence) try: for i in data['c']: - if i in ('C','O','4','B','7','V','P','W','U'): return [] + if i in ('C','O','4','B','7','V','P','W','U','Z'): return [] except KeyError: pass diff --git a/v2realbot/static/js/utils.js b/v2realbot/static/js/utils.js index 0d48ece..24d3783 100644 --- a/v2realbot/static/js/utils.js +++ b/v2realbot/static/js/utils.js @@ -3,8 +3,8 @@ API_KEY = localStorage.getItem("api-key") var chart = null // var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"] // var reset_colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"] -var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#7B0E60","#9B2888","#BD38A0","#A30F68","#6E0B50","#CA2183","#E6319B","#A04C54","#643848","#CA7474","#E68D8D","#4F9C34","#3B7128","#73DF4D","#95EF65","#A857A4","#824690","#D087CC","#E2A1DF","#79711B","#635D17","#99912B","#B1A73D","#3779C9","#2B68B3","#5599ED","#77A9F7","#003A4C","#002F3B","#004C67","#00687D","#A1C6B5","#8CC6A5","#C9E6D5","#E4F6EA","#D2144A","#A60F3B","#FA2463","#FF3775"]; -var reset_colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#7B0E60","#9B2888","#BD38A0","#A30F68","#6E0B50","#CA2183","#E6319B","#A04C54","#643848","#CA7474","#E68D8D","#4F9C34","#3B7128","#73DF4D","#95EF65","#A857A4","#824690","#D087CC","#E2A1DF","#79711B","#635D17","#99912B","#B1A73D","#3779C9","#2B68B3","#5599ED","#77A9F7","#003A4C","#002F3B","#004C67","#00687D","#A1C6B5","#8CC6A5","#C9E6D5","#E4F6EA","#D2144A","#A60F3B","#FA2463","#FF3775"]; +var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#7B0E60","#9B2888","#BD38A0","#A30F68","#6E0B50","#CA2183","#E6319B","#A04C54","#643848","#CA7474","#E68D8D","#4F9C34","#3B7128","#73DF4D","#95EF65","#A857A4","#824690","#D087CC","#E2A1DF","#79711B","#635D17","#99912B","#B1A73D","#3779C9","#2B68B3","#5599ED","#77A9F7","#004C67","#00687D","#A1C6B5","#8CC6A5","#C9E6D5","#E4F6EA","#D2144A","#A60F3B","#FA2463","#FF3775"]; +var reset_colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#7B0E60","#9B2888","#BD38A0","#A30F68","#6E0B50","#CA2183","#E6319B","#A04C54","#643848","#CA7474","#E68D8D","#4F9C34","#3B7128","#73DF4D","#95EF65","#A857A4","#824690","#D087CC","#E2A1DF","#79711B","#635D17","#99912B","#B1A73D","#3779C9","#2B68B3","#5599ED","#77A9F7","#004C67","#00687D","#A1C6B5","#8CC6A5","#C9E6D5","#E4F6EA","#D2144A","#A60F3B","#FA2463","#FF3775"]; var indList = []