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.models import BarSet, QuoteSet, TradeSet
from alpaca.data.timeframe import TimeFrame
import mplfinance as mpf
# import mplfinance as mpf
import pandas as pd
from v2realbot.utils.utils import zoneNY
from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY
parametry = {}
# no keys required
#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_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'])
#print(bars.df.close)
bars = bars.tz_convert('America/New_York')
print(bars)
print(bars.df.columns)
#bars = bars.tz_convert('America/New_York')
print(bars.data["BAC"])
#print(bars.df.columns)
#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
type='candle', # use candlesticks
volume=True, # also show the volume
mav=(3,6,9), # use three different moving averages
figratio=(3,1), # set the ratio of the figure
style='yahoo', # choose the yahoo style
title='Prvni chart');
# mpf.plot(bars.df, # the dataframe containing the OHLC (Open, High, Low and Close) data
# type='candle', # use candlesticks
# volume=True, # also show the volume
# mav=(3,6,9), # use three different moving averages
# figratio=(3,1), # set the ratio of the figure
# style='yahoo', # choose the yahoo style
# title='Prvni chart');
# #vrací se list od dict
# print(bars["BAC"])

View File

@ -72,6 +72,7 @@ class RunnerView(BaseModel):
run_name: Optional[str] = None
run_note: Optional[str] = None
run_account: Account
run_symbol: Optional[str] = None
run_trade_count: Optional[int] = 0
run_profit: Optional[float] = 0
run_positions: Optional[int] = 0
@ -85,6 +86,7 @@ class Runner(BaseModel):
run_started: Optional[datetime] = None
run_mode: Mode
run_account: Account
run_symbol: Optional[str] = None
run_name: Optional[str] = None
run_note: Optional[str] = None
run_trade_count: Optional[int]
@ -98,6 +100,33 @@ class Runner(BaseModel):
run_pause_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):
id: UUID
submitted_at: datetime
@ -130,6 +159,7 @@ class RunArchive(BaseModel):
id: UUID
#id of running strategy (stratin/runner)
strat_id: UUID
symbol: str
name: str
note: Optional[str] = None
started: datetime

View File

@ -3,7 +3,7 @@ from v2realbot.enums.enums import Mode, Account, FillCondition
from appdirs import user_data_dir
#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
#0 - optimistic, every knot high will fill the order
#N - N consecutive trades required

View File

@ -2,8 +2,9 @@ from typing import Any, List
from uuid import UUID, uuid4
import pickle
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.timeframe import TimeFrame
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account
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
@ -365,6 +366,7 @@ def run_stratin(id: UUID, runReq: RunRequest):
run_started = datetime.now(zoneNY),
run_pause_ev = pe,
run_name = name,
run_symbol = symbol,
run_note = runReq.note,
run_stop_ev = se,
run_thread = vlakno,
@ -409,6 +411,7 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
strat_id = runner.id,
name=runner.run_name,
note=runner.run_note,
symbol=runner.run_symbol,
started=runner.run_started,
stopped=runner.run_stopped,
mode=runner.run_mode,
@ -463,6 +466,19 @@ def get_archived_runner_details_byID(id: UUID):
else:
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
# 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__))))
from v2realbot.enums.enums import Mode, Account
from v2realbot.config import WEB_API_KEY
from alpaca.data.timeframe import TimeFrame, TimeFrameUnit
from datetime import datetime
#from icecream import install, ic
import os
@ -12,7 +13,7 @@ from fastapi.security import APIKeyHeader
import uvicorn
from uuid import UUID
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.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
@ -299,6 +300,15 @@ def _get_archived_runner_details_byID(runner_id) -> RunArchiveDetail:
else:
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
for i in cs.db.runners:

View File

@ -1,37 +1,57 @@
<!DOCTYPE html>
<html>
<!doctype html>
<html lang="en" data-bs-theme="light">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>V2realbot</title>
<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="16x16" href="/static//favicon-16x16.png">
<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>
<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">
<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> -->
</head>
<body>
<div id="main" class="mainConteiner flex-container">
<div id="main" class="mainConteiner flex-container content">
<div id="chartContainer" class="flex-items">
<label data-toggle="collapse" data-target="#chartContainerInner">Realtime chart</label>
<h5>Status: <span id="status">Not connected</span></h5>
<div id="chartContainerInner" class="collapsed collapse in">
<label data-bs-toggle="collapse" data-bs-target="#chartContainerInner" aria-expanded="true">
<h4><span class="badge secondary-bg">Chart</span></h4>
</label>
<div>Status: <span id="status">Not connected</span></div>
<div id="chartContainerInner" class="collapse">
<div id="formular">
<form action="">
<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="disconnect(event)" id="bt-disc" style="display: None" class="btn btn-success">Disconnect</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-outline-success btn-sm">Disconnect</button>
<!-- <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>
</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="statusName" class="headerItem"></div>
<div id="statusMode" class="headerItem"></div>
@ -50,34 +70,40 @@
</div>
<div id="hist-trades" class="flex-items">
<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>SYM: <input type="text" id="trade-symbol" autocomplete="off"/></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>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>
<div id="trades-data" style="display: none" class="collapse in">
<table id="trades-data-table" class="display dataTable no-footer" style="width: 300px;display: contents;"></table>
<button id="bt-trade" class="btn btn-outline-success btn-sm">Show</button></div>
<div id="trades-data" style="display: none" class="collapse show">
<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 id="runner-table" class="flex-items">
<label data-toggle="collapse" data-target="#runner-table-inner">Running</label>
<div id="runner-table-inner" class="collapsed">
<label data-bs-toggle="collapse" data-bs-target="#runner-table-inner">
<h4><span class="badge secondary-bg">Running Strategies</span></h4>
</label>
<div id="runner-table-inner" class="collapse show">
<div id="controls">
<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 id="button_pause" class="btn btn-success">Pause/Unpause</button>
<button id="button_stop" class="btn btn-success">Stop</button>
<button id="button_stopall" class="btn btn-success">Stop All</button>
<button id="button_refresh" class="btn btn-success">Refresh</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-outline-success btn-sm">Pause/Unpause</button>
<button id="button_stop" class="btn btn-outline-success btn-sm">Stop</button>
<button id="button_stopall" class="btn btn-outline-success btn-sm">Stop All</button>
<button id="button_refresh" class="btn btn-outline-success btn-sm">Refresh</button>
</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>
<tr>
<th>Id</th>
<th>Started</th>
<th>Mode</th>
<th>Symbol</th>
<th>Account</th>
<th>Paused</th>
<th>Profit</th>
@ -94,18 +120,18 @@
<form method="post" id="stopForm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title_stop"><i class="fa fa-plus"></i> Stop Strategy</h4>
<h4 class="modal-title"><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 class="modal-body">
<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">
</div>
</div>
<div class="modal-footer">
<input type="submit" name="stop" id="stop" class="btn btn-info" value="stop" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="stop" id="stop" class="btn btn-primary" value="stop" />
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</form>
@ -114,23 +140,26 @@
</div>
<div id="archive-table" class="flex-items">
<label data-toggle="collapse" data-target="#archive-table-inner">Run Archive</label>
<div id="archive-table-inner" class="collapsed">
<label data-bs-toggle="collapse" data-bs-target="#archive-table-inner">
<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="chartArchive" style="position: relative;">BT chart</div>
<div id="chartArchive" style="position: relative;"></div>
<div class="legend" id="legendArchive"></div>
</div>
<div id="controls">
<button id="button_show_arch" class="btn btn-success">Show</button>
<button id="button_delete_arch" class="btn btn-success">Delete</button>
<!-- <button id="button_stopall" class="btn btn-success">Stop All</button>
<button id="button_refresh" class="btn btn-success">Refresh</button> -->
<button id="button_show_arch" class="btn btn-outline-success btn-sm">Show</button>
<button id="button_delete_arch" class="btn btn-outline-success btn-sm">Delete</button>
<!-- <button id="button_stopall" class="btn btn-outline-success btn-sm">Stop All</button>
<button id="button_refresh" class="btn btn-outline-success btn-sm">Refresh</button> -->
</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>
<tr>
<th>Id</th>
<th>Name</th>
<th>Symbol</th>
<th>Note</th>
<th>started</th>
<th>stopped</th>
@ -154,18 +183,18 @@
<form method="post" id="delFormArchive">
<div class="modal-content">
<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 Archive</h4>
<h4 class="modal-title"><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 class="modal-body">
<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">
</div>
</div>
<div class="modal-footer">
<input type="submit" name="delete" id="deletearchive" class="btn btn-info" value="Delete" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="delete" id="deletearchive" class="btn btn-primary" value="Delete" />
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>
@ -173,16 +202,18 @@
</div>
</div>
<div id="stratin-table" class="flex-items">
<label data-toggle="collapse" data-target="#stratin-table-inner">Strategies</label>
<div id="stratin-table-inner" class="collapsed">
<button id="button_add" class="btn btn-success">Add</button>
<button id="button_add_json" class="btn btn-success">Add JSON</button>
<button id="button_edit" class="btn btn-success">Edit</button>
<button id="button_dup" class="btn btn-success">Duplicate</button>
<button id="button_copy" class="btn btn-success">Copy JSON</button>
<button id="button_delete" class="btn btn-success">Delete</button>
<button id="button_run" class="btn btn-success">Run Strategy</button>
<table id="stratinTable" class="display" style="width:100%">
<label data-bs-toggle="collapse" data-bs-target="#stratin-table-inner">
<h4><span class="badge secondary-bg">Strategies</span></h4>
</label>
<div id="stratin-table-inner" class="collapse show">
<button id="button_add" class="btn btn-outline-success btn-sm">Add</button>
<button id="button_add_json" class="btn btn-outline-success btn-sm">Add JSON</button>
<button id="button_edit" class="btn btn-outline-success btn-sm">Edit</button>
<button id="button_dup" class="btn btn-outline-success btn-sm">Duplicate</button>
<button id="button_copy" class="btn btn-outline-success btn-sm">Copy JSON</button>
<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>
<tr>
<th>Id</th>
@ -209,64 +240,64 @@
<form method="post" id="recordForm">
<div class="modal-content">
<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>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
</div>
<div class="modal-footer">
<!--<input type="hidden" name="id" id="id" />-->
<!--<input type="hidden" name="action" id="action" value="" />-->
<input type="submit" name="save" id="save" class="btn btn-info" value="Save" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="save" id="save" class="btn btn-primary" value="Save" />
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>
@ -277,18 +308,18 @@
<form method="post" id="delForm">
<div class="modal-content">
<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>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<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">
</div>
</div>
<div class="modal-footer">
<input type="submit" name="delete" id="delete" class="btn btn-info" value="Delete" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="delete" id="delete" class="btn btn-primary" value="Delete" />
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>
@ -299,18 +330,18 @@
<form method="post" id="jsonForm">
<div class="modal-content">
<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>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<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>
</div>
</div>
<div class="modal-footer">
<input type="submit" name="json_add" id="json_add" class="btn btn-info" value="Add" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="json_add" id="json_add" class="btn btn-primary" value="Add" />
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>
@ -321,49 +352,49 @@
<form method="post" id="runForm">
<div class="modal-content">
<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>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<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>
</div>
<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>
</div>
<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>
</div>
<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>
</div>
<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">
</div>
<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">
</div>
<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">
</div>
<div class="form-group">
<label for="cash" class="control-label">Subscribe for RT</label>
<input type="checkbox" class="form-control" id="subscribe" name="subscribe">
<label for="cash" class="form-label">Subscribe for RT</label>
<input type="checkbox" class="form-check-input mt-0" id="subscribe" name="subscribe" aria-label="Real time subscribe">
</div>
</div>
<div class="modal-footer">
<!--<input type="hidden" name="id" id="id" />-->
<!--<input type="hidden" name="action" id="action" value="" />-->
<input type="submit" name="run" id="run" class="btn btn-info" value="Run" />
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" name="run" id="run" class="btn btn-primary" value="Run" />
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</form>

View File

@ -56,7 +56,8 @@ function transform_data(data) {
a_markers["position"] = "aboveBar"
a_markers["color"] = "#e8c76d"
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)
}
@ -68,7 +69,8 @@ function transform_data(data) {
marker["color"] = (trade.order.side == "buy") ? "blue" : "red"
//marker["shape"] = (trade.order.side == "buy") ? "arrowUp" : "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)
//prevedeme iso data na timestampy
@ -100,8 +102,48 @@ function transform_data(data) {
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
function chart_archived_run(archRecord, data) {
function chart_archived_run(archRecord, data, oneMinuteBars) {
if (chart !== null) {
chart.remove()
clear_status_header()
@ -109,32 +151,100 @@ function chart_archived_run(archRecord, data) {
toolTip.style.display = 'none';
}
}
//console.log("inside")
var transformed_data = transform_data(data)
//console.log(transformed_data)
//tbd transform indicators
//var markersData = transform_trades(data)
// time: datesForMarkers[i].time,
// position: 'aboveBar',
// color: '#e91e63',
// shape: 'arrowDown',
// text: 'Sell @ ' + Math.floor(datesForMarkers[i].high + 2),
document.getElementById("chart").style.display = "block"
//initialize resolutions
var native_resolution = data.bars.resolution[0]+"s"
//console.log("native", native_resolution)
//available intervals zatim jen 1m
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
var chartOptions = { width: 1300, height: 600, leftPriceScale: {visible: true}}
chart = LightweightCharts.createChart(document.getElementById('chart'), chartOptions);
document.getElementById("chart").style.display = "block"
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: {
mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true
}})
var archCandlestickSeries = chart.addCandlestickSeries({ lastValueVisible: true, priceLineWidth:2, priceLineColor: "red", priceFormat: { type: 'price', precision: 2, minMove: 0.01 }});
container1.append(switcherElement)
var archCandlestickSeries = null
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({
// 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({
// title: "avgpbuyline",
@ -164,9 +270,7 @@ function chart_archived_run(archRecord, data) {
lineWidth: 1,
lastValueVisible: false
});
avgBuyLine.setData(transformed_data["avgp_buy_line"]);
avgBuyLine.setMarkers(transformed_data["avgp_markers"])
var markersLine = chart.addLineSeries({
@ -176,12 +280,7 @@ function chart_archived_run(archRecord, data) {
lineWidth: 1,
lastValueVisible: false
});
markersLine.setData(transformed_data["markers_line"]);
//console.log("markers")
//console.log(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
@ -223,7 +307,77 @@ function chart_archived_run(archRecord, data) {
// //console.log(param.hoveredObjectId);
// });
//TODO
// - legend
// - identifikatory
// - volume
//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 => {
$('#trade-timestamp').val(param.time)
@ -289,8 +443,6 @@ function chart_archived_run(archRecord, data) {
$("#statusStratvars").text(JSON.stringify(archRecord.stratvars,null,2))
chart.timeScale().fitContent();
//TBD other dynamically created indicators
}

View File

@ -43,9 +43,12 @@ $(document).ready(function () {
dataType: "json",
success:function(data){
$('#button_show_arch').attr('disabled',false);
$('#chartContainerInner').addClass("show");
//$('#chartArchive').append(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) {
var err = eval("(" + xhr.responseText + ")");
@ -103,6 +106,7 @@ var archiveRecords =
},
columns: [{ data: 'id' },
{data: 'name'},
{data: 'symbol'},
{data: 'note'},
{data: 'started'},
{data: 'stopped'},
@ -118,12 +122,12 @@ var archiveRecords =
{data: 'open_orders', visible: true}
],
columnDefs: [{
targets: [3,4,7,8],
targets: [4,5,8,9],
render: function ( data, type, row ) {
return format_date(data)
},
}],
order: [[4, 'desc']],
order: [[5, 'desc']],
paging: true,
lengthChange: false,
// 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;"' : '')
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.timestamp + '</td></tr>';
@ -467,6 +467,7 @@ var runnerRecords =
columns: [{ data: 'id' },
{data: 'run_started'},
{data: 'run_mode'},
{data: 'run_symbol'},
{data: 'run_account'},
{data: 'run_paused'},
{data: 'run_profit'},

View File

@ -1,5 +1,4 @@
//it is called after population
function populate_real_time_chart() {
if (chart !== null) {
@ -7,8 +6,30 @@ function populate_real_time_chart() {
clear_status_header();
}
$('#chartContainerInner').addClass("show");
//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.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: {
mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true
@ -40,6 +61,8 @@ function populate_real_time_chart() {
//chart.timeScale().fitContent();
//TBD unifikovat legendu
//TBD dynamicky zobrazovat vsechny indikatory
//document.getElementById('chart').style.display = 'inline-block';
var legendlist = document.getElementById('legend');

View File

@ -2,6 +2,40 @@
API_KEY = localStorage.getItem("api-key")
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
JSON.safeStringify = (obj, indent = 2) => {
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 {
display: inline-grid;
flex-direction: row;
@ -81,15 +118,19 @@ pre {
}
#trades-data {
height: 350px;
height: 40s0px;
overflow: auto;
}
#statusHeader {
margin-left: 55px;
margin-left: 0px;
font-size: normal;
font-weight: bold;
display: flex;
/* font-weight: bold; */
display: -webkit-inline-box;
background-color: #128faf;
/* color: white; */
padding: 1px;
padding-left: 5px;
}
.headerItem {
@ -103,6 +144,7 @@ pre {
.switcher {
display: flex;
align-items: center;
margin-left: 54px;
height: 30px;
margin-top: 8px;
color: #2196F3;