pridan draft batch runu
This commit is contained in:
@ -6,7 +6,7 @@ from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, Orde
|
||||
from v2realbot.indicators.indicators import ema
|
||||
from v2realbot.indicators.oscillators import rsi
|
||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||
from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, round2five, is_open_rush, is_close_rush, eval_cond_dict, Average, crossed_down, crossed_up, crossed, is_pivot, json_serial
|
||||
from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, round2five, is_open_rush, is_close_rush, is_window_open, eval_cond_dict, Average, crossed_down, crossed_up, crossed, is_pivot, json_serial
|
||||
from v2realbot.utils.directive_utils import get_conditions_from_configuration
|
||||
from v2realbot.common.model import SLHistory
|
||||
from datetime import datetime
|
||||
@ -1108,13 +1108,17 @@ def next(data, state: StrategyState):
|
||||
#obecne precondition preds vstupem - platne jak pro condition based tak pro plugin
|
||||
def common_go_preconditions_check(signalname: str, options: dict):
|
||||
#ZAKLADNI KONTROLY ATRIBUTU s fallbackem na obecné
|
||||
#check working windows
|
||||
close_rush = safe_get(options, "close_rush",safe_get(state.vars, "open_rush",0))
|
||||
open_rush = safe_get(options, "open_rush",safe_get(state.vars, "close_rush",0))
|
||||
#check working windows (open - close, in minutes from the start of marker)
|
||||
window_open = safe_get(options, "window_open",safe_get(state.vars, "window_open",0))
|
||||
window_close = safe_get(options, "window_close",safe_get(state.vars, "window_close",390))
|
||||
|
||||
if is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), open_rush) or is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), close_rush):
|
||||
state.ilog(e=f"SIGNAL {signalname} - RUSH STANDBY", msg=f"{open_rush=} {close_rush=} ")
|
||||
return False
|
||||
if is_window_open(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), window_open, window_close) is False:
|
||||
state.ilog(e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{window_open=} {window_close=} ")
|
||||
return False
|
||||
|
||||
# if is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), open_rush) or is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), close_rush):
|
||||
# state.ilog(e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{open_rush=} {close_rush=} ")
|
||||
# return False
|
||||
|
||||
#natvrdo nebo na podminku
|
||||
activated = safe_get(options, "activated", True)
|
||||
|
||||
Binary file not shown.
@ -27,6 +27,7 @@ from alpaca.data.enums import Exchange
|
||||
class Intervals(BaseModel):
|
||||
start: str
|
||||
end: str
|
||||
note: Optional[str] = None
|
||||
|
||||
# Define the data model for the TestLists
|
||||
class TestList(BaseModel):
|
||||
@ -71,6 +72,7 @@ class RunRequest(BaseModel):
|
||||
ilog_save: bool = False
|
||||
bt_from: datetime = None
|
||||
bt_to: datetime = None
|
||||
test_batch_id: Optional[str] = None
|
||||
cash: int = 100000
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ from alpaca.data.requests import StockTradesRequest, StockBarsRequest
|
||||
from alpaca.data.enums import DataFeed
|
||||
from alpaca.data.timeframe import TimeFrame
|
||||
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
||||
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent
|
||||
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals
|
||||
from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
||||
from v2realbot.utils.ilog import delete_logs
|
||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||
@ -19,6 +19,7 @@ from tinydb import TinyDB, Query, where
|
||||
from tinydb.operations import set
|
||||
import json
|
||||
from numpy import ndarray
|
||||
from rich import print
|
||||
import pandas as pd
|
||||
from traceback import format_exc
|
||||
from datetime import timedelta, time
|
||||
@ -309,8 +310,94 @@ def capsule(target: object, db: object):
|
||||
db.runners.remove(i)
|
||||
|
||||
print("Runner STOPPED")
|
||||
|
||||
#vrátí konkrétní sadu testlistu
|
||||
def get_testlist_byID(record_id: str):
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id, name, dates FROM test_list WHERE id = ?", (record_id,))
|
||||
row = cursor.fetchone()
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
|
||||
if row is None:
|
||||
return -2, "not found"
|
||||
else:
|
||||
return 0, TestList(id=row[0], name=row[1], dates=json.loads(row[2]))
|
||||
|
||||
|
||||
#volano pro batchove spousteni (BT,)
|
||||
def run_batch_stratin(id: UUID, runReq: RunRequest):
|
||||
if runReq.test_batch_id is None:
|
||||
return (-1, "batch_id required for batch run")
|
||||
|
||||
if runReq.mode != Mode.BT:
|
||||
return (-1, "batch run only for backtest")
|
||||
|
||||
print("request values:", runReq)
|
||||
|
||||
print("getting intervals")
|
||||
testlist: TestList
|
||||
|
||||
res, testlist = get_testlist_byID(record_id=runReq.test_batch_id)
|
||||
|
||||
if res < 0:
|
||||
return (-1, f"not existing ID of testlists with {runReq.test_batch_id}")
|
||||
|
||||
#spousti se vlakno s paralelnim behem a vracime ok
|
||||
ridici_vlakno = Thread(target=batch_run_manager, args=(id, runReq, testlist), name=f"Batch run controll thread started.")
|
||||
ridici_vlakno.start()
|
||||
print(enumerate())
|
||||
|
||||
return 0, f"Batch run started"
|
||||
|
||||
|
||||
#thread, ktery bude ridit paralelni spousteni
|
||||
# bud ceka na dokonceni v runners nebo to bude ridit jinak a bude mit jednoho runnera?
|
||||
# nejak vymyslet.
|
||||
# logovani zatim jen do print
|
||||
def batch_run_manager(id: UUID, runReq: RunRequest, testlist: TestList):
|
||||
#zde muzu iterovat nad intervaly
|
||||
#cekat az dobehne jeden interval a pak spustit druhy
|
||||
#pripadne naplanovat beh - to uvidim
|
||||
#domyslet kompatibilitu s budoucim automatickym "dennim" spousteni strategii
|
||||
#taky budu mit nejaky konfiguracni RUN MANAGER, tak by krome rizeniho denniho runu
|
||||
#mohl podporovat i BATCH RUNy.
|
||||
batch_id = str(uuid4())[:8]
|
||||
print("generated batch_ID", batch_id)
|
||||
|
||||
print("test batch", testlist)
|
||||
|
||||
print("test date", testlist.dates)
|
||||
interval: Intervals
|
||||
cnt_max = len(testlist.dates)
|
||||
cnt = 0
|
||||
for intrvl in testlist.dates:
|
||||
cnt += 1
|
||||
interval = intrvl
|
||||
if interval.note is not None:
|
||||
print("mame zde note")
|
||||
print("Datum od", interval.start)
|
||||
print("Datum do", interval.end)
|
||||
print("starting")
|
||||
|
||||
#předání atributů datetime.fromisoformat
|
||||
runReq.bt_from = datetime.fromisoformat(interval.start)
|
||||
runReq.bt_to = datetime.fromisoformat(interval.end)
|
||||
runReq.note = f"Batch {batch_id} run #{cnt}/{cnt_max} Note:{interval.note}"
|
||||
|
||||
#protoze jsme v ridicim vlaknu, poustime za sebou jednotlive stratiny v synchronnim modu
|
||||
res, id_val = run_stratin(id=id, runReq=runReq, synchronous=True)
|
||||
if res < 0:
|
||||
print(f"CHyba v runu #{cnt} od:{runReq.bt_from} do {runReq.bt_to} -> {id_val}")
|
||||
break
|
||||
|
||||
print("Batch manager FINISHED")
|
||||
|
||||
|
||||
#stratin run
|
||||
def run_stratin(id: UUID, runReq: RunRequest):
|
||||
def run_stratin(id: UUID, runReq: RunRequest, synchronous: bool = False):
|
||||
if runReq.mode == Mode.BT:
|
||||
if runReq.bt_from is None:
|
||||
return (-1, "start date required for BT")
|
||||
@ -405,6 +492,12 @@ def run_stratin(id: UUID, runReq: RunRequest):
|
||||
print(db.runners)
|
||||
print(i)
|
||||
print(enumerate())
|
||||
|
||||
#pokud spoustime v batch módu, tak čekáme na výsledek a pak pouštíme další run
|
||||
if synchronous:
|
||||
print(f"waiting for thread {vlakno} to finish")
|
||||
vlakno.join()
|
||||
|
||||
return (0, id)
|
||||
except Exception as e:
|
||||
return (-2, "Exception: "+str(e)+format_exc())
|
||||
|
||||
Binary file not shown.
@ -226,7 +226,11 @@ def _get_stratin(stratin_id) -> StrategyInstance:
|
||||
|
||||
@app.put("/stratins/{stratin_id}/run", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
||||
def _run_stratin(stratin_id: UUID, runReq: RunRequest):
|
||||
res, id = cs.run_stratin(id=stratin_id, runReq=runReq)
|
||||
print(runReq)
|
||||
if runReq.test_batch_id is not None:
|
||||
res, id = cs.run_batch_stratin(id=stratin_id, runReq=runReq)
|
||||
else:
|
||||
res, id = cs.run_stratin(id=stratin_id, runReq=runReq)
|
||||
if res == 0: return id
|
||||
elif res < 0:
|
||||
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error: {res}:{id}")
|
||||
@ -336,8 +340,8 @@ def _get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, dateti
|
||||
@app.post('/testlists/', dependencies=[Depends(api_key_auth)])
|
||||
def create_record(testlist: TestList):
|
||||
# Generate a new UUID for the record
|
||||
testlist.id = str(uuid4())
|
||||
|
||||
testlist.id = str(uuid4())[:8]
|
||||
|
||||
# Insert the record into the database
|
||||
conn = pool.get_connection()
|
||||
cursor = conn.cursor()
|
||||
@ -366,17 +370,12 @@ def get_testlists():
|
||||
# API endpoint to retrieve a single record by ID
|
||||
@app.get('/testlists/{record_id}')
|
||||
def get_testlist(record_id: str):
|
||||
conn = pool.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id, name, dates FROM test_list WHERE id = ?", (record_id,))
|
||||
row = cursor.fetchone()
|
||||
pool.release_connection(conn)
|
||||
|
||||
if row is None:
|
||||
res, testlist = cs.get_testlist_byID(record_id=record_id)
|
||||
|
||||
if res == 0:
|
||||
return testlist
|
||||
elif res < 0:
|
||||
raise HTTPException(status_code=404, detail='Record not found')
|
||||
|
||||
testlist = TestList(id=row[0], name=row[1], dates=json.loads(row[2]))
|
||||
return testlist
|
||||
|
||||
# API endpoint to update a record
|
||||
@app.put('/testlists/{record_id}')
|
||||
|
||||
@ -38,7 +38,10 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mousetrap/1.4.6/mousetrap.min.js"></script>
|
||||
<!-- <script src="https://cdn.datatables.net/select/1.6.2/js/dataTables.select.min.js"></script> -->
|
||||
<script src="/static/js/fast-toml.js" type="text/javascript"></script>
|
||||
|
||||
|
||||
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/editor/editor.main.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/loader.min.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="main" class="mainConteiner flex-container content">
|
||||
@ -112,6 +115,7 @@
|
||||
<button id="button_refresh" class="refresh btn btn-outline-success btn-sm">Refresh</button>
|
||||
<button id="button_connect" class="btn btn-outline-success btn-sm">Connect</button>
|
||||
</div>
|
||||
<div>status info</div>
|
||||
<table id="runnerTable" class="table-striped table dataTable" style="width:100%; border-color: #dce1dc;">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -340,7 +344,16 @@
|
||||
<div class="form-group">
|
||||
<label for="close_rush" class="form-label">close_rush</label>
|
||||
<input type="number" class="form-control" id="close_rush" name="close_rush" placeholder="close_rush" value=0 required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div id="editor"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Create a textarea for saving content -->
|
||||
<!-- <textarea id="content" style="display: none;"></textarea> -->
|
||||
<div class="form-group">
|
||||
<label for="stratvars_conf" class="form-label">stratvars_conf</label>
|
||||
<textarea class="form-control" rows="16" id="stratvars_conf" name="stratvars_conf" required></textarea>
|
||||
@ -459,7 +472,6 @@
|
||||
<label for="account" class="form-label">Account</label>
|
||||
<select class="form-control" id="account" name="account"><option value="ACCOUNT1">ACCOUNT1</option><option value="ACCOUNT2">ACCOUNT2</option></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="debug" class="form-label">debug</label>
|
||||
<select class="form-control" id="debug" name="debug"><option value="true">true</option><option value="false" selected>false</option></select>
|
||||
@ -472,6 +484,10 @@
|
||||
<label for="bt_to" class="form-label">bt_to</label>
|
||||
<input type="datetime-local" class="form-control" id="bt_to" name="bt_to" placeholder="2023-04-06T09:00:00Z" step="1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="test_batch_id" class="form-label">Test Batch ID</label>
|
||||
<input type="text" class="form-control" id="test_batch_id" name="test_batch_id" placeholder="test intervals ID">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cash" class="form-label">cash</label>
|
||||
<input type="number" class="form-control" id="cash" name="cash" placeholder="cash" value="100000">
|
||||
@ -521,6 +537,8 @@
|
||||
<input type="datetime-local" id="datepickerstart" step="1">
|
||||
<label for="datepickerend">End:</label>
|
||||
<input type="datetime-local" id="datepickerend" step="1">
|
||||
<label for="datenote">Note:</label>
|
||||
<input type="text" id="datenote">
|
||||
<button type="button" id="addTagBtn" class="btn btn-outline-success btn-sm">Add Date</button>
|
||||
<br>
|
||||
<div id="tagContainer"></div>
|
||||
|
||||
@ -24,6 +24,8 @@ function transform_data(data) {
|
||||
var sl_line_markers_sada = []
|
||||
//console.log(JSON.stringify(data.ext_data.sl_history, null, 2))
|
||||
prev_id = 0
|
||||
//cas of first record, nekdy jsou stejny - musim pridat setinku
|
||||
prev_cas = 0
|
||||
data.ext_data.sl_history.forEach((histRecord, index, array) => {
|
||||
|
||||
console.log("plnime")
|
||||
@ -41,8 +43,16 @@ function transform_data(data) {
|
||||
}
|
||||
|
||||
prev_id = histRecord.id
|
||||
|
||||
//prevedeme iso data na timestampy
|
||||
cas = histRecord.time
|
||||
|
||||
if (cas == prev_cas) {
|
||||
cas = cas + 0.001
|
||||
}
|
||||
|
||||
prev_cas = cas
|
||||
|
||||
//line pro buy/sell markery
|
||||
sline = {}
|
||||
sline["time"] = cas
|
||||
@ -599,6 +609,8 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
||||
slLine.forEach((series, index, array) => {
|
||||
chart.removeSeries(series)
|
||||
})
|
||||
slLine=[]
|
||||
|
||||
}
|
||||
// if (slLine) {
|
||||
// chart.removeSeries(slLine)
|
||||
@ -627,7 +639,6 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
||||
});
|
||||
|
||||
slLine_temp.setData(slRecord);
|
||||
//zatim nemame markery pro sl history
|
||||
slLine_temp.setMarkers(transformed_data["sl_line_markers"][index]);
|
||||
slLine.push(slLine_temp)
|
||||
|
||||
|
||||
@ -406,11 +406,32 @@ $(document).ready(function () {
|
||||
//console.log(localStorage.getItem("bt_from"))
|
||||
$('#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"));
|
||||
$('#account').val(localStorage.getItem("account"));
|
||||
$('#debug').val(localStorage.getItem("debug"));
|
||||
$('#ilog_save').val(localStorage.getItem("ilog_save"));
|
||||
$('#runid').val(row.id);
|
||||
|
||||
// Initially, check the value of "batch" and enable/disable "from" and "to" accordingly
|
||||
if ($("#test_batch_id").val() !== "") {
|
||||
$("#bt_from, #bt_to").prop("disabled", true);
|
||||
} else {
|
||||
$("#bt_from, #bt_to").prop("disabled", false);
|
||||
}
|
||||
|
||||
// Listen for changes in the "batch" input
|
||||
$("#test_batch_id").on("input", function() {
|
||||
if ($(this).val() !== "") {
|
||||
// If "batch" is not empty, disable "from" and "to"
|
||||
$("#bt_from, #bt_to").prop("disabled", true);
|
||||
} else {
|
||||
// If "batch" is empty, enable "from" and "to"
|
||||
$("#bt_from, #bt_to").prop("disabled", false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
//button add
|
||||
@ -441,6 +462,23 @@ $(document).ready(function () {
|
||||
$('.modal-title').html(" Edit Records");
|
||||
$('#action').val('updateRecord');
|
||||
$('#save').val('Save');
|
||||
//code for toml editor
|
||||
// Initialize Monaco Editor
|
||||
|
||||
// require.config({ paths: { vs: 'monaco-editor/min/vs' } });
|
||||
// require(['vs/editor/editor.main'], function () {
|
||||
// var editor = $("#editor").monacoEditor({
|
||||
// language: "toml",
|
||||
// value: row.stratvars_conf
|
||||
// });
|
||||
// // Get content from Monaco Editor and set it to the textarea using jQuery
|
||||
// editor.getModels()[0].onDidChangeContent(function() {
|
||||
// var tomlContent = monaco.editor.getModels()[0].getValue();
|
||||
// $('#stratvars_conf').val(tomlContent);
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
});
|
||||
//delete button
|
||||
$('#button_delete').click(function () {
|
||||
@ -576,6 +614,7 @@ var runnerRecords =
|
||||
$("#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("account", $('#account').val());
|
||||
localStorage.setItem("debug", $('#debug').val());
|
||||
@ -587,7 +626,7 @@ $("#runModal").on('submit','#runForm', function(event){
|
||||
//rename runid to id
|
||||
Object.defineProperty(formData, "id", Object.getOwnPropertyDescriptor(formData, "runid"));
|
||||
delete formData["runid"];
|
||||
//console.log(formData)
|
||||
console.log(formData)
|
||||
if ($('#ilog_save').prop('checked')) {
|
||||
formData.ilog_save = true;
|
||||
}
|
||||
@ -599,6 +638,8 @@ $("#runModal").on('submit','#runForm', function(event){
|
||||
if (formData.bt_from == "") {delete formData["bt_from"];}
|
||||
if (formData.bt_to == "") {delete formData["bt_to"];}
|
||||
|
||||
if (formData.test_batch_id == "") {delete formData["test_batch_id"];}
|
||||
|
||||
//create strat_json - snapshot of stratin
|
||||
row = stratinRecords.row('.selected').data();
|
||||
const rec = new Object()
|
||||
|
||||
@ -16,7 +16,15 @@ $(document).ready(function() {
|
||||
datesArray.forEach(function(dates) {
|
||||
var tag = $('<div class="tag">' + dates.start + " --- " + dates.end + '<span class="close">X</span></div>');
|
||||
tag.find('.close').click(function() {
|
||||
var dateText = tag.text();
|
||||
console.log("clicked")
|
||||
datesArray = datesArray.filter(function(date) {
|
||||
tagcontent = date.start + " --- " + date.end + "X"
|
||||
console.log(tagcontent,dateText)
|
||||
return tagcontent !== dateText;
|
||||
});
|
||||
$(this).parent().remove();
|
||||
console.log("ccclickd")
|
||||
});
|
||||
$('#tagContainer').append(tag);
|
||||
});
|
||||
@ -29,9 +37,13 @@ $(document).ready(function() {
|
||||
records.forEach(function(record) {
|
||||
var recordItem = $('<div class="recordItem"></div>');
|
||||
var recordDetails = $('<div class="recordDetails"></div>').html('<strong>ID:</strong> ' + record.id + '<br><strong>Name:</strong> ' + record.name + '<br><strong>Dates:</strong> ');
|
||||
|
||||
|
||||
record.dates.forEach(function(interval) {
|
||||
var intervalItem = $('<div class="intervalContainer"></div>').html('<strong>Start:</strong> ' + interval.start + '<br><strong>End:</strong> ' + interval.end);
|
||||
var note = ""
|
||||
if (interval.note !== null) {
|
||||
var note = '<br><strong>Note:</strong> ' + interval.note
|
||||
}
|
||||
var intervalItem = $('<div class="intervalContainer"></div>').html('<strong>Start:</strong> ' + interval.start + '<br><strong>End:</strong> ' + interval.end + note);
|
||||
recordDetails.append(intervalItem);
|
||||
});
|
||||
|
||||
@ -98,15 +110,24 @@ $(document).ready(function() {
|
||||
$('#addTagBtn').click(function() {
|
||||
var dateTextStart = $('#datepickerstart').val().trim();
|
||||
var dateTextEnd = $('#datepickerend').val().trim();
|
||||
var datenote = $('#datenote').val();
|
||||
if ((dateTextStart !== '') && (dateTextEnd !== '')) {
|
||||
var tag = $('<div class="tag">' + dateTextStart + " --- " + dateTextEnd + '<span class="close">X</span></div>');
|
||||
tag.find('.close').click(function() {
|
||||
var dateText = tag.text();
|
||||
console.log("clicked")
|
||||
datesArray = datesArray.filter(function(date) {
|
||||
tagcontent = date.start + " --- " + date.end + "X"
|
||||
console.log(tagcontent,dateText)
|
||||
return tagcontent !== dateText;
|
||||
});
|
||||
$(this).parent().remove();
|
||||
});
|
||||
$('#tagContainer').append(tag);
|
||||
var interval = {}
|
||||
interval["start"] = dateTextStart
|
||||
interval["end"] = dateTextEnd
|
||||
interval["note"] = datenote
|
||||
datesArray.push(interval);
|
||||
$('#datepicker').val('');
|
||||
}
|
||||
@ -145,15 +166,17 @@ $(document).ready(function() {
|
||||
cancelEdit();
|
||||
});
|
||||
|
||||
$('#tagContainer').on('click', '.tag .close', function() {
|
||||
var tag = $(this).parent();
|
||||
var dateText = tag.text();
|
||||
datesArray = datesArray.filter(function(date) {
|
||||
tagcontent = date.start + " --- " + date.end
|
||||
return tagcontent !== dateText;
|
||||
});
|
||||
tag.remove();
|
||||
});
|
||||
// $('#tagContainer').on('click', '.tag .close', function() {
|
||||
// var tag = $(this).parent();
|
||||
// var dateText = tag.text();
|
||||
// console.log("clicked")
|
||||
// datesArray = datesArray.filter(function(date) {
|
||||
// tagcontent = date.start + " --- " + date.end
|
||||
// console.log(tagcontent,dateText)
|
||||
// return tagcontent !== dateText;
|
||||
// });
|
||||
// tag.remove();
|
||||
// });
|
||||
|
||||
function getRecords() {
|
||||
$.ajax({
|
||||
|
||||
@ -223,6 +223,7 @@ function cleanup_chart() {
|
||||
clear_status_header()
|
||||
chart = null
|
||||
indList = [];
|
||||
slLine = []
|
||||
markersLine = null
|
||||
avgBuyLine = null
|
||||
volumeSeries = null
|
||||
|
||||
@ -398,6 +398,13 @@ pre {
|
||||
'opsz' 24
|
||||
}
|
||||
|
||||
.intervalContainer {
|
||||
float: left;
|
||||
border-width: thick;
|
||||
border: beige;
|
||||
display: inline-table;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* TestList part generated by ChatGPT */
|
||||
.recordItem {
|
||||
|
||||
Binary file not shown.
@ -284,6 +284,34 @@ def is_open_rush(dt: datetime, mins: int = 30):
|
||||
rushtime = (datetime.combine(date.today(), business_hours["from"]) + timedelta(minutes=mins)).time()
|
||||
return business_hours["from"] <= dt.time() < rushtime
|
||||
|
||||
#TODO market time pro dany den si dotahnout z Alpaca
|
||||
def is_window_open(dt: datetime, start: int = 0, end: int = 390):
|
||||
""""
|
||||
Returns true if time (start in minutes and end in minutes) is in working window
|
||||
"""
|
||||
if start < 0 or start > 389:
|
||||
return False
|
||||
|
||||
if end < 0 or end > 389:
|
||||
return False
|
||||
|
||||
dt = dt.astimezone(zoneNY)
|
||||
business_hours = {
|
||||
"from": time(hour=9, minute=30),
|
||||
"to": time(hour=16, minute=0)
|
||||
}
|
||||
startime = (datetime.combine(date.today(), business_hours["from"]) + timedelta(minutes=start)).time()
|
||||
endtime = (datetime.combine(date.today(), business_hours["from"]) + timedelta(minutes=end)).time()
|
||||
|
||||
#time not within business hours
|
||||
if not business_hours["from"] <= dt.time() <= business_hours["to"]:
|
||||
return False
|
||||
|
||||
if startime <= dt.time() <= endtime:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_close_rush(dt: datetime, mins: int = 30):
|
||||
""""
|
||||
Returns true if time is within afternoon rush (close-mins)
|
||||
|
||||
Reference in New Issue
Block a user