frontend config added
This commit is contained in:
Binary file not shown.
@ -24,6 +24,12 @@ from alpaca.data.enums import Exchange
|
||||
# return user.id
|
||||
# raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")
|
||||
|
||||
# Define a Pydantic model for input data
|
||||
class ConfigItem(BaseModel):
|
||||
id: Optional[int] = None
|
||||
item_name: str
|
||||
json_data: str
|
||||
|
||||
class Intervals(BaseModel):
|
||||
start: str
|
||||
end: str
|
||||
|
||||
@ -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, TestList, Intervals
|
||||
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem
|
||||
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
|
||||
@ -761,6 +761,7 @@ def get_all_archived_runners_detail():
|
||||
c = conn.cursor()
|
||||
res = c.execute(f"SELECT data FROM runner_detail")
|
||||
finally:
|
||||
conn.row_factory = None
|
||||
pool.release_connection(conn)
|
||||
return 0, res.fetchall()
|
||||
|
||||
@ -780,6 +781,7 @@ def get_archived_runner_details_byID(id: UUID):
|
||||
result = c.execute(f"SELECT data FROM runner_detail WHERE runner_id='{str(id)}'")
|
||||
res= result.fetchone()
|
||||
finally:
|
||||
conn.row_factory = None
|
||||
pool.release_connection(conn)
|
||||
if res==None:
|
||||
return -2, "not found"
|
||||
@ -797,6 +799,114 @@ def insert_archive_detail(archdetail: RunArchiveDetail):
|
||||
pool.release_connection(conn)
|
||||
return res.rowcount
|
||||
|
||||
# region TESTLISTS db services
|
||||
def get_testlists():
|
||||
try:
|
||||
conn = pool.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id, name, dates FROM test_list")
|
||||
rows = cursor.fetchall()
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
|
||||
testlists = []
|
||||
for row in rows:
|
||||
print(row)
|
||||
testlist = TestList(id=row[0], name=row[1], dates=json.loads(row[2]))
|
||||
testlists.append(testlist)
|
||||
|
||||
return 0, testlists
|
||||
|
||||
# endregion
|
||||
|
||||
# region CONFIG db services
|
||||
|
||||
def get_all_config_items():
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT id, item_name, json_data FROM config_table')
|
||||
config_items = [{"id": row[0], "item_name": row[1], "json_data": row[2]} for row in cursor.fetchall()]
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
return 0, config_items
|
||||
|
||||
# Function to get a config item by ID
|
||||
def get_config_item_by_id(item_id):
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT item_name, json_data FROM config_table WHERE id = ?', (item_id,))
|
||||
row = cursor.fetchone()
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
if row is None:
|
||||
return -2, "not found"
|
||||
else:
|
||||
return 0, {"item_name": row[0], "json_data": row[1]}
|
||||
|
||||
# Function to get a config item by ID
|
||||
def get_config_item_by_name(item_name):
|
||||
#print(item_name)
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
query = f"SELECT item_name, json_data FROM config_table WHERE item_name = '{item_name}'"
|
||||
#print(query)
|
||||
cursor.execute(query)
|
||||
row = cursor.fetchone()
|
||||
#print(row)
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
if row is None:
|
||||
return -2, "not found"
|
||||
else:
|
||||
return 0, {"item_name": row[0], "json_data": row[1]}
|
||||
|
||||
# Function to create a new config item
|
||||
def create_config_item(config_item: ConfigItem):
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('INSERT INTO config_table (item_name, json_data) VALUES (?, ?)', (config_item.item_name, config_item.json_data))
|
||||
item_id = cursor.lastrowid
|
||||
conn.commit()
|
||||
print(item_id)
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
|
||||
return 0, {"id": item_id, "item_name":config_item.item_name, "json_data":config_item.json_data}
|
||||
except Exception as e:
|
||||
return -2, str(e)
|
||||
|
||||
# Function to update a config item by ID
|
||||
def update_config_item(item_id, config_item: ConfigItem):
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('UPDATE config_table SET item_name = ?, json_data = ? WHERE id = ?', (config_item.item_name, config_item.json_data, item_id))
|
||||
conn.commit()
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
return 0, {"id": item_id, **config_item.dict()}
|
||||
except Exception as e:
|
||||
return -2, str(e)
|
||||
|
||||
# Function to delete a config item by ID
|
||||
def delete_config_item(item_id):
|
||||
conn = pool.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('DELETE FROM config_table WHERE id = ?', (item_id,))
|
||||
conn.commit()
|
||||
finally:
|
||||
pool.release_connection(conn)
|
||||
return 0, {"id": item_id}
|
||||
|
||||
# endregion
|
||||
|
||||
#returns b
|
||||
def get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetime_object_to: datetime, timeframe: TimeFrame):
|
||||
"""Returns Bar object
|
||||
|
||||
@ -14,7 +14,7 @@ import uvicorn
|
||||
from uuid import UUID
|
||||
import v2realbot.controller.services as cs
|
||||
from v2realbot.utils.ilog import get_log_window
|
||||
from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveDetail, Bar, RunArchiveChange, TestList
|
||||
from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveDetail, Bar, RunArchiveChange, TestList, ConfigItem
|
||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query
|
||||
from fastapi.responses import HTMLResponse, FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
@ -354,18 +354,11 @@ def create_record(testlist: TestList):
|
||||
# API endpoint to retrieve all records
|
||||
@app.get('/testlists/', dependencies=[Depends(api_key_auth)])
|
||||
def get_testlists():
|
||||
conn = pool.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id, name, dates FROM test_list")
|
||||
rows = cursor.fetchall()
|
||||
pool.release_connection(conn)
|
||||
|
||||
testlists = []
|
||||
for row in rows:
|
||||
testlist = TestList(id=row[0], name=row[1], dates=json.loads(row[2]))
|
||||
testlists.append(testlist)
|
||||
|
||||
return testlists
|
||||
res, sada = cs.get_testlists()
|
||||
if res == 0:
|
||||
return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
# API endpoint to retrieve a single record by ID
|
||||
@app.get('/testlists/{record_id}')
|
||||
@ -416,6 +409,73 @@ def delete_testlist(record_id: str):
|
||||
|
||||
return {'message': 'Record deleted'}
|
||||
|
||||
# region CONFIG APIS
|
||||
|
||||
# Get all config items
|
||||
@app.get("/config-items/", dependencies=[Depends(api_key_auth)])
|
||||
def get_all_items() -> list[ConfigItem]:
|
||||
res, sada = cs.get_all_config_items()
|
||||
if res == 0:
|
||||
return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
|
||||
# Get a config item by ID
|
||||
@app.get("/config-items/{item_id}", dependencies=[Depends(api_key_auth)])
|
||||
def get_item(item_id: int)-> ConfigItem:
|
||||
res, sada = cs.get_config_item_by_id(item_id)
|
||||
if res == 0:
|
||||
return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
# Get a config item by Name
|
||||
@app.get("/config-items-by-name/", dependencies=[Depends(api_key_auth)])
|
||||
def get_item(item_name: str)-> ConfigItem:
|
||||
res, sada = cs.get_config_item_by_name(item_name)
|
||||
if res == 0:
|
||||
return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
# Create a new config item
|
||||
@app.post("/config-items/", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
||||
def create_item(config_item: ConfigItem) -> ConfigItem:
|
||||
res, sada = cs.create_config_item(config_item)
|
||||
if res == 0: return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not created: {res}:{id} {sada}")
|
||||
|
||||
|
||||
# Update a config item by ID
|
||||
@app.put("/config-items/{item_id}", dependencies=[Depends(api_key_auth)])
|
||||
def update_item(item_id: int, config_item: ConfigItem) -> ConfigItem:
|
||||
res, sada = cs.get_config_item_by_id(item_id)
|
||||
if res != 0:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
res, sada = cs.update_config_item(item_id, config_item)
|
||||
if res == 0: return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not created: {res}:{id}")
|
||||
|
||||
|
||||
# Delete a config item by ID
|
||||
@app.delete("/config-items/{item_id}", dependencies=[Depends(api_key_auth)])
|
||||
def delete_item(item_id: int) -> dict:
|
||||
res, sada = cs.get_config_item_by_id(item_id)
|
||||
if res != 0:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
|
||||
|
||||
res, sada = cs.delete_config_item(item_id)
|
||||
if res == 0: return sada
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not created: {res}:{id}")
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# Thread function to insert data from the queue into the database
|
||||
def insert_queue2db():
|
||||
print("starting insert_queue2db thread")
|
||||
|
||||
@ -559,13 +559,28 @@
|
||||
<h4>Config</h4>
|
||||
</label>
|
||||
<div id="configInner" class="collapse show">
|
||||
config options
|
||||
<form id="configForm">
|
||||
<label for="configList">Select an Item:</label>
|
||||
<select id="configList"></select><br><br>
|
||||
|
||||
<label for="itemName">Item Name:</label>
|
||||
<input type="text" id="itemName"><br><br>
|
||||
|
||||
<label for="jsonTextarea">JSON Data:</label><br>
|
||||
<textarea id="jsonTextarea" rows="10" cols="50"></textarea><br><br>
|
||||
|
||||
<button type="button" id="saveButton">Save</button>
|
||||
<button type="button" id="addButton">Add</button>
|
||||
<button type="button" id="deleteButton">Delete</button>
|
||||
<button type="button" id="cancelButton">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottomContainer" class="flex-items" style="height: 800px">
|
||||
<BR>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/config.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
|
||||
<script src="/static/js/jquery.serializejson.js"></script>
|
||||
<script src="/static/js/utils.js"></script>
|
||||
@ -575,5 +590,6 @@
|
||||
<script src="/static/js/realtimechart.js"></script>
|
||||
<script src="/static/js/mytables.js"></script>
|
||||
<script src="/static/js/testlist.js"></script>
|
||||
<script src="/static/js/configform.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,6 +1,9 @@
|
||||
|
||||
var tradeDetails = new Map();
|
||||
var toolTip = null
|
||||
var CHART_SHOW_TEXT = false
|
||||
var CHART_SHOW_TEXT = get_from_config("CHART_SHOW_TEXT", false)
|
||||
|
||||
console.log("CHART_SHOW_TEXT archchart", CHART_SHOW_TEXT)
|
||||
// var vwapSeries = null
|
||||
// var volumeSeries = null
|
||||
var markersLine = null
|
||||
@ -11,6 +14,7 @@ var slLine = []
|
||||
//input array object bars = { high: [1,2,3], time: [1,2,3], close: [2,2,2]...}
|
||||
//output array [{ time: 111, open: 11, high: 33, low: 333, close: 333},..]
|
||||
function transform_data(data) {
|
||||
var SHOW_SL_DIGITS = get_from_config("SHOW_SL_DIGITS", true)
|
||||
transformed = []
|
||||
//get basic bars, volume and vvwap
|
||||
var bars = []
|
||||
@ -64,7 +68,8 @@ function transform_data(data) {
|
||||
sline_markers["position"] = "inBar"
|
||||
sline_markers["color"] = "#f5aa42"
|
||||
//sline_markers["shape"] = "circle"
|
||||
sline_markers["text"] = histRecord.sl_val.toFixed(3)
|
||||
console.log("SHOW_SL_DIGITS",SHOW_SL_DIGITS)
|
||||
sline_markers["text"] = SHOW_SL_DIGITS ? histRecord.sl_val.toFixed(3) : ""
|
||||
sl_line_markers_sada.push(sline_markers)
|
||||
|
||||
if (index === array.length - 1) {
|
||||
|
||||
64
v2realbot/static/js/config.js
Normal file
64
v2realbot/static/js/config.js
Normal file
@ -0,0 +1,64 @@
|
||||
//JS code for using config value on the frontend
|
||||
configData = {}
|
||||
|
||||
function get_from_config(name, def_value) {
|
||||
console.log("required", name, configData)
|
||||
if ((configData["JS"]) && (configData["JS"][name] !== undefined)) {
|
||||
console.log("returned from config", configData["JS"][name])
|
||||
return configData["JS"][name]
|
||||
}
|
||||
else {
|
||||
console.log("returned def_value", def_value)
|
||||
return def_value
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
const apiBaseUrl = '';
|
||||
|
||||
// Function to populate the config list and load JSON data initially
|
||||
function loadConfig(configName) {
|
||||
const rec = new Object()
|
||||
rec.item_name = configName
|
||||
$.ajax({
|
||||
url: `${apiBaseUrl}/config-items-by-name/`,
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('X-API-Key',
|
||||
API_KEY); },
|
||||
METHOD: 'GET',
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
data: rec,
|
||||
success: function (data) {
|
||||
console.log(data)
|
||||
try {
|
||||
configData[configName] = JSON.parse(data.json_data)
|
||||
console.log(configData)
|
||||
console.log("jsme tu")
|
||||
indConfig = configData["JS"].indConfig
|
||||
console.log("after")
|
||||
console.log(JSON.stringify(indConfig, null,null, 2))
|
||||
|
||||
console.log("before CHART_SHOW_TEXT",CHART_SHOW_TEXT)
|
||||
var CHART_SHOW_TEXT = configData["JS"].CHART_SHOW_TEXT
|
||||
console.log("after CHART_SHOW_TEXT",CHART_SHOW_TEXT)
|
||||
}
|
||||
catch (error) {
|
||||
window.alert(`Nešlo rozparsovat JSON_data string ${configName}`, error.message)
|
||||
}
|
||||
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
var err = eval("(" + xhr.responseText + ")");
|
||||
window.alert(`Nešlo dotáhnout config nastaveni z db ${configName}`, JSON.stringify(xhr));
|
||||
console.log(JSON.stringify(xhr));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const jsConfigName = "JS"
|
||||
//naloadovan config
|
||||
loadConfig(jsConfigName)
|
||||
|
||||
});
|
||||
166
v2realbot/static/js/configform.js
Normal file
166
v2realbot/static/js/configform.js
Normal file
@ -0,0 +1,166 @@
|
||||
//JS code for FRONTEND CONFIG FORM
|
||||
$(document).ready(function () {
|
||||
// API Base URL
|
||||
const apiBaseUrl = '';
|
||||
let editingItemId = null;
|
||||
var localArray = []
|
||||
|
||||
|
||||
// Function to populate the config list and load JSON data initially
|
||||
function populateConfigList(to_select = null) {
|
||||
$.ajax({
|
||||
url: `${apiBaseUrl}/config-items/`,
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('X-API-Key',
|
||||
API_KEY); },
|
||||
type: 'GET',
|
||||
success: function (data) {
|
||||
const configList = $('#configList');
|
||||
configList.empty();
|
||||
|
||||
localArray = data
|
||||
selected = ""
|
||||
data.forEach((item, index, array) => {
|
||||
selected = "";
|
||||
//pokud prijde id ktere mame vybrat vybereme to, jinak vybereme prvni
|
||||
if (((to_select !== null) && (to_select == item.id)) || ((to_select == null) && (index==0))) {
|
||||
selected = "SELECTED"
|
||||
$('#itemName').val(item.item_name);
|
||||
$('#jsonTextarea').val(item.json_data);
|
||||
editingItemId = item.id;
|
||||
}
|
||||
configList.append(`<option value="${item.id}" ${selected}>${item.item_name}</option>`);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
function showJSONdata(itemId) {
|
||||
localArray.forEach((item, index, array) => {
|
||||
if (item.id == itemId) {
|
||||
$('#itemName').val(item.item_name);
|
||||
$('#jsonTextarea').val(item.json_data);
|
||||
editingItemId = itemId;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#cancelButton').attr('disabled', true);
|
||||
// Populate the config list and load JSON data and item name initially
|
||||
populateConfigList();
|
||||
|
||||
// Event listener for config list change
|
||||
$('#configList').change(function () {
|
||||
const selectedItem = $(this).val();
|
||||
console.log(selectedItem)
|
||||
if (selectedItem) {
|
||||
showJSONdata(selectedItem);
|
||||
}
|
||||
});
|
||||
|
||||
// Save or add a config item
|
||||
$('#saveButton').click(function () {
|
||||
const itemName = $('#itemName').val();
|
||||
const jsonData = $('#jsonTextarea').val();
|
||||
var validformat = false
|
||||
$('#addButton').attr('disabled', false);
|
||||
$('#deleteButton').attr('disabled', false);
|
||||
|
||||
try {
|
||||
var parsedJSON = JSON.parse(jsonData)
|
||||
validformat = true
|
||||
}
|
||||
catch (error) {
|
||||
alert("Not valid JSON", error.message)
|
||||
}
|
||||
|
||||
if (validformat) {
|
||||
var confirmed = window.confirm("Sure?");
|
||||
|
||||
if (editingItemId && confirmed) {
|
||||
// Update the selected item with the modified data using API
|
||||
$.ajax({
|
||||
url: `${apiBaseUrl}/config-items/${editingItemId}`,
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('X-API-Key',
|
||||
API_KEY); },
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ item_name: itemName, json_data: jsonData }),
|
||||
success: function () {
|
||||
alert('Data saved successfully.');
|
||||
populateConfigList(editingItemId); // Refresh the config list
|
||||
}
|
||||
});
|
||||
|
||||
} else if (confirmed) {
|
||||
// Add a new config item using API
|
||||
$.ajax({
|
||||
url: `${apiBaseUrl}/config-items/`,
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('X-API-Key',
|
||||
API_KEY); },
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({ item_name: itemName, json_data: jsonData }),
|
||||
success: function (data) {
|
||||
console.log(data)
|
||||
alert('New item added successfully.');
|
||||
populateConfigList(data.id); // Refresh the config list
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add a new config item (populates a new record in the form)
|
||||
$('#addButton').click(function () {
|
||||
$('#configList').val('');
|
||||
$('#itemName').val('');
|
||||
$('#jsonTextarea').val('');
|
||||
editingItemId = null;
|
||||
$('#addButton').attr('disabled', true);
|
||||
$('#deleteButton').attr('disabled', true);
|
||||
$('#cancelButton').attr('disabled', false);
|
||||
|
||||
});
|
||||
|
||||
// Add a new config item (populates a new record in the form)
|
||||
$('#cancelButton').click(function () {
|
||||
$('#addButton').attr('disabled', false);
|
||||
$('#deleteButton').attr('disabled', false);
|
||||
$('#cancelButton').attr('disabled', true);
|
||||
populateConfigList();
|
||||
});
|
||||
|
||||
// Delete a config item
|
||||
$('#deleteButton').click(function () {
|
||||
if (editingItemId == null) {
|
||||
$('#configList').val('');
|
||||
$('#itemName').val('');
|
||||
$('#jsonTextarea').val('');
|
||||
}
|
||||
else {
|
||||
var confirmed = window.confirm("Confirm?");
|
||||
if (confirmed) {
|
||||
|
||||
$.ajax({
|
||||
url: `${apiBaseUrl}/config-items/${editingItemId}`,
|
||||
beforeSend: function (xhr) {
|
||||
xhr.setRequestHeader('X-API-Key',
|
||||
API_KEY); },
|
||||
type: 'DELETE',
|
||||
success: function () {
|
||||
alert('Item deleted successfully.');
|
||||
populateConfigList(); // Refresh the config list
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@ -525,7 +525,7 @@ var stratinRecords =
|
||||
{data: 'history', visible: false},
|
||||
{data: 'id', visible: true},
|
||||
],
|
||||
paging: false,
|
||||
paging: true,
|
||||
processing: false,
|
||||
columnDefs: [{
|
||||
targets: 12,
|
||||
|
||||
@ -50,6 +50,7 @@ indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, pri
|
||||
{name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
|
||||
{name: "stoch2", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
|
||||
{name: "sec_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},]
|
||||
console.log(JSON.stringify(indConfig, null,null, 2))
|
||||
|
||||
|
||||
function initialize_statusheader() {
|
||||
|
||||
Reference in New Issue
Block a user