upravy gui

This commit is contained in:
David Brazda
2023-04-30 20:39:46 +02:00
parent 60b8457b4f
commit 902eee1d67
14 changed files with 515 additions and 169 deletions

View File

@ -7,35 +7,38 @@ import time
from alpaca.data import Quote, Trade, Snapshot, Bar from alpaca.data import Quote, Trade, Snapshot, Bar
from alpaca.data.models import BarSet, QuoteSet, TradeSet from alpaca.data.models import BarSet, QuoteSet, TradeSet
from alpaca.data.timeframe import TimeFrame from alpaca.data.timeframe import TimeFrame
import mplfinance as mpf # import mplfinance as mpf
import pandas as pd import pandas as pd
from v2realbot.utils.utils import zoneNY
from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY
parametry = {} parametry = {}
# no keys required # no keys required
#client = CryptoHistoricalDataClient() #client = CryptoHistoricalDataClient()
client = StockHistoricalDataClient(API_KEY, SECRET_KEY, raw_data=False) client = StockHistoricalDataClient(ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, raw_data=False)
datetime_object_from = datetime.datetime(2023, 2, 27, 18, 51, 38, tzinfo=datetime.timezone.utc) datetime_object_from = datetime.datetime(2023, 2, 27, 18, 51, 38, tzinfo=datetime.timezone.utc)
datetime_object_to = datetime.datetime(2023, 2, 27, 21, 51, 39, tzinfo=datetime.timezone.utc) datetime_object_to = datetime.datetime(2023, 2, 27, 21, 51, 39, tzinfo=datetime.timezone.utc)
bar_request = StockBarsRequest(symbol_or_symbols="BAC",timeframe=TimeFrame.Hour, start=datetime_object_from, end=datetime_object_to, feed=DataFeed.SIP) bar_request = StockBarsRequest(symbol_or_symbols="BAC",timeframe=TimeFrame.Minute, start=datetime_object_from, end=datetime_object_to, feed=DataFeed.SIP)
bars = client.get_stock_bars(bar_request).df # bars = client.get_stock_bars(bar_request).df
bars = client.get_stock_bars(bar_request)
#bars = bars.drop(['symbol']) #bars = bars.drop(['symbol'])
#print(bars.df.close) #print(bars.df.close)
bars = bars.tz_convert('America/New_York') #bars = bars.tz_convert('America/New_York')
print(bars) print(bars.data["BAC"])
print(bars.df.columns) #print(bars.df.columns)
#Index(['open', 'high', 'low', 'close', 'volume', 'trade_count', 'vwap'], dtype='object') #Index(['open', 'high', 'low', 'close', 'volume', 'trade_count', 'vwap'], dtype='object')
bars.df.set_index('timestamp', inplace=True) # bars.df.set_index('timestamp', inplace=True)
mpf.plot(bars.df, # the dataframe containing the OHLC (Open, High, Low and Close) data # mpf.plot(bars.df, # the dataframe containing the OHLC (Open, High, Low and Close) data
type='candle', # use candlesticks # type='candle', # use candlesticks
volume=True, # also show the volume # volume=True, # also show the volume
mav=(3,6,9), # use three different moving averages # mav=(3,6,9), # use three different moving averages
figratio=(3,1), # set the ratio of the figure # figratio=(3,1), # set the ratio of the figure
style='yahoo', # choose the yahoo style # style='yahoo', # choose the yahoo style
title='Prvni chart'); # title='Prvni chart');
# #vrací se list od dict # #vrací se list od dict
# print(bars["BAC"]) # print(bars["BAC"])

View File

@ -72,6 +72,7 @@ class RunnerView(BaseModel):
run_name: Optional[str] = None run_name: Optional[str] = None
run_note: Optional[str] = None run_note: Optional[str] = None
run_account: Account run_account: Account
run_symbol: Optional[str] = None
run_trade_count: Optional[int] = 0 run_trade_count: Optional[int] = 0
run_profit: Optional[float] = 0 run_profit: Optional[float] = 0
run_positions: Optional[int] = 0 run_positions: Optional[int] = 0
@ -85,6 +86,7 @@ class Runner(BaseModel):
run_started: Optional[datetime] = None run_started: Optional[datetime] = None
run_mode: Mode run_mode: Mode
run_account: Account run_account: Account
run_symbol: Optional[str] = None
run_name: Optional[str] = None run_name: Optional[str] = None
run_note: Optional[str] = None run_note: Optional[str] = None
run_trade_count: Optional[int] run_trade_count: Optional[int]
@ -98,6 +100,33 @@ class Runner(BaseModel):
run_pause_ev: Optional[object] = None run_pause_ev: Optional[object] = None
run_stop_ev: Optional[object] = None run_stop_ev: Optional[object] = None
class Bar(BaseModel):
"""Represents one bar/candlestick of aggregated trade data over a specified interval.
Attributes:
symbol (str): The ticker identifier for the security whose data forms the bar.
timestamp (datetime): The closing timestamp of the bar.
open (float): The opening price of the interval.
high (float): The high price during the interval.
low (float): The low price during the interval.
close (float): The closing price of the interval.
volume (float): The volume traded over the interval.
trade_count (Optional[float]): The number of trades that occurred.
vwap (Optional[float]): The volume weighted average price.
exchange (Optional[float]): The exchange the bar was formed on.
"""
symbol: str
timestamp: datetime
open: float
high: float
low: float
close: float
volume: float
trade_count: Optional[float]
vwap: Optional[float]
class Order(BaseModel): class Order(BaseModel):
id: UUID id: UUID
submitted_at: datetime submitted_at: datetime
@ -130,6 +159,7 @@ class RunArchive(BaseModel):
id: UUID id: UUID
#id of running strategy (stratin/runner) #id of running strategy (stratin/runner)
strat_id: UUID strat_id: UUID
symbol: str
name: str name: str
note: Optional[str] = None note: Optional[str] = None
started: datetime started: datetime

View File

@ -3,7 +3,7 @@ from v2realbot.enums.enums import Mode, Account, FillCondition
from appdirs import user_data_dir from appdirs import user_data_dir
#no print in console #no print in console
QUIET_MODE = False QUIET_MODE = True
#how many consecutive trades with the fill price are necessary for LIMIT fill to happen in backtesting #how many consecutive trades with the fill price are necessary for LIMIT fill to happen in backtesting
#0 - optimistic, every knot high will fill the order #0 - optimistic, every knot high will fill the order
#N - N consecutive trades required #N - N consecutive trades required

View File

@ -2,8 +2,9 @@ from typing import Any, List
from uuid import UUID, uuid4 from uuid import UUID, uuid4
import pickle import pickle
from alpaca.data.historical import StockHistoricalDataClient from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockTradesRequest from alpaca.data.requests import StockTradesRequest, StockBarsRequest
from alpaca.data.enums import DataFeed from alpaca.data.enums import DataFeed
from alpaca.data.timeframe import TimeFrame
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail
from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial
@ -365,6 +366,7 @@ def run_stratin(id: UUID, runReq: RunRequest):
run_started = datetime.now(zoneNY), run_started = datetime.now(zoneNY),
run_pause_ev = pe, run_pause_ev = pe,
run_name = name, run_name = name,
run_symbol = symbol,
run_note = runReq.note, run_note = runReq.note,
run_stop_ev = se, run_stop_ev = se,
run_thread = vlakno, run_thread = vlakno,
@ -409,6 +411,7 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
strat_id = runner.id, strat_id = runner.id,
name=runner.run_name, name=runner.run_name,
note=runner.run_note, note=runner.run_note,
symbol=runner.run_symbol,
started=runner.run_started, started=runner.run_started,
stopped=runner.run_stopped, stopped=runner.run_stopped,
mode=runner.run_mode, mode=runner.run_mode,
@ -463,6 +466,19 @@ def get_archived_runner_details_byID(id: UUID):
else: else:
return 0, res return 0, res
#returns b
def get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetime_object_to: datetime, timeframe: TimeFrame):
"""Returns Bar object
"""
try:
client = StockHistoricalDataClient(ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, raw_data=False)
#datetime_object_from = datetime(2023, 2, 27, 18, 51, 38, tzinfo=datetime.timezone.utc)
#datetime_object_to = datetime(2023, 2, 27, 21, 51, 39, tzinfo=datetime.timezone.utc)
bar_request = StockBarsRequest(symbol_or_symbols=symbol,timeframe=timeframe, start=datetime_object_from, end=datetime_object_to, feed=DataFeed.SIP)
bars = client.get_stock_bars(bar_request)
return 0, bars.data[symbol]
except Exception as e:
return -2, str(e)
# change_archived_runner # change_archived_runner
# delete_archived_runner_details # delete_archived_runner_details

View File

@ -2,6 +2,7 @@ import os,sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from v2realbot.enums.enums import Mode, Account from v2realbot.enums.enums import Mode, Account
from v2realbot.config import WEB_API_KEY from v2realbot.config import WEB_API_KEY
from alpaca.data.timeframe import TimeFrame, TimeFrameUnit
from datetime import datetime from datetime import datetime
#from icecream import install, ic #from icecream import install, ic
import os import os
@ -12,7 +13,7 @@ from fastapi.security import APIKeyHeader
import uvicorn import uvicorn
from uuid import UUID from uuid import UUID
import v2realbot.controller.services as cs import v2realbot.controller.services as cs
from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveDetail from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveDetail, Bar
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query
from fastapi.responses import HTMLResponse, FileResponse from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
@ -299,6 +300,15 @@ def _get_archived_runner_details_byID(runner_id) -> RunArchiveDetail:
else: else:
raise HTTPException(status_code=404, detail=f"No runner with id: {runner_id} a {set}") raise HTTPException(status_code=404, detail=f"No runner with id: {runner_id} a {set}")
#get alpaca history bars
@app.get("/history_bars/", dependencies=[Depends(api_key_auth)])
def _get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetime_object_to: datetime, timeframe_amount: int, timeframe_unit: TimeFrameUnit) -> list[Bar]:
res, set =cs.get_alpaca_history_bars(symbol, datetime_object_from, datetime_object_to, TimeFrame(amount=timeframe_amount,unit=timeframe_unit))
if res == 0:
return set
else:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found")
#join cekej na dokonceni vsech #join cekej na dokonceni vsech
for i in cs.db.runners: for i in cs.db.runners:

View File

@ -1,37 +1,57 @@
<!DOCTYPE html> <!doctype html>
<html> <html lang="en" data-bs-theme="light">
<head> <head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>V2realbot</title> <title>V2realbot</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static//favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/static//favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static//favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/static//favicon-16x16.png">
<link rel="manifest" href="/static/site.webmanifest"> <link rel="manifest" href="/static/site.webmanifest">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/dataTables.bootstrap5.min.css">
<!-- <script src="https://code.jquery.com/jquery-3.5.1.js"></script> -->
<script src="https://code.jquery.com/jquery-3.6.4.js" integrity="sha256-a9jBBRygX1Bh5lt8GZjXDzyOB+bWve9EiO7tROUtj/E=" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet"> <link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="/static/js/jquery.dataTables.min.js"></script> <script src="/static/js/jquery.dataTables.min.js"></script> -->
<link rel="stylesheet" href="/static/main.css"> <link rel="stylesheet" href="/static/main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/mousetrap/1.4.6/mousetrap.min.js"></script> <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="https://cdn.datatables.net/select/1.6.2/js/dataTables.select.min.js"></script> -->
</head> </head>
<body> <body>
<div id="main" class="mainConteiner flex-container"> <div id="main" class="mainConteiner flex-container content">
<div id="chartContainer" class="flex-items"> <div id="chartContainer" class="flex-items">
<label data-toggle="collapse" data-target="#chartContainerInner">Realtime chart</label> <label data-bs-toggle="collapse" data-bs-target="#chartContainerInner" aria-expanded="true">
<h5>Status: <span id="status">Not connected</span></h5> <h4><span class="badge secondary-bg">Chart</span></h4>
<div id="chartContainerInner" class="collapsed collapse in"> </label>
<div>Status: <span id="status">Not connected</span></div>
<div id="chartContainerInner" class="collapse">
<div id="formular"> <div id="formular">
<form action=""> <form action="">
<input type="text" id="runnerId" autocomplete="off" placeholder="StrategyID" value=""/> <input type="text" id="runnerId" autocomplete="off" placeholder="StrategyID" value=""/>
<button onclick="connect(event)" id="bt-conn" class="btn btn-success">Connect</button> <button onclick="connect(event)" id="bt-conn" class="btn btn-outline-success btn-sm">Connect</button>
<button onclick="disconnect(event)" id="bt-disc" style="display: None" class="btn btn-success">Disconnect</button> <button onclick="disconnect(event)" id="bt-disc" style="display: None" class="btn btn-outline-success btn-sm">Disconnect</button>
<!-- <label>Message: --> <input type="text" id="messageText" autocomplete="off" placeholder="WS out message"/> <!-- <label>Message: --> <input type="text" id="messageText" autocomplete="off" placeholder="WS out message"/>
<button onclick="sendMessage(event)" id="bt.send" class="btn btn-success">Send</button> <button onclick="sendMessage(event)" id="bt.send" class="btn btn-outline-success btn-sm">Send</button>
</form> </form>
</div> </div>
<div id="statusHeader" data-toggle="collapse" data-target="#statusStratvars"> <div id="statusHeader" data-bs-toggle="collapse" data-bs-target="#statusStratvars">
<div id="statusRegime" class="headerItem"></div> <div id="statusRegime" class="headerItem"></div>
<div id="statusName" class="headerItem"></div> <div id="statusName" class="headerItem"></div>
<div id="statusMode" class="headerItem"></div> <div id="statusMode" class="headerItem"></div>
@ -50,34 +70,40 @@
</div> </div>
<div id="hist-trades" class="flex-items"> <div id="hist-trades" class="flex-items">
<div id="form-trades"> <div id="form-trades">
<label data-toggle="collapse" data-target="#trades-data">Trade history</label> <label data-bs-toggle="collapse" data-bs-target="#trades-data">
<h4><span class="badge secondary-bg">Trade History</span></h4>
</label>
<label>Timestamp: <input type="text" id="trade-timestamp" autocomplete="off"/></label> <label>Timestamp: <input type="text" id="trade-timestamp" autocomplete="off"/></label>
<label>SYM: <input type="text" id="trade-symbol" autocomplete="off"/></label> <label>SYM: <input type="text" id="trade-symbol" autocomplete="off"/></label>
<label>Count: <input type="number" id="trade-count" autocomplete="off" value="2"/></label> <label>Count: <input type="number" id="trade-count" autocomplete="off" value="2"/></label>
<label>Minsize: <input type="number" id="trade-minsize" autocomplete="off" value="100"/></label> <label>Minsize: <input type="number" id="trade-minsize" autocomplete="off" value="100"/></label>
<label>Filter: C,O,4,B,7,V,P<input type="text" id="trade-filter" autocomplete="off"/></label> <label>Filter: C,O,4,B,7,V,P<input type="text" id="trade-filter" autocomplete="off"/></label>
<button id="bt-trade" class="btn btn-success">Show</button></div> <button id="bt-trade" class="btn btn-outline-success btn-sm">Show</button></div>
<div id="trades-data" style="display: none" class="collapse in"> <div id="trades-data" style="display: none" class="collapse show">
<table id="trades-data-table" class="display dataTable no-footer" style="width: 300px;display: contents;"></table> <table id="trades-data-table" class="dataTable no-footer" style="width:300px; border-color: #dce1dc; display:contents"></table>
<!-- <table id="trades-data-table" class="dataTable no-footer" style="width: 300px;display: contents;"></table> -->
</div> </div>
</div> </div>
<div id="runner-table" class="flex-items"> <div id="runner-table" class="flex-items">
<label data-toggle="collapse" data-target="#runner-table-inner">Running</label> <label data-bs-toggle="collapse" data-bs-target="#runner-table-inner">
<div id="runner-table-inner" class="collapsed"> <h4><span class="badge secondary-bg">Running Strategies</span></h4>
</label>
<div id="runner-table-inner" class="collapse show">
<div id="controls"> <div id="controls">
<label>API-KEY: <input type="password" id="api-key" autocomplete="off"/></label> <label>API-KEY: <input type="password" id="api-key" autocomplete="off"/></label>
<button onclick="store_api_key(event)" id="bt-store" class="btn btn-success">Store</button> <button onclick="store_api_key(event)" id="bt-store" class="btn btn-outline-success btn-sm">Store</button>
<button id="button_pause" class="btn btn-success">Pause/Unpause</button> <button id="button_pause" class="btn btn-outline-success btn-sm">Pause/Unpause</button>
<button id="button_stop" class="btn btn-success">Stop</button> <button id="button_stop" class="btn btn-outline-success btn-sm">Stop</button>
<button id="button_stopall" class="btn btn-success">Stop All</button> <button id="button_stopall" class="btn btn-outline-success btn-sm">Stop All</button>
<button id="button_refresh" class="btn btn-success">Refresh</button> <button id="button_refresh" class="btn btn-outline-success btn-sm">Refresh</button>
</div> </div>
<table id="runnerTable" class="display" style="width:100%"> <table id="runnerTable" class="table-striped table-bordered dataTable" style="width:100%; border-color: #dce1dc;">
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>Started</th> <th>Started</th>
<th>Mode</th> <th>Mode</th>
<th>Symbol</th>
<th>Account</th> <th>Account</th>
<th>Paused</th> <th>Paused</th>
<th>Profit</th> <th>Profit</th>
@ -94,18 +120,18 @@
<form method="post" id="stopForm"> <form method="post" id="stopForm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title"><i class="fa fa-plus"></i> Stop Strategy</h4>
<h4 class="modal-title_stop"><i class="fa fa-plus"></i> Stop Strategy</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="runnerid" class="control-label">Id</label> <label for="runnerid" class="form-label">Id</label>
<input type="text" class="form-control" id="runnerid" name="runnerid" placeholder="id"> <input type="text" class="form-control" id="runnerid" name="runnerid" placeholder="id">
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<input type="submit" name="stop" id="stop" class="btn btn-info" value="stop" /> <input type="submit" name="stop" id="stop" class="btn btn-primary" value="stop" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>
@ -114,23 +140,26 @@
</div> </div>
<div id="archive-table" class="flex-items"> <div id="archive-table" class="flex-items">
<label data-toggle="collapse" data-target="#archive-table-inner">Run Archive</label> <label data-bs-toggle="collapse" data-bs-target="#archive-table-inner">
<div id="archive-table-inner" class="collapsed"> <h4><span class="badge secondary-bg">Past Runs</span></h4>
</label>
<div id="archive-table-inner" class="collapse show">
<div id="archive-chart"> <div id="archive-chart">
<div id="chartArchive" style="position: relative;">BT chart</div> <div id="chartArchive" style="position: relative;"></div>
<div class="legend" id="legendArchive"></div> <div class="legend" id="legendArchive"></div>
</div> </div>
<div id="controls"> <div id="controls">
<button id="button_show_arch" class="btn btn-success">Show</button> <button id="button_show_arch" class="btn btn-outline-success btn-sm">Show</button>
<button id="button_delete_arch" class="btn btn-success">Delete</button> <button id="button_delete_arch" class="btn btn-outline-success btn-sm">Delete</button>
<!-- <button id="button_stopall" class="btn btn-success">Stop All</button> <!-- <button id="button_stopall" class="btn btn-outline-success btn-sm">Stop All</button>
<button id="button_refresh" class="btn btn-success">Refresh</button> --> <button id="button_refresh" class="btn btn-outline-success btn-sm">Refresh</button> -->
</div> </div>
<table id="archiveTable" class="display" style="width:100%"> <table id="archiveTable" class="table-striped table-bordered dataTable" style="width:100%; border-color: #dce1dc;">
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>Name</th> <th>Name</th>
<th>Symbol</th>
<th>Note</th> <th>Note</th>
<th>started</th> <th>started</th>
<th>stopped</th> <th>stopped</th>
@ -154,18 +183,18 @@
<form method="post" id="delFormArchive"> <form method="post" id="delFormArchive">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title"><i class="fa fa-plus"></i> Delete Archive</h4>
<h4 class="modal-title_del"><i class="fa fa-plus"></i> Delete Archive</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="delidarchive" class="control-label">Id</label> <label for="delidarchive" class="form-label">Id</label>
<input type="text" class="form-control" id="delidarchive" name="delidarchive" placeholder="id"> <input type="text" class="form-control" id="delidarchive" name="delidarchive" placeholder="id">
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<input type="submit" name="delete" id="deletearchive" class="btn btn-info" value="Delete" /> <input type="submit" name="delete" id="deletearchive" class="btn btn-primary" value="Delete" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>
@ -173,16 +202,18 @@
</div> </div>
</div> </div>
<div id="stratin-table" class="flex-items"> <div id="stratin-table" class="flex-items">
<label data-toggle="collapse" data-target="#stratin-table-inner">Strategies</label> <label data-bs-toggle="collapse" data-bs-target="#stratin-table-inner">
<div id="stratin-table-inner" class="collapsed"> <h4><span class="badge secondary-bg">Strategies</span></h4>
<button id="button_add" class="btn btn-success">Add</button> </label>
<button id="button_add_json" class="btn btn-success">Add JSON</button> <div id="stratin-table-inner" class="collapse show">
<button id="button_edit" class="btn btn-success">Edit</button> <button id="button_add" class="btn btn-outline-success btn-sm">Add</button>
<button id="button_dup" class="btn btn-success">Duplicate</button> <button id="button_add_json" class="btn btn-outline-success btn-sm">Add JSON</button>
<button id="button_copy" class="btn btn-success">Copy JSON</button> <button id="button_edit" class="btn btn-outline-success btn-sm">Edit</button>
<button id="button_delete" class="btn btn-success">Delete</button> <button id="button_dup" class="btn btn-outline-success btn-sm">Duplicate</button>
<button id="button_run" class="btn btn-success">Run Strategy</button> <button id="button_copy" class="btn btn-outline-success btn-sm">Copy JSON</button>
<table id="stratinTable" class="display" style="width:100%"> <button id="button_delete" class="btn btn-outline-success btn-sm">Delete</button>
<button id="button_run" class="btn btn-outline-success btn-sm">Run Strategy</button>
<table id="stratinTable" class="table-striped table-bordered dataTable" style="width:100%; border-color: #dce1dc;">
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
@ -209,64 +240,64 @@
<form method="post" id="recordForm"> <form method="post" id="recordForm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><i class="fa fa-plus"></i> Add Record</h4> <h4 class="modal-title"><i class="fa fa-plus"></i> Add Record</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="id" class="control-label">Id</label> <label for="id" class="form-label">Id</label>
<input type="text" class="form-control" id="id" name="id" placeholder="id" readonly> <input type="text" class="form-control" id="id" name="id" placeholder="id" readonly>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="id2" class="control-label">Id2</label> <label for="id2" class="form-label">Id2</label>
<input type="text" class="form-control" id="id2" name="id2" placeholder="id2" required> <input type="text" class="form-control" id="id2" name="id2" placeholder="id2" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="name" class="control-label">Name</label> <label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name" required> <input type="text" class="form-control" id="name" name="name" placeholder="Name" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="symbol" class="control-label">symbol</label> <label for="symbol" class="form-label">symbol</label>
<input type="text" class="form-control" id="symbol" name="symbol" placeholder="Symbol" required> <input type="text" class="form-control" id="symbol" name="symbol" placeholder="Symbol" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="class_name" class="control-label">class_name</label> <label for="class_name" class="form-label">class_name</label>
<input type="text" class="form-control" id="class_name" name="class_name" placeholder="class_name" required> <input type="text" class="form-control" id="class_name" name="class_name" placeholder="class_name" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="script" class="control-label">script</label> <label for="script" class="form-label">script</label>
<input type="text" class="form-control" id="script" name="script" placeholder="script" required> <input type="text" class="form-control" id="script" name="script" placeholder="script" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="open_rush" class="control-label">open_rush</label> <label for="open_rush" class="form-label">open_rush</label>
<input type="number" class="form-control" id="open_rush" name="open_rush" placeholder="open_rush" value=0 required> <input type="number" class="form-control" id="open_rush" name="open_rush" placeholder="open_rush" value=0 required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="close_rush" class="control-label">close_rush</label> <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> <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 class="form-group">
<label for="stratvars_conf" class="control-label">stratvars_conf</label> <label for="stratvars_conf" class="form-label">stratvars_conf</label>
<textarea class="form-control" rows="8" id="stratvars_conf" name="stratvars_conf" required></textarea> <textarea class="form-control" rows="8" id="stratvars_conf" name="stratvars_conf" required></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="add_data_conf" class="control-label">add_data_conf</label> <label for="add_data_conf" class="form-label">add_data_conf</label>
<textarea class="form-control" rows="7" id="add_data_conf" name="add_data_conf" required></textarea> <textarea class="form-control" rows="7" id="add_data_conf" name="add_data_conf" required></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="note" class="control-label">note</label> <label for="note" class="form-label">note</label>
<textarea class="form-control" rows="2" id="note" name="note"></textarea> <textarea class="form-control" rows="2" id="note" name="note"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="history" class="control-label">history</label> <label for="history" class="form-label">history</label>
<textarea class="form-control" rows="3" id="history" name="history"></textarea> <textarea class="form-control" rows="3" id="history" name="history"></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<!--<input type="hidden" name="id" id="id" />--> <!--<input type="hidden" name="id" id="id" />-->
<!--<input type="hidden" name="action" id="action" value="" />--> <!--<input type="hidden" name="action" id="action" value="" />-->
<input type="submit" name="save" id="save" class="btn btn-info" value="Save" /> <input type="submit" name="save" id="save" class="btn btn-primary" value="Save" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>
@ -277,18 +308,18 @@
<form method="post" id="delForm"> <form method="post" id="delForm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title_del"><i class="fa fa-plus"></i> Delete Record</h4> <h4 class="modal-title_del"><i class="fa fa-plus"></i> Delete Record</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="delid" class="control-label">Id</label> <label for="delid" class="form-label">Id</label>
<input type="text" class="form-control" id="delid" name="delid" placeholder="id"> <input type="text" class="form-control" id="delid" name="delid" placeholder="id">
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<input type="submit" name="delete" id="delete" class="btn btn-info" value="Delete" /> <input type="submit" name="delete" id="delete" class="btn btn-primary" value="Delete" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>
@ -299,18 +330,18 @@
<form method="post" id="jsonForm"> <form method="post" id="jsonForm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title_json"><i class="fa fa-plus"></i> Add JSON Record</h4> <h4 class="modal-title_json"><i class="fa fa-plus"></i> Add JSON Record</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="jsontext" class="control-label">JSON</label> <label for="jsontext" class="form-label">JSON</label>
<textarea class="form-control" rows="7" id="jsontext" name="jsontext" required></textarea> <textarea class="form-control" rows="7" id="jsontext" name="jsontext" required></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<input type="submit" name="json_add" id="json_add" class="btn btn-info" value="Add" /> <input type="submit" name="json_add" id="json_add" class="btn btn-primary" value="Add" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>
@ -321,49 +352,49 @@
<form method="post" id="runForm"> <form method="post" id="runForm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title_run"><i class="fa fa-plus"></i> Run strategy</h4> <h4 class="modal-title_run"><i class="fa fa-plus"></i> Run strategy</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label for="runid" class="control-label">Id</label> <label for="runid" class="form-label">Id</label>
<input type="text" class="form-control" id="runid" name="runid" placeholder="id" readonly> <input type="text" class="form-control" id="runid" name="runid" placeholder="id" readonly>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="mode" class="control-label">Mode</label> <label for="mode" class="form-label">Mode</label>
<select class="form-control" id="mode" name="mode"><option value="paper">paper</option><option value="live">live</option><option value="backtest">backtest</option></select> <select class="form-control" id="mode" name="mode"><option value="paper">paper</option><option value="live">live</option><option value="backtest">backtest</option></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="account" class="control-label">Account</label> <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> <select class="form-control" id="account" name="account"><option value="ACCOUNT1">ACCOUNT1</option><option value="ACCOUNT2">ACCOUNT2</option></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="debug" class="control-label">debug</label> <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> <select class="form-control" id="debug" name="debug"><option value="true">true</option><option value="false" selected>false</option></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="bt_from" class="control-label">bt_from</label> <label for="bt_from" class="form-label">bt_from</label>
<input type="datetime-local" class="form-control" id="bt_from" name="bt_from" placeholder="2023-04-06T09:00:00Z"> <input type="datetime-local" class="form-control" id="bt_from" name="bt_from" placeholder="2023-04-06T09:00:00Z">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="bt_to" class="control-label">bt_to</label> <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"> <input type="datetime-local" class="form-control" id="bt_to" name="bt_to" placeholder="2023-04-06T09:00:00Z">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="cash" class="control-label">cash</label> <label for="cash" class="form-label">cash</label>
<input type="number" class="form-control" id="cash" name="cash" placeholder="cash" value="100000"> <input type="number" class="form-control" id="cash" name="cash" placeholder="cash" value="100000">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="cash" class="control-label">Subscribe for RT</label> <label for="cash" class="form-label">Subscribe for RT</label>
<input type="checkbox" class="form-control" id="subscribe" name="subscribe"> <input type="checkbox" class="form-check-input mt-0" id="subscribe" name="subscribe" aria-label="Real time subscribe">
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<!--<input type="hidden" name="id" id="id" />--> <!--<input type="hidden" name="id" id="id" />-->
<!--<input type="hidden" name="action" id="action" value="" />--> <!--<input type="hidden" name="action" id="action" value="" />-->
<input type="submit" name="run" id="run" class="btn btn-info" value="Run" /> <input type="submit" name="run" id="run" class="btn btn-primary" value="Run" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -56,7 +56,8 @@ function transform_data(data) {
a_markers["position"] = "aboveBar" a_markers["position"] = "aboveBar"
a_markers["color"] = "#e8c76d" a_markers["color"] = "#e8c76d"
a_markers["shape"] = "arrowDown" a_markers["shape"] = "arrowDown"
a_markers["text"] = trade.position_qty + " " + parseFloat(trade.pos_avg_price).toFixed(3) // a_markers["text"] = trade.position_qty + " " + parseFloat(trade.pos_avg_price).toFixed(3)
a_markers["text"] = trade.position_qty
avgp_markers.push(a_markers) avgp_markers.push(a_markers)
} }
@ -68,7 +69,8 @@ function transform_data(data) {
marker["color"] = (trade.order.side == "buy") ? "blue" : "red" marker["color"] = (trade.order.side == "buy") ? "blue" : "red"
//marker["shape"] = (trade.order.side == "buy") ? "arrowUp" : "arrowDown" //marker["shape"] = (trade.order.side == "buy") ? "arrowUp" : "arrowDown"
marker["shape"] = (trade.order.side == "buy") ? "circle" : "arrowDown" marker["shape"] = (trade.order.side == "buy") ? "circle" : "arrowDown"
marker["text"] = trade.qty + " " + trade.price //marker["text"] = trade.qty + " " + trade.price
marker["text"] = trade.qty
markers.push(marker) markers.push(marker)
//prevedeme iso data na timestampy //prevedeme iso data na timestampy
@ -100,8 +102,48 @@ function transform_data(data) {
return transformed return transformed
} }
//unit: Min, Hour, Day, Week, Month
//prepare data before displaying archived chart - fetch history bars if necessary
function prepare_data(archRunner, timeframe_amount, timeframe_unit, archivedRunnerDetail) {
req = {}
req["symbol"] = archRunner.symbol
req["datetime_object_from"] = archRunner.bt_from
req["datetime_object_to"] = archRunner.bt_to
req["timeframe_amount"] = timeframe_amount
req["timeframe_unit"] = timeframe_unit
$.ajax({
url:"/history_bars/",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
data: req,
success:function(data){
//console.log("bars", JSON.stringify(data))
data.map((el)=>{
cas = new Date(el.timestamp)
el.time = cas.getTime()/1000;
delete el.timestamp
});
//console.log("bars_after_transformation", JSON.stringify(data))
oneMinuteBars = data
chart_archived_run(archRunner, archivedRunnerDetail, oneMinuteBars);
//call function to continue
//return data
//$("#statusStratvars").text(JSON.stringify(data.stratvars,null,2))
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
}
})
}
//render chart of archived runs //render chart of archived runs
function chart_archived_run(archRecord, data) { function chart_archived_run(archRecord, data, oneMinuteBars) {
if (chart !== null) { if (chart !== null) {
chart.remove() chart.remove()
clear_status_header() clear_status_header()
@ -109,32 +151,100 @@ function chart_archived_run(archRecord, data) {
toolTip.style.display = 'none'; toolTip.style.display = 'none';
} }
} }
//console.log("inside")
var transformed_data = transform_data(data) var transformed_data = transform_data(data)
//console.log(transformed_data)
//tbd transform indicators
//var markersData = transform_trades(data)
// time: datesForMarkers[i].time, //initialize resolutions
// position: 'aboveBar', var native_resolution = data.bars.resolution[0]+"s"
// color: '#e91e63', //console.log("native", native_resolution)
// shape: 'arrowDown',
// text: 'Sell @ ' + Math.floor(datesForMarkers[i].high + 2), //available intervals zatim jen 1m
document.getElementById("chart").style.display = "block" var intervals = [native_resolution, '1m'];
nativeData = transformed_data["bars"]
//get one minute data
//tbd prepare volume
//console.log("oneMinuteData",oneMinuteBars)
var AllCandleSeriesesData = new Map([
[native_resolution, nativeData ],
["1m", oneMinuteBars ],
]);
var switcherElement = createSimpleSwitcher(intervals, intervals[1], switch_to_interval);
//define tooltip
const container1 = document.getElementById('chart');
const toolTipWidth = 90;
const toolTipHeight = 90;
const toolTipMargin = 15;
// Create and style the tooltip html element
toolTip = document.createElement('div');
//width: 90px; , height: 80px;
toolTip.style = `position: absolute; display: none; padding: 8px; box-sizing: border-box; font-size: 12px; text-align: left; z-index: 1000; top: 12px; left: 12px; pointer-events: none; border: 1px solid; border-radius: 2px;font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;`;
toolTip.style.background = 'white';
toolTip.style.color = 'black';
toolTip.style.borderColor = '#2962FF';
container1.appendChild(toolTip);
//initialize chart //initialize chart
var chartOptions = { width: 1300, height: 600, leftPriceScale: {visible: true}} document.getElementById("chart").style.display = "block"
chart = LightweightCharts.createChart(document.getElementById('chart'), chartOptions);
var chartOptions = { width: 1300,
height: 600,
leftPriceScale: {visible: true},
layout: {
background: {
type: 'solid',
color: '#000000',
},
textColor: '#d1d4dc',
},
grid: {
vertLines: {
visible: true,
color: "#434d46"
},
horzLines: {
color: "#667069",
visible:true
},
},
}
chart = LightweightCharts.createChart(container1, chartOptions);
chart.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: { chart.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: {
mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true
}}) }})
var archCandlestickSeries = chart.addCandlestickSeries({ lastValueVisible: true, priceLineWidth:2, priceLineColor: "red", priceFormat: { type: 'price', precision: 2, minMove: 0.01 }});
archCandlestickSeries.priceScale().applyOptions({ container1.append(switcherElement)
scaleMargins: {
top: 0.1, // highest point of the series will be 10% away from the top var archCandlestickSeries = null
bottom: 0.4, // lowest point will be 40% away from the bottom
}, switch_to_interval(intervals[1])
}); chart.timeScale().fitContent();
function switch_to_interval(interval) {
//prip prenuti prepisujeme candlestick a markery
if (archCandlestickSeries) {
last_range = chart.timeScale().getVisibleRange()
chart.removeSeries(archCandlestickSeries);
archCandlestickSeries = null
}
else {
last_range = null
}
archCandlestickSeries = chart.addCandlestickSeries({ lastValueVisible: true, priceLineWidth:2, priceLineColor: "red", priceFormat: { type: 'price', precision: 2, minMove: 0.01 }});
archCandlestickSeries.priceScale().applyOptions({
scaleMargins: {
top: 0.1, // highest point of the series will be 10% away from the top
bottom: 0.4, // lowest point will be 40% away from the bottom
},
});
archCandlestickSeries.setData(AllCandleSeriesesData.get(interval));
if (last_range) {
chart.timeScale().setVisibleRange(last_range);
}
}
var archVwapSeries = chart.addLineSeries({ var archVwapSeries = chart.addLineSeries({
// title: "vwap", // title: "vwap",
@ -152,10 +262,6 @@ function chart_archived_run(archRecord, data) {
}, },
}); });
archVwapSeries.setData(transformed_data["vwap"])
archCandlestickSeries.setData(transformed_data["bars"])
archVolumeSeries.setData(transformed_data["volume"])
var avgBuyLine = chart.addLineSeries({ var avgBuyLine = chart.addLineSeries({
// title: "avgpbuyline", // title: "avgpbuyline",
@ -164,9 +270,7 @@ function chart_archived_run(archRecord, data) {
lineWidth: 1, lineWidth: 1,
lastValueVisible: false lastValueVisible: false
}); });
avgBuyLine.setData(transformed_data["avgp_buy_line"]); avgBuyLine.setData(transformed_data["avgp_buy_line"]);
avgBuyLine.setMarkers(transformed_data["avgp_markers"]) avgBuyLine.setMarkers(transformed_data["avgp_markers"])
var markersLine = chart.addLineSeries({ var markersLine = chart.addLineSeries({
@ -176,12 +280,7 @@ function chart_archived_run(archRecord, data) {
lineWidth: 1, lineWidth: 1,
lastValueVisible: false lastValueVisible: false
}); });
markersLine.setData(transformed_data["markers_line"]); markersLine.setData(transformed_data["markers_line"]);
//console.log("markers")
//console.log(transformed_data["markers"])
markersLine.setMarkers(transformed_data["markers"]) markersLine.setMarkers(transformed_data["markers"])
@ -199,21 +298,6 @@ function chart_archived_run(archRecord, data) {
// }); // });
//define tooltip
const container1 = document.getElementById('chart');
const toolTipWidth = 90;
const toolTipHeight = 90;
const toolTipMargin = 15;
// Create and style the tooltip html element
toolTip = document.createElement('div');
//width: 90px; , height: 80px;
toolTip.style = `position: absolute; display: none; padding: 8px; box-sizing: border-box; font-size: 12px; text-align: left; z-index: 1000; top: 12px; left: 12px; pointer-events: none; border: 1px solid; border-radius: 2px;font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;`;
toolTip.style.background = 'white';
toolTip.style.color = 'black';
toolTip.style.borderColor = '#2962FF';
container1.appendChild(toolTip);
//TODO onlick zkopirovat timestamp param.time //TODO onlick zkopirovat timestamp param.time
@ -223,7 +307,77 @@ function chart_archived_run(archRecord, data) {
// //console.log(param.hoveredObjectId); // //console.log(param.hoveredObjectId);
// }); // });
//TODO
// - legend
// - identifikatory
// - volume
//chart.subscribeCrosshairMove(param => { //chart.subscribeCrosshairMove(param => {
chart.subscribeCrosshairMove(param => {
//$('#trade-timestamp').val(param.time)
if (
param.point === undefined ||
!param.time ||
param.point.x < 0 ||
param.point.x > container1.clientWidth ||
param.point.y < 0 ||
param.point.y > container1.clientHeight
) {
toolTip.style.display = 'none';
} else {
//vyber serie s jakou chci pracovat - muzu i dynamicky
//je to mapa https://tradingview.github.io/lightweight-charts/docs/api/interfaces/MouseEventParams
//key = series (key.seriestype vraci Line/Candlestick atp.) https://tradingview.github.io/lightweight-charts/docs/api/interfaces/SeriesOptionsMap
toolTip.style.display = 'none';
toolTip.innerHTML = "";
var data = param.seriesData.get(markersLine);
var data2 = param.seriesData.get(avgBuyLine);
if ((data !== undefined) || (data2 !== undefined)) {
//param.seriesData.forEach((value, key) => {
//console.log("key",key)
//console.log("value",value)
//data = value
//DOCASNE VYPNUTO
toolTip.style.display = 'block';
//console.log(JSON.safeStringify(key))
// if (toolTip.innerHTML == "") {
// toolTip.innerHTML = `<div>${param.time}</div>`
// }
buy_price = 0
//u sell markeru nemame avgBuyLine
if (data2 !== undefined) {
buy_price = parseFloat(data2.value).toFixed(3)
}
toolTip.innerHTML += `<div>POS:${tradeDetails.get(param.time).position_qty}/${buy_price}</div><div>T:${tradeDetails.get(param.time).qty}/${data.value}</div>`;
//inspirace
// toolTip.innerHTML = `<div style="color: ${'#2962FF'}">Apple Inc.</div><div style="font-size: 24px; margin: 4px 0px; color: ${'black'}">
// ${Math.round(100 * price) / 100}
// </div><div style="color: ${'black'}">
// ${dateStr}
// </div>`;
// Position tooltip according to mouse cursor position
toolTip.style.left = param.point.x+120 + 'px';
toolTip.style.top = param.point.y + 'px';
}
//});
}
});
chart.subscribeClick(param => { chart.subscribeClick(param => {
$('#trade-timestamp').val(param.time) $('#trade-timestamp').val(param.time)
@ -288,8 +442,6 @@ function chart_archived_run(archRecord, data) {
$("#statusAccount").text(archRecord.account) $("#statusAccount").text(archRecord.account)
$("#statusStratvars").text(JSON.stringify(archRecord.stratvars,null,2)) $("#statusStratvars").text(JSON.stringify(archRecord.stratvars,null,2))
chart.timeScale().fitContent();
//TBD other dynamically created indicators //TBD other dynamically created indicators

View File

@ -43,9 +43,12 @@ $(document).ready(function () {
dataType: "json", dataType: "json",
success:function(data){ success:function(data){
$('#button_show_arch').attr('disabled',false); $('#button_show_arch').attr('disabled',false);
$('#chartContainerInner').addClass("show");
//$('#chartArchive').append(JSON.stringify(data,null,2)); //$('#chartArchive').append(JSON.stringify(data,null,2));
console.log(JSON.stringify(data,null,2)); console.log(JSON.stringify(data,null,2));
chart_archived_run(row, data); //if lower res is required call prepare_data otherwise call chart_archived_run()
//get other base resolutions
prepare_data(row, 1, "Min", data)
}, },
error: function(xhr, status, error) { error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")"); var err = eval("(" + xhr.responseText + ")");
@ -103,6 +106,7 @@ var archiveRecords =
}, },
columns: [{ data: 'id' }, columns: [{ data: 'id' },
{data: 'name'}, {data: 'name'},
{data: 'symbol'},
{data: 'note'}, {data: 'note'},
{data: 'started'}, {data: 'started'},
{data: 'stopped'}, {data: 'stopped'},
@ -118,12 +122,12 @@ var archiveRecords =
{data: 'open_orders', visible: true} {data: 'open_orders', visible: true}
], ],
columnDefs: [{ columnDefs: [{
targets: [3,4,7,8], targets: [4,5,8,9],
render: function ( data, type, row ) { render: function ( data, type, row ) {
return format_date(data) return format_date(data)
}, },
}], }],
order: [[4, 'desc']], order: [[5, 'desc']],
paging: true, paging: true,
lengthChange: false, lengthChange: false,
// createdRow: function( row, data, dataIndex){ // createdRow: function( row, data, dataIndex){

View File

@ -154,7 +154,7 @@ $(document).ready(function () {
bg = (findCommonElements3(filterList, tradeLine.conditions) || (parseInt(tradeLine.size) < minsize) ? 'style="background-color: #e6e6e6;"' : '') bg = (findCommonElements3(filterList, tradeLine.conditions) || (parseInt(tradeLine.size) < minsize) ? 'style="background-color: #e6e6e6;"' : '')
row += '<tr role="row" '+ ((timestamp == puvodni) ? 'class="highlighted"' : '') +' ' + bg + '><td>' + timestamp + '</td><td>' + tradeLine.price + '</td>' + row += '<tr role="row" '+ ((timestamp == puvodni) ? 'class="highlighted"' : '') +' ' + bg + '><td>' + timestamp + '</td><td>' + tradeLine.price + '</td>' +
'<td>' + tradeLine.size + '</td><td>' + tradeLine.id + '</td>' + '<td class="dt-center">' + tradeLine.size + '</td><td>' + tradeLine.id + '</td>' +
'<td>' + tradeLine.conditions + '</td><td>' + tradeLine.tape + '</td>' + '<td>' + tradeLine.conditions + '</td><td>' + tradeLine.tape + '</td>' +
'<td>' + tradeLine.timestamp + '</td></tr>'; '<td>' + tradeLine.timestamp + '</td></tr>';
@ -467,6 +467,7 @@ var runnerRecords =
columns: [{ data: 'id' }, columns: [{ data: 'id' },
{data: 'run_started'}, {data: 'run_started'},
{data: 'run_mode'}, {data: 'run_mode'},
{data: 'run_symbol'},
{data: 'run_account'}, {data: 'run_account'},
{data: 'run_paused'}, {data: 'run_paused'},
{data: 'run_profit'}, {data: 'run_profit'},

View File

@ -1,5 +1,4 @@
//it is called after population
function populate_real_time_chart() { function populate_real_time_chart() {
if (chart !== null) { if (chart !== null) {
@ -7,8 +6,30 @@ function populate_real_time_chart() {
clear_status_header(); clear_status_header();
} }
$('#chartContainerInner').addClass("show");
//const chartOptions = { layout: { textColor: 'black', background: { type: 'solid', color: 'white' } } }; //const chartOptions = { layout: { textColor: 'black', background: { type: 'solid', color: 'white' } } };
var chartOptions = { width: 1045, height: 600, leftPriceScale: {visible: true}} //var chartOptions = { width: 1045, height: 600, leftPriceScale: {visible: true}}
var chartOptions = { width: 1045,
height: 600,
leftPriceScale: {visible: true},
layout: {
background: {
type: 'solid',
color: '#000000',
},
textColor: '#d1d4dc',
},
grid: {
vertLines: {
visible: false,
},
horzLines: {
color: 'rgba(42, 46, 57, 0.5)',
},
},
}
chart = LightweightCharts.createChart(document.getElementById('chart'), chartOptions); chart = LightweightCharts.createChart(document.getElementById('chart'), chartOptions);
chart.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: { chart.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: {
mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true
@ -40,6 +61,8 @@ function populate_real_time_chart() {
//chart.timeScale().fitContent(); //chart.timeScale().fitContent();
//TBD unifikovat legendu
//TBD dynamicky zobrazovat vsechny indikatory //TBD dynamicky zobrazovat vsechny indikatory
//document.getElementById('chart').style.display = 'inline-block'; //document.getElementById('chart').style.display = 'inline-block';
var legendlist = document.getElementById('legend'); var legendlist = document.getElementById('legend');

View File

@ -2,6 +2,40 @@
API_KEY = localStorage.getItem("api-key") API_KEY = localStorage.getItem("api-key")
var chart = null var chart = null
//range switch pro chart https://jsfiddle.net/TradingView/qrb9a850/
function createSimpleSwitcher(items, activeItem, activeItemChangedCallback) {
var switcherElement = document.createElement('div');
switcherElement.classList.add('switcher');
var intervalElements = items.map(function(item) {
var itemEl = document.createElement('button');
itemEl.innerText = item;
itemEl.classList.add('switcher-item');
itemEl.classList.toggle('switcher-active-item', item === activeItem);
itemEl.addEventListener('click', function() {
onItemClicked(item);
});
switcherElement.appendChild(itemEl);
return itemEl;
});
function onItemClicked(item) {
if (item === activeItem) {
return;
}
intervalElements.forEach(function(element, index) {
element.classList.toggle('switcher-active-item', items[index] === item);
});
activeItem = item;
activeItemChangedCallback(item);
}
return switcherElement;
}
// safely handles circular references https://stackoverflow.com/questions/11616630/how-can-i-print-a-circular-structure-in-a-json-like-format // safely handles circular references https://stackoverflow.com/questions/11616630/how-can-i-print-a-circular-structure-in-a-json-like-format
JSON.safeStringify = (obj, indent = 2) => { JSON.safeStringify = (obj, indent = 2) => {
let cache = []; let cache = [];

View File

@ -1,3 +1,40 @@
:root {
--dt-row-selected: 18, 143, 175;
}
tbody, td, tfoot, th, thead, tr {
border-color: inherit;
border-style: solid;
border-width: 0;
padding: 4px;
}
.secondary-bg {
--bs-bg-opacity: 1;
background-color: #128faf;
}
.btn-outline-success {
--bs-btn-color: #316164;
--bs-btn-border-color: #247e85;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #3996a4;
--bs-btn-hover-border-color: #198754;
--bs-btn-focus-shadow-rgb: 25,135,84;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #40929d;
--bs-btn-active-border-color: #446379;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #697d81;
--bs-btn-disabled-bg: transparent;
--bs-btn-disabled-border-color: #839498;
--bs-gradient: none;
}
html {
font-size: 14px;
}
.flex-container { .flex-container {
display: inline-grid; display: inline-grid;
flex-direction: row; flex-direction: row;
@ -81,15 +118,19 @@ pre {
} }
#trades-data { #trades-data {
height: 350px; height: 40s0px;
overflow: auto; overflow: auto;
} }
#statusHeader { #statusHeader {
margin-left: 55px; margin-left: 0px;
font-size: normal; font-size: normal;
font-weight: bold; /* font-weight: bold; */
display: flex; display: -webkit-inline-box;
background-color: #128faf;
/* color: white; */
padding: 1px;
padding-left: 5px;
} }
.headerItem { .headerItem {
@ -103,6 +144,7 @@ pre {
.switcher { .switcher {
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 54px;
height: 30px; height: 30px;
margin-top: 8px; margin-top: 8px;
color: #2196F3; color: #2196F3;