diff --git a/testy/archive/alpacagetlasttrades.py b/testy/archive/alpacagetlasttrades.py index 17c567b..04c4ba9 100644 --- a/testy/archive/alpacagetlasttrades.py +++ b/testy/archive/alpacagetlasttrades.py @@ -1,27 +1,35 @@ from alpaca.data.historical import CryptoHistoricalDataClient, StockHistoricalDataClient from alpaca.data.requests import CryptoLatestTradeRequest, StockLatestTradeRequest, StockLatestBarRequest, StockTradesRequest from alpaca.data.enums import DataFeed -from config import API_KEY, SECRET_KEY, MAX_BATCH_SIZE -import datetime +from v2realbot.config import ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY +from datetime import datetime import time +from v2realbot.utils.utils import zoneNY parametry = {} # no keys required #client = CryptoHistoricalDataClient() -client = StockHistoricalDataClient(API_KEY, SECRET_KEY, raw_data=True) +client = StockHistoricalDataClient(ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, raw_data=True) # single symbol request #request_trade_params = StockTradesRequest(symbol_or_symbols="BAC", feed = DataFeed.SIP) #request_last_bar_params = StockLatestBarRequest(symbol_or_symbols="BAC", feed=DataFeed.SIP) #2023, 2, 27, 18, 51, 38 - -datetime_object_from = datetime.datetime(2023, 2, 26, 17, 51, 38, tzinfo=datetime.timezone.utc) - -datetime_object_to = datetime.datetime(2023, 2, 28, 17, 51, 39, tzinfo=datetime.timezone.utc) - -trades_request = StockTradesRequest(symbol_or_symbols="C", feed = DataFeed.SIP, start=datetime_object_from, end=datetime_object_to) +client = StockHistoricalDataClient(ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, raw_data=False) +ted = datetime.now() +timstp=ted.timestamp() +print(f"{timstp=}") +datumfromtimestamp = datetime.fromtimestamp(timstp, zoneNY) +print(datumfromtimestamp) +datetime_object_from = datetime(2023, 4, 14, 15, 51, 38, tzinfo=zoneNY) +datetime_object_to = datetime(2023, 4, 14, 15, 51, 39, tzinfo=zoneNY) +# datetime_object_from = datetime.fromtimestamp(1682310012.024338) +# datetime_object_to = datetime.fromtimestamp(1682310015.024338) +print(datetime_object_from.timestamp()) +print(datetime_object_to.timestamp()) +trades_request = StockTradesRequest(symbol_or_symbols="BAC", feed = DataFeed.SIP, start=datetime_object_from, end=datetime_object_to) #latest_trade = client.get_stock_latest_trade(request_trade_params) #latest_bar = client.get_stock_latest_bar(request_last_bar_params) @@ -36,4 +44,17 @@ all_trades = client.get_stock_trades(trades_request) # print("last trade",latest_trade) # print("latest bar",latest_bar) # print("Trades Today", all_trades) -print(len(all_trades["C"])) +#print(len(all_trades["C"])) +#1682310012.024338 +print(all_trades["BAC"]) +# raw True +# [{'t': '2023-04-14T19:51:38.432128256Z', 'x': 'D', 'p': 49.805, 's': 100, 'c': [' '], 'i': 71696766285400, 'z': 'A'}, {'t': '2023-04-14T19:51:38.518662144Z', 'x': 'T', 'p': 49.8, 's': 9, 'c': [' ', 'I'], 'i': 62880002366518, 'z': 'A'}] +# raw False +# [{ 'conditions': [' '], +# 'exchange': 'D', +# 'id': 71696766285400, +# 'price': 49.805, +# 'size': 100.0, +# 'symbol': 'C', +# 'tape': 'A', +# 'timestamp': datetime.datetime(2023, 4, 14, 19, 51, 38, 432128, tzinfo=datetime.timezone.utc)}, ] \ No newline at end of file diff --git a/v2realbot/__pycache__/config.cpython-310.pyc b/v2realbot/__pycache__/config.cpython-310.pyc index 1981e06..ca1a39a 100644 Binary files a/v2realbot/__pycache__/config.cpython-310.pyc and b/v2realbot/__pycache__/config.cpython-310.pyc differ diff --git a/v2realbot/common/__pycache__/model.cpython-310.pyc b/v2realbot/common/__pycache__/model.cpython-310.pyc index 6663228..a47035e 100644 Binary files a/v2realbot/common/__pycache__/model.cpython-310.pyc and b/v2realbot/common/__pycache__/model.cpython-310.pyc differ diff --git a/v2realbot/common/model.py b/v2realbot/common/model.py index 0ca24ca..cac50ae 100644 --- a/v2realbot/common/model.py +++ b/v2realbot/common/model.py @@ -6,6 +6,7 @@ from typing import Any, Optional, List, Union from datetime import datetime, date from pydantic import BaseModel from v2realbot.enums.enums import Mode, Account +from alpaca.data.enums import Exchange #tu samou variantu pak UpdateStrategyInstanceWhileRunning @@ -23,6 +24,19 @@ from v2realbot.enums.enums import Mode, Account # return user.id # raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}") + +#for GUI +class Trade(BaseModel): + symbol: str + timestamp: datetime + exchange: Optional[Union[Exchange, str]] + price: float + size: float + id: int + conditions: Optional[List[str]] + tape: Optional[str] + + #persisted object in pickle class StrategyInstance(BaseModel): id: Optional[UUID | str | None] = None diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index 5886ef6..22dd025 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -1,12 +1,15 @@ 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.enums import DataFeed from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account from v2realbot.common.model import StrategyInstance, Runner, RunRequest from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string from datetime import datetime from threading import Thread, current_thread, Event, enumerate -from v2realbot.config import STRATVARS_UNCHANGEABLES +from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY import importlib from queue import Queue db = Store() @@ -352,3 +355,17 @@ def run_stratin(id: UUID, runReq: RunRequest): except Exception as e: return (-2, "Exception: "+str(e)) return (-2, "not found") + +def get_trade_history(symbol: str, timestamp_from: float, timestamp_to:float): + try: + datetime_object_from = datetime.fromtimestamp(timestamp_from, zoneNY) + datetime_object_to = datetime.fromtimestamp(timestamp_to, zoneNY) + #datetime_object_from = datetime(2023, 4, 14, 15, 51, 38, tzinfo=zoneNY) + #datetime_object_to = datetime(2023, 4, 14, 15, 51, 39, tzinfo=zoneNY) + client = StockHistoricalDataClient(ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, raw_data=False) + trades_request = StockTradesRequest(symbol_or_symbols=symbol, feed = DataFeed.SIP, start=datetime_object_from, end=datetime_object_to) + all_trades = client.get_stock_trades(trades_request) + #print(all_trades[symbol]) + return 0, all_trades[symbol] + except Exception as e: + return (-2, f"problem {e}") \ No newline at end of file diff --git a/v2realbot/main.py b/v2realbot/main.py index 83403ce..10b3b92 100644 --- a/v2realbot/main.py +++ b/v2realbot/main.py @@ -12,7 +12,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 +from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query from fastapi.responses import HTMLResponse, FileResponse from fastapi.staticfiles import StaticFiles @@ -254,6 +254,14 @@ def stop_all_stratins(): elif res < 0: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{id}") +@app.get("/tradehistory/{symbol}", dependencies=[Depends(api_key_auth)]) +def get_trade_history(symbol: str, timestamp_from: float, timestamp_to:float) -> list[Trade]: + res, set = cs.get_trade_history(symbol, timestamp_from, timestamp_to) + if res == 0: + return set + else: + raise HTTPException(status_code=404, detail=f"No trades found {res}") + #join cekej na dokonceni vsech for i in cs.db.runners: i.run_thread.join() diff --git a/v2realbot/static/index.html b/v2realbot/static/index.html index 4ee058a..3d8f445 100644 --- a/v2realbot/static/index.html +++ b/v2realbot/static/index.html @@ -36,7 +36,19 @@ - +
+
+ + + + + + +
+ +
diff --git a/v2realbot/static/js/mytables.js b/v2realbot/static/js/mytables.js index e594718..2552c99 100644 --- a/v2realbot/static/js/mytables.js +++ b/v2realbot/static/js/mytables.js @@ -1,6 +1,14 @@ API_KEY = localStorage.getItem("api-key") +// Iterate through each element in the +// first array and if some of them +// include the elements in the second +// array then return true. +function findCommonElements3(arr1, arr2) { +return arr1.some(item => arr2.includes(item)) +} + //KEY shortcuts Mousetrap.bind('e', function() { $( "#button_edit" ).trigger( "click" ); @@ -88,6 +96,13 @@ $(document).ready(function () { stratinRecords.ajax.reload(); runnerRecords.ajax.reload(); + $('#trade-timestamp').val(localStorage.getItem("trade_timestamp")); + $('#trade-count').val(localStorage.getItem("trade_count")); + $('#trade-symbol').val(localStorage.getItem("trade_symbol")); + $('#trade-minsize').val(localStorage.getItem("trade_minsize")); + $('#trade-filter').val(localStorage.getItem("trade_filter")); + + //disable buttons (enable on row selection) $('#button_pause').attr('disabled','disabled'); $('#button_stop').attr('disabled','disabled'); @@ -131,13 +146,86 @@ $(document).ready(function () { } }); + + //button get historical trades + $('#bt-trade').click(function () { + event.preventDefault(); + $('#bt-trade').attr('disabled','disabled'); + $( "#trades-data").addClass("in"); + + localStorage.setItem("trade_timestamp",$('#trade-timestamp').val()); + localStorage.setItem("trade_count",$('#trade-count').val()); + localStorage.setItem("trade_symbol",$('#trade-symbol').val()); + localStorage.setItem("trade_minsize",$('#trade-minsize').val()); + localStorage.setItem("trade_filter",$('#trade-filter').val()); + + const rec = new Object() + rec.timestamp_from = parseFloat($('#trade-timestamp').val())-parseInt($('#trade-count').val()) + rec.timestamp_to = parseFloat($('#trade-timestamp').val())+parseInt($('#trade-count').val()) + symbol = $('#trade-symbol').val() + //jsonString = JSON.stringify(rec); + //alert(JSON.stringify(rec)) + $.ajax({ + url:"/tradehistory/"+symbol+"/", + beforeSend: function (xhr) { + xhr.setRequestHeader('X-API-Key', + API_KEY); }, + method:"GET", + contentType: "application/json", + dataType: "json", + data: rec, + success:function(data){ + $('#bt-trade').attr('disabled', false); + $('#trades-data').show(); + //$('#trades-data').text("") + var minsize = parseInt($('#trade-minsize').val()); + //filter string to filter array + var valueInserted = $("#trade-filter").val(); // "tag1,tag2,tag3, "two words"" + var filterList = valueInserted.split(","); // ["tag1", "tag2", "tag3", "two words"] + for (var i in filterList) { + filterList[i] = filterList[i].trim(); + } + + console.log("filter list") + console.log(filterList) + console.log(minsize) + var row = "" + var puvodni = parseFloat($('#trade-timestamp').val()) + $('#trades-data-table').html(row); + data.forEach((tradeLine) => { + //console.log(JSON.stringify(tradeLine)) + date = new Date(tradeLine.timestamp) + timestamp = date.getTime()/1000 + + //trade contains filtered condition + bg = (findCommonElements3(filterList, tradeLine.conditions) ? 'style="background-color: #e6e6e6;"' : '') + + row += '' + timestamp + '' + tradeLine.price + '' + + '' + tradeLine.size + '' + tradeLine.id + '' + + '' + tradeLine.conditions + '' + tradeLine.tape + '' + + '' + tradeLine.timestamp + ''; + + }); + //console.log(row); + $('#trades-data-table').html(row); + // $('#trades-data').html(row) + }, + error: function(xhr, status, error) { + var err = eval("(" + xhr.responseText + ")"); + window.alert(JSON.stringify(xhr)); + console.log(JSON.stringify(xhr)); + $('#bt-trade').attr('disabled', false); + } + }) +}); + //button refresh $('#button_refresh').click(function () { runnerRecords.ajax.reload(); stratinRecords.ajax.reload(); }) - //button refresh + //button copy $('#button_copy').click(function () { event.preventDefault(); $('#button_copy').attr('disabled','disabled'); diff --git a/v2realbot/static/main.css b/v2realbot/static/main.css index 8421371..0a786e8 100644 --- a/v2realbot/static/main.css +++ b/v2realbot/static/main.css @@ -78,4 +78,9 @@ pre { .pidi { /* display: block; */ font-size: smaller; +} + +#trades-data { + height: 350px; + overflow: auto; } \ No newline at end of file