diff --git a/testy/pickle.py b/testy/pickle.py
new file mode 100644
index 0000000..aaa0d38
--- /dev/null
+++ b/testy/pickle.py
@@ -0,0 +1,39 @@
+import pickle
+import os
+from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN, MEDIA_DIRECTORY, RUNNER_DETAIL_DIRECTORY
+
+# #class to persist
+# class Store:
+# stratins : List[StrategyInstance] = []
+# runners: List[Runner] = []
+# def __init__(self) -> None:
+# self.db_file = DATA_DIR + "/strategyinstances.cache"
+# if os.path.exists(self.db_file):
+# with open (self.db_file, 'rb') as fp:
+# self.stratins = pickle.load(fp)
+
+# def save(self):
+# with open(self.db_file, 'wb') as fp:
+# pickle.dump(self.stratins, fp)
+
+
+#db = Store()
+
+def try_reading_after_skipping_bytes(file_path, skip_bytes, chunk_size=1024):
+ with open(file_path, 'rb') as file:
+ file.seek(skip_bytes) # Skip initial bytes
+ while True:
+ try:
+ data = pickle.load(file)
+ print("Recovered data:", data)
+ break # Exit loop if successful
+ except EOFError:
+ print("Reached end of file without recovering data.")
+ break
+ except pickle.UnpicklingError:
+ # Move ahead in file by chunk_size bytes and try again
+ file.seek(file.tell() + chunk_size, os.SEEK_SET)
+
+
+file_path = DATA_DIR + "/strategyinstances.cache"
+try_reading_after_skipping_bytes(file_path,1)
\ No newline at end of file
diff --git a/v2realbot/ENTRY_ClassicSL_v01.py b/v2realbot/ENTRY_ClassicSL_v01.py
index 17fbd42..ad64cf6 100644
--- a/v2realbot/ENTRY_ClassicSL_v01.py
+++ b/v2realbot/ENTRY_ClassicSL_v01.py
@@ -20,6 +20,9 @@ from alpaca.trading.requests import GetCalendarRequest
from alpaca.trading.client import TradingClient
from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR, OFFLINE_MODE
from alpaca.trading.models import Calendar
+from v2realbot.indicators.oscillators import rsi
+from v2realbot.indicators.moving_averages import sma
+import numpy as np
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
""""
@@ -161,7 +164,7 @@ def init(state: StrategyState):
#time_to = time_to.date()
today = time_to.date()
- several_days_ago = today - timedelta(days=40)
+ several_days_ago = today - timedelta(days=60)
#printanyway(f"{today=}",f"{several_days_ago=}")
clientTrading = TradingClient(ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, raw_data=False)
#get all market days from here to 40days ago
@@ -190,6 +193,30 @@ def init(state: StrategyState):
#printanyway(history_datetime_from, history_datetime_to)
#az do predchziho market dne dne
state.dailyBars = get_historical_bars(state.symbol, history_datetime_from, history_datetime_to, TimeFrame.Day)
+
+ #NOTE zatim pridano takto do baru dalsi indikatory
+ #BUDE PREDELANO - v rámci custom rozliseni a static indikátoru
+
+ #RSI vraci pouze pro vsechny + prepend with zeros nepocita prvnich N (dle rsi length)
+ rsi_calculated = rsi(state.dailyBars["vwap"], 14).tolist()
+ num_zeros_to_prepend = len(state.dailyBars["vwap"]) - len(rsi_calculated)
+ state.dailyBars["rsi"] = [0]*num_zeros_to_prepend + rsi_calculated
+
+ #VOLUME
+ volume_sma = sma(state.dailyBars["volume"], 10) #vraci celkovy pocet - 10
+ items_to_prepend = len(state.dailyBars["volume"]) - len(volume_sma)
+
+ volume_sma = np.hstack((np.full(items_to_prepend, np.nan), volume_sma))
+
+ #normalized divergence currvol-smavolume/currvol+smavolume
+ volume_data = np.array(state.dailyBars["volume"])
+ normalized_divergence = (volume_data - volume_sma) / (volume_data + volume_sma)
+ # Replace NaN values with 0 or some other placeholder if needed
+ normalized_divergence = np.nan_to_num(normalized_divergence)
+ volume_sma = np.nan_to_num(volume_sma)
+ state.dailyBars["volume_sma_divergence"] = normalized_divergence.tolist()
+ state.dailyBars["volume_sma"] = volume_sma.tolist()
+
#printanyway("daily bars FILLED", state.dailyBars)
#zatim ukladame do extData - pro instant indicatory a gui
state.extData["dailyBars"] = state.dailyBars
diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py
index cef6965..bf5aa23 100644
--- a/v2realbot/controller/services.py
+++ b/v2realbot/controller/services.py
@@ -1551,7 +1551,7 @@ def preview_indicator_byTOML(id: UUID, indicator: InstantIndicator, save: bool =
local_dict_inds = {key: state.indicators[key] for key in state.indicators.keys() if key != "time"}
local_dict_bars = {key: state.bars[key] for key in state.bars.keys() if key != "time"}
state.ind_mapping = {**local_dict_inds, **local_dict_bars, **local_dict_cbar_inds}
- print("IND MAPPING DONE:", state.ind_mapping)
+ #print("IND MAPPING DONE:", state.ind_mapping)
##intialize dynamic indicators
initialize_dynamic_indicators(state)
diff --git a/v2realbot/static/index.html b/v2realbot/static/index.html
index 581cde7..9ea038a 100644
--- a/v2realbot/static/index.html
+++ b/v2realbot/static/index.html
@@ -696,8 +696,8 @@
-
-
+
+
diff --git a/v2realbot/static/js/libs/dataTables.bootstrap5.min.css b/v2realbot/static/js/libs/dataTables.bootstrap5.min.css
index 3df6787..b4c4cdd 100644
--- a/v2realbot/static/js/libs/dataTables.bootstrap5.min.css
+++ b/v2realbot/static/js/libs/dataTables.bootstrap5.min.css
@@ -2,4 +2,4 @@
*
* ©2020 SpryMedia Ltd, all rights reserved.
* License: MIT datatables.net/license/mit
- */table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important;border-spacing:0}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.table-striped>tbody>tr:nth-of-type(2n+1)>*{box-shadow:none}table.dataTable>tbody>tr{background-color:transparent}table.dataTable>tbody>tr.selected>*{box-shadow:inset 0 0 0 9999px rgb(13, 110, 253);box-shadow:inset 0 0 0 9999px rgb(var(--dt-row-selected));color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable>tbody>tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable.table-striped>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.05)}table.dataTable.table-striped>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.95);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95)}table.dataTable.table-hover>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.075)}table.dataTable.table-hover>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.975);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975)}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:auto;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:.85em}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dt-row{position:relative}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:before,div.dataTables_scrollBody>table>thead .sorting_asc:before,div.dataTables_scrollBody>table>thead .sorting_desc:before,div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody tr:first-child th,div.dataTables_scrollBody>table>tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}div.dataTables_wrapper div.dataTables_paginate ul.pagination{justify-content:center !important}}table.dataTable.table-sm>thead>tr>th:not(.sorting_disabled){padding-right:20px}table.table-bordered.dataTable{border-right-width:0}table.table-bordered.dataTable thead tr:first-child th,table.table-bordered.dataTable thead tr:first-child td{border-top-width:1px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:first-child,table.table-bordered.dataTable th:first-child,table.table-bordered.dataTable td:first-child,table.table-bordered.dataTable td:first-child{border-left-width:1px}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:1px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-bottom-width:1px}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:last-child{padding-right:0}
+ */table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important;border-spacing:0}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}/*table.dataTable.table-striped>tbody>tr:nth-of-type(2n+1)>*{box-shadow:none}*/table.dataTable>tbody>tr{background-color:transparent}table.dataTable>tbody>tr.selected>*{box-shadow:inset 0 0 0 9999px rgb(13, 110, 253);box-shadow:inset 0 0 0 9999px rgb(var(--dt-row-selected));color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable>tbody>tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable.table-striped>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.05)}table.dataTable.table-striped>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.95);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95)}table.dataTable.table-hover>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.075)}table.dataTable.table-hover>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.975);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975)}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:auto;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:.85em}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dt-row{position:relative}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:before,div.dataTables_scrollBody>table>thead .sorting_asc:before,div.dataTables_scrollBody>table>thead .sorting_desc:before,div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody tr:first-child th,div.dataTables_scrollBody>table>tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}div.dataTables_wrapper div.dataTables_paginate ul.pagination{justify-content:center !important}}table.dataTable.table-sm>thead>tr>th:not(.sorting_disabled){padding-right:20px}table.table-bordered.dataTable{border-right-width:0}table.table-bordered.dataTable thead tr:first-child th,table.table-bordered.dataTable thead tr:first-child td{border-top-width:1px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:first-child,table.table-bordered.dataTable th:first-child,table.table-bordered.dataTable td:first-child,table.table-bordered.dataTable td:first-child{border-left-width:1px}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:1px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-bottom-width:1px}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:last-child{padding-right:0}
diff --git a/v2realbot/static/js/mytables.js b/v2realbot/static/js/mytables.js
index f106f8e..040e9cb 100644
--- a/v2realbot/static/js/mytables.js
+++ b/v2realbot/static/js/mytables.js
@@ -636,7 +636,7 @@ $(document).ready(function () {
$('#bt_to').val(localStorage.getItem("bt_to"));
//console.log(localStorage.getItem("bt_to"))
$('#test_batch_id').val(localStorage.getItem("test_batch_id"));
- $('#mode').val(localStorage.getItem("mode"));
+ $('#runmode').val(localStorage.getItem("runmode"));
$('#account').val(localStorage.getItem("account"));
$('#debug').val(localStorage.getItem("debug"));
$('#ilog_save').val(localStorage.getItem("ilog_save"));
@@ -965,7 +965,9 @@ $("#runModal").on('submit','#runForm', function(event){
localStorage.setItem("bt_from", $('#bt_from').val());
localStorage.setItem("bt_to", $('#bt_to').val());
localStorage.setItem("test_batch_id", $('#test_batch_id').val());
- localStorage.setItem("mode", $('#mode').val());
+ localStorage.setItem("runmode", $('#runmode').val());
+ console.log("mode set to", $('#runmode').val())
+ console.log("mode loaded value", localStorage.getItem("runmode"))
localStorage.setItem("account", $('#account').val());
localStorage.setItem("debug", $('#debug').val());
localStorage.setItem("ilog_save", $('#ilog_save').val());
diff --git a/v2realbot/static/main.css b/v2realbot/static/main.css
index 54e2f20..7f659fb 100644
--- a/v2realbot/static/main.css
+++ b/v2realbot/static/main.css
@@ -194,15 +194,16 @@ strong {
[data-bs-theme=dark] {
--bs-font-sans-serif: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-body-line-height: 1.3;
- --bs-body-font-size: 1.0rem;
+ --bs-body-font-size: 1.125rem;
--bs-body-font-weight: 300;
color-scheme: dark;
- --bs-body-color: #787b86;
+ --bs-body-color: #a1a1a1;
+ /* --bs-body-color: #787b86; */
--bs-body-color-rgb: 173,181,189;
/* --bs-body-bg: #2a2e39; */
--bs-body-bg: #121722;
--bs-body-bg-rgb: 33,37,41;
- --bs-emphasis-color: #adb5bd;
+ --bs-emphasis-color: #c8c8c8;
--bs-emphasis-color-rgb: 255,255,255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173,181,189;
@@ -337,7 +338,7 @@ table.dataTable thead>tr>th.sorting_asc:before, table.dataTable thead>tr>th.sort
/* #128faf; */
.btn-outline-success {
- --bs-btn-color: #75a9ac;
+ --bs-btn-color: #94b1b3;
--bs-btn-border-color: #8b8b8b;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #3996a4;
diff --git a/v2realbot/strategyblocks/indicators/custom/classes/DayTime.py b/v2realbot/strategyblocks/indicators/custom/classes/DayTime.py
new file mode 100644
index 0000000..ba65ee1
--- /dev/null
+++ b/v2realbot/strategyblocks/indicators/custom/classes/DayTime.py
@@ -0,0 +1,29 @@
+from v2realbot.strategyblocks.indicators.custom.classes.indicatorbase import IndicatorBase
+from datetime import datetime, time
+from v2realbot.utils.utils import zoneNY
+
+class DayTime(IndicatorBase):
+ def __init__(self, state):
+ super().__init__(state)
+ #TODO toto v initu dynamicky
+ # Convert market open/close times to seconds since epoch
+ self.market_open_time = self._time_to_seconds_since_epoch(time(9, 30), state)
+ self.market_close_time = self._time_to_seconds_since_epoch(time(16, 0), state)
+ # Total market duration in seconds
+ self.total_market_duration = self.market_close_time - self.market_open_time
+
+ def _time_to_seconds_since_epoch(self, market_time, state):
+ # Convert a time object to seconds since epoch for a typical day (e.g., today)
+ today = datetime.fromtimestamp(state.time).astimezone(zoneNY).date()
+ market_datetime = zoneNY.localize(datetime.combine(today, market_time))
+ return market_datetime.timestamp()
+
+ def next(self, time):
+ current_timestamp = time[-1]
+ # Check if the current time is within market hours
+ if self.market_open_time <= current_timestamp <= self.market_close_time:
+ time_since_open = current_timestamp - self.market_open_time
+ normalized_time = time_since_open / self.total_market_duration
+ return normalized_time
+ else:
+ return 0
\ No newline at end of file
diff --git a/v2realbot/strategyblocks/indicators/custom/classes/WeekDay.py b/v2realbot/strategyblocks/indicators/custom/classes/WeekDay.py
new file mode 100644
index 0000000..dd975d4
--- /dev/null
+++ b/v2realbot/strategyblocks/indicators/custom/classes/WeekDay.py
@@ -0,0 +1,12 @@
+from v2realbot.strategyblocks.indicators.custom.classes.indicatorbase import IndicatorBase
+from datetime import datetime, time
+from v2realbot.utils.utils import zoneNY
+
+#do budoucna predelat na staticky indikator
+class WeekDay(IndicatorBase):
+ def __init__(self, state):
+ super().__init__(state)
+ self.weekday = datetime.fromtimestamp(state.time).astimezone(zoneNY).weekday()
+
+ def next(self):
+ return self.weekday
\ No newline at end of file
diff --git a/v2realbot/strategyblocks/indicators/custom/target.py b/v2realbot/strategyblocks/indicators/custom/target.py
index 40812d4..520b959 100644
--- a/v2realbot/strategyblocks/indicators/custom/target.py
+++ b/v2realbot/strategyblocks/indicators/custom/target.py
@@ -61,7 +61,11 @@ def target(state, params, name):
if split_index == -1:
return -2, "for second based window length, source is required in format bars|close"
dict_name = source[:split_index]
- time_series = getattr(state, dict_name)["time"]
+ if dict_name == "bars":
+ #u baru je time v datetime, proto bereme udpated
+ time_series = getattr(state, dict_name)["updated"]
+ else:
+ time_series = getattr(state, dict_name)["time"]
state.cache[name]["time_series"] = time_series
else:
time_series = state.cache[name]["time_series"]