strategy trade counter, gui shortcuts, better log
This commit is contained in:
@ -4,7 +4,7 @@ from v2realbot.strategy.base import StrategyState
|
|||||||
from v2realbot.strategy.StrategyOrderLimitVykladaci import StrategyOrderLimitVykladaci
|
from v2realbot.strategy.StrategyOrderLimitVykladaci import StrategyOrderLimitVykladaci
|
||||||
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
||||||
from v2realbot.indicators.indicators import ema
|
from v2realbot.indicators.indicators import ema
|
||||||
from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, dict_replace_value, print
|
from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, dict_replace_value, print, safe_get
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from icecream import install, ic
|
from icecream import install, ic
|
||||||
#from rich import print
|
#from rich import print
|
||||||
@ -51,6 +51,7 @@ stratvars = AttributeDict(maxpozic = 400,
|
|||||||
slope_lookback = 300,
|
slope_lookback = 300,
|
||||||
lookback_offset = 20,
|
lookback_offset = 20,
|
||||||
minimum_slope = -0.05,
|
minimum_slope = -0.05,
|
||||||
|
first_buy_market = False
|
||||||
)
|
)
|
||||||
##toto rozparsovat a strategii spustit stejne jako v main
|
##toto rozparsovat a strategii spustit stejne jako v main
|
||||||
toml_string = """
|
toml_string = """
|
||||||
@ -129,7 +130,12 @@ def next(data, state: StrategyState):
|
|||||||
price = last_price
|
price = last_price
|
||||||
state.ilog(e="BUY Vykladame", msg="first price"+str(price) + "pozic:"+str(vykladka), curve=curve, ema=state.indicators.ema[-1], trend=state.vars.Trend, price=price, vykladka=vykladka)
|
state.ilog(e="BUY Vykladame", msg="first price"+str(price) + "pozic:"+str(vykladka), curve=curve, ema=state.indicators.ema[-1], trend=state.vars.Trend, price=price, vykladka=vykladka)
|
||||||
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
||||||
state.buy_l(price=price, size=qty)
|
|
||||||
|
##VAR - na zaklade conf. muzeme jako prvni posilat MARKET
|
||||||
|
if safe_get(state.vars, "first_buy_market") == True:
|
||||||
|
state.buy(size=qty)
|
||||||
|
else:
|
||||||
|
state.buy_l(price=price, size=qty)
|
||||||
print("prvni limitka na aktuální cenu. Další podle křivky", price, qty)
|
print("prvni limitka na aktuální cenu. Další podle křivky", price, qty)
|
||||||
for i in range(0,vykladka-1):
|
for i in range(0,vykladka-1):
|
||||||
price = price2dec(float(price - curve[i]))
|
price = price2dec(float(price - curve[i]))
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -43,8 +43,8 @@ from v2realbot.common.model import TradeUpdate, Order
|
|||||||
#from rich import print
|
#from rich import print
|
||||||
import threading
|
import threading
|
||||||
import asyncio
|
import asyncio
|
||||||
from v2realbot.config import BT_DELAYS, DATA_DIR, FILL_CONDITION_BUY_LIMIT, FILL_CONDITION_SELL_LIMIT, FILL_LOG_SURROUNDING_TRADES, FILL_CONS_TRADES_REQUIRED
|
from v2realbot.config import BT_DELAYS, DATA_DIR, BT_FILL_CONDITION_BUY_LIMIT, BT_FILL_CONDITION_SELL_LIMIT, BT_FILL_LOG_SURROUNDING_TRADES, BT_FILL_CONS_TRADES_REQUIRED
|
||||||
from v2realbot.utils.utils import AttributeDict, ltp, zoneNY, trunc, count_decimals,print
|
from v2realbot.utils.utils import AttributeDict, ltp, zoneNY, trunc, count_decimals, print
|
||||||
from v2realbot.utils.tlog import tlog
|
from v2realbot.utils.tlog import tlog
|
||||||
from v2realbot.enums.enums import FillCondition
|
from v2realbot.enums.enums import FillCondition
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@ -194,7 +194,7 @@ class Backtester:
|
|||||||
#TEST zkusime to nemazat, jak ovlivni performance
|
#TEST zkusime to nemazat, jak ovlivni performance
|
||||||
#Mazeme, jinak je to hruza
|
#Mazeme, jinak je to hruza
|
||||||
#nechavame na konci trady, které muzeme potrebovat pro consekutivni pravidlo
|
#nechavame na konci trady, které muzeme potrebovat pro consekutivni pravidlo
|
||||||
del self.btdata[0:index_end-2-FILL_CONS_TRADES_REQUIRED]
|
del self.btdata[0:index_end-2-BT_FILL_CONS_TRADES_REQUIRED]
|
||||||
#ic("after delete",len(self.btdata[0:index_end]))
|
#ic("after delete",len(self.btdata[0:index_end]))
|
||||||
|
|
||||||
if changes: return 1
|
if changes: return 1
|
||||||
@ -235,9 +235,9 @@ class Backtester:
|
|||||||
#NASTVENI PODMINEK PLNENI
|
#NASTVENI PODMINEK PLNENI
|
||||||
fast_fill_condition = i[1] <= o.limit_price
|
fast_fill_condition = i[1] <= o.limit_price
|
||||||
slow_fill_condition = i[1] < o.limit_price
|
slow_fill_condition = i[1] < o.limit_price
|
||||||
if FILL_CONDITION_BUY_LIMIT == FillCondition.FAST:
|
if BT_FILL_CONDITION_BUY_LIMIT == FillCondition.FAST:
|
||||||
fill_condition = fast_fill_condition
|
fill_condition = fast_fill_condition
|
||||||
elif FILL_CONDITION_BUY_LIMIT == FillCondition.SLOW:
|
elif BT_FILL_CONDITION_BUY_LIMIT == FillCondition.SLOW:
|
||||||
fill_condition = slow_fill_condition
|
fill_condition = slow_fill_condition
|
||||||
else:
|
else:
|
||||||
print("unknow fill condition")
|
print("unknow fill condition")
|
||||||
@ -245,17 +245,17 @@ class Backtester:
|
|||||||
|
|
||||||
if float(i[0]) > float(order_min_fill_time+BT_DELAYS.limit_order_offset) and fill_condition:
|
if float(i[0]) > float(order_min_fill_time+BT_DELAYS.limit_order_offset) and fill_condition:
|
||||||
consec_cnt += 1
|
consec_cnt += 1
|
||||||
if consec_cnt == FILL_CONS_TRADES_REQUIRED:
|
if consec_cnt == BT_FILL_CONS_TRADES_REQUIRED:
|
||||||
|
|
||||||
#(1679081919.381649, 27.88)
|
#(1679081919.381649, 27.88)
|
||||||
ic(i)
|
ic(i)
|
||||||
fill_time = i[0]
|
fill_time = i[0]
|
||||||
fill_price = i[1]
|
fill_price = i[1]
|
||||||
print("FILL LIMIT BUY at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
print("FILL LIMIT BUY at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
||||||
if FILL_LOG_SURROUNDING_TRADES != 0:
|
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
||||||
#TODO loguru
|
#TODO loguru
|
||||||
print("FILL SURR TRADES: before",work_range[index-FILL_LOG_SURROUNDING_TRADES:index])
|
print("FILL SURR TRADES: before",work_range[index-BT_FILL_LOG_SURROUNDING_TRADES:index])
|
||||||
print("FILL SURR TRADES: fill and after",work_range[index:index+FILL_LOG_SURROUNDING_TRADES])
|
print("FILL SURR TRADES: fill and after",work_range[index:index+BT_FILL_LOG_SURROUNDING_TRADES])
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
consec_cnt = 0
|
consec_cnt = 0
|
||||||
@ -266,9 +266,9 @@ class Backtester:
|
|||||||
#NASTVENI PODMINEK PLNENI
|
#NASTVENI PODMINEK PLNENI
|
||||||
fast_fill_condition = i[1] >= o.limit_price
|
fast_fill_condition = i[1] >= o.limit_price
|
||||||
slow_fill_condition = i[1] > o.limit_price
|
slow_fill_condition = i[1] > o.limit_price
|
||||||
if FILL_CONDITION_SELL_LIMIT == FillCondition.FAST:
|
if BT_FILL_CONDITION_SELL_LIMIT == FillCondition.FAST:
|
||||||
fill_condition = fast_fill_condition
|
fill_condition = fast_fill_condition
|
||||||
elif FILL_CONDITION_SELL_LIMIT == FillCondition.SLOW:
|
elif BT_FILL_CONDITION_SELL_LIMIT == FillCondition.SLOW:
|
||||||
fill_condition = slow_fill_condition
|
fill_condition = slow_fill_condition
|
||||||
else:
|
else:
|
||||||
print("unknown fill condition")
|
print("unknown fill condition")
|
||||||
@ -276,16 +276,16 @@ class Backtester:
|
|||||||
|
|
||||||
if float(i[0]) > float(order_min_fill_time+BT_DELAYS.limit_order_offset) and fill_condition:
|
if float(i[0]) > float(order_min_fill_time+BT_DELAYS.limit_order_offset) and fill_condition:
|
||||||
consec_cnt += 1
|
consec_cnt += 1
|
||||||
if consec_cnt == FILL_CONS_TRADES_REQUIRED:
|
if consec_cnt == BT_FILL_CONS_TRADES_REQUIRED:
|
||||||
#(1679081919.381649, 27.88)
|
#(1679081919.381649, 27.88)
|
||||||
ic(i)
|
ic(i)
|
||||||
fill_time = i[0]
|
fill_time = i[0]
|
||||||
fill_price = i[1]
|
fill_price = i[1]
|
||||||
print("FILL LIMIT SELL at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
print("FILL LIMIT SELL at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
|
||||||
if FILL_LOG_SURROUNDING_TRADES != 0:
|
if BT_FILL_LOG_SURROUNDING_TRADES != 0:
|
||||||
#TODO loguru
|
#TODO loguru
|
||||||
print("FILL SELL SURR TRADES: before",work_range[index-FILL_LOG_SURROUNDING_TRADES:index])
|
print("FILL SELL SURR TRADES: before",work_range[index-BT_FILL_LOG_SURROUNDING_TRADES:index])
|
||||||
print("FILL SELL SURR TRADES: fill and after",work_range[index:index+FILL_LOG_SURROUNDING_TRADES])
|
print("FILL SELL SURR TRADES: fill and after",work_range[index:index+BT_FILL_LOG_SURROUNDING_TRADES])
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
consec_cnt = 0
|
consec_cnt = 0
|
||||||
|
|||||||
@ -3,21 +3,21 @@ from v2realbot.enums.enums import Mode, Account, FillCondition
|
|||||||
from appdirs import user_data_dir
|
from appdirs import user_data_dir
|
||||||
|
|
||||||
|
|
||||||
#how many consecutive trades with the fill price are necessary for LIMIT fill to happen()
|
#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
|
||||||
#not impl.yet
|
#not impl.yet
|
||||||
#minimum is 1
|
#minimum is 1
|
||||||
FILL_CONS_TRADES_REQUIRED = 2
|
BT_FILL_CONS_TRADES_REQUIRED = 2
|
||||||
#during trade execution logs X-surrounding trades of the one that triggers the fill
|
#during bt trade execution logs X-surrounding trades of the one that triggers the fill
|
||||||
FILL_LOG_SURROUNDING_TRADES = 10
|
BT_FILL_LOG_SURROUNDING_TRADES = 10
|
||||||
#fill condition for limit order
|
#fill condition for limit order in bt
|
||||||
# fast - price has to be equal or bigger <=
|
# fast - price has to be equal or bigger <=
|
||||||
# slow - price has to be bigger <
|
# slow - price has to be bigger <
|
||||||
FILL_CONDITION_BUY_LIMIT = FillCondition.FAST
|
BT_FILL_CONDITION_BUY_LIMIT = FillCondition.FAST
|
||||||
FILL_CONDITION_SELL_LIMIT = FillCondition.FAST
|
BT_FILL_CONDITION_SELL_LIMIT = FillCondition.FAST
|
||||||
#no print in console
|
#no print in console
|
||||||
QUIET_MODE = False
|
QUIET_MODE = True
|
||||||
#backend counter of api requests
|
#backend counter of api requests
|
||||||
COUNT_API_REQUESTS = False
|
COUNT_API_REQUESTS = False
|
||||||
#stratvars that cannot be changed in gui
|
#stratvars that cannot be changed in gui
|
||||||
|
|||||||
@ -222,12 +222,13 @@ def save_history(id: UUID, st: object, runner: Runner, reason: str = None):
|
|||||||
#zkousime precist profit z objektu
|
#zkousime precist profit z objektu
|
||||||
try:
|
try:
|
||||||
profit = st.state.profit
|
profit = st.state.profit
|
||||||
|
trade_count = len(st.tradeList)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
profit = str(e)
|
profit = str(e)
|
||||||
|
|
||||||
for i in db.stratins:
|
for i in db.stratins:
|
||||||
if str(i.id) == str(id):
|
if str(i.id) == str(id):
|
||||||
i.history += "START:"+str(runner.run_started)+"STOP:"+str(runner.run_stopped)+"ACC:"+runner.run_account.value+"M:"+runner.run_mode.value+"PROFIT:"+str(profit)+ "REASON:" + str(reason)
|
i.history += "START:"+str(runner.run_started)+"STOP:"+str(runner.run_stopped)+"ACC:"+runner.run_account.value+"M:"+runner.run_mode.value+"PROFIT:"+str(round(profit,2))+ "TradeCNT:"+str(trade_count) + "REASON:" + str(reason)
|
||||||
#i.history += str(runner.__dict__)+"<BR>"
|
#i.history += str(runner.__dict__)+"<BR>"
|
||||||
db.save()
|
db.save()
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -12,6 +12,7 @@
|
|||||||
<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>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="main" class="mainConteiner flex-container">
|
<div id="main" class="mainConteiner flex-container">
|
||||||
|
|||||||
@ -1,6 +1,35 @@
|
|||||||
|
|
||||||
API_KEY = localStorage.getItem("api-key")
|
API_KEY = localStorage.getItem("api-key")
|
||||||
|
|
||||||
|
//KEY shortcuts
|
||||||
|
Mousetrap.bind('e', function() {
|
||||||
|
$( "#button_edit" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('a', function() {
|
||||||
|
$( "#button_add" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('d', function() {
|
||||||
|
$( "#button_dup" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('c', function() {
|
||||||
|
$( "#button_copy" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('r', function() {
|
||||||
|
$( "#button_run" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('p', function() {
|
||||||
|
$( "#button_pause" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('s', function() {
|
||||||
|
$( "#button_stop" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('j', function() {
|
||||||
|
$( "#button_add_json" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
Mousetrap.bind('x', function() {
|
||||||
|
$( "#button_delete" ).trigger( "click" );
|
||||||
|
});
|
||||||
|
|
||||||
//on button
|
//on button
|
||||||
function store_api_key(event) {
|
function store_api_key(event) {
|
||||||
key = document.getElementById("api-key").value;
|
key = document.getElementById("api-key").value;
|
||||||
|
|||||||
@ -62,7 +62,7 @@ function connect(event) {
|
|||||||
var lines = document.getElementById('lines')
|
var lines = document.getElementById('lines')
|
||||||
var line = document.createElement('div')
|
var line = document.createElement('div')
|
||||||
line.classList.add("line")
|
line.classList.add("line")
|
||||||
const newLine = document.createTextNode("-----------------NEXT ITER------------------")
|
const newLine = document.createTextNode("---------------")
|
||||||
line.appendChild(newLine)
|
line.appendChild(newLine)
|
||||||
lines.appendChild(line)
|
lines.appendChild(line)
|
||||||
|
|
||||||
@ -84,8 +84,7 @@ function connect(event) {
|
|||||||
logcnt++;
|
logcnt++;
|
||||||
row = '<div data-toggle="collapse" data-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ logLine.message+'</div>'
|
row = '<div data-toggle="collapse" data-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ logLine.message+'</div>'
|
||||||
str_row = JSON.stringify(logLine.details, null, 2)
|
str_row = JSON.stringify(logLine.details, null, 2)
|
||||||
|
row_detail = '<div id="rec'+logcnt+'" data-toggle="collapse" data-target="#rec'+logcnt+'"class="collapse pidi"><pre>' + str_row + '</pre></div>'
|
||||||
row_detail = '<div id="rec'+logcnt+'" class="collapse pidi"><pre>' + str_row + '</pre></div>'
|
|
||||||
|
|
||||||
var lines = document.getElementById('lines')
|
var lines = document.getElementById('lines')
|
||||||
var line = document.createElement('div')
|
var line = document.createElement('div')
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
from v2realbot.strategy.base import Strategy
|
from v2realbot.strategy.base import Strategy
|
||||||
from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print
|
from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial
|
||||||
from v2realbot.utils.tlog import tlog, tlog_exception
|
from v2realbot.utils.tlog import tlog, tlog_exception
|
||||||
from v2realbot.enums.enums import Mode, Order, Account
|
from v2realbot.enums.enums import Mode, Order, Account
|
||||||
from alpaca.trading.models import TradeUpdate
|
from alpaca.trading.models import TradeUpdate
|
||||||
from alpaca.trading.enums import TradeEvent, OrderStatus
|
from alpaca.trading.enums import TradeEvent, OrderStatus
|
||||||
from v2realbot.indicators.indicators import ema
|
from v2realbot.indicators.indicators import ema
|
||||||
|
import json
|
||||||
#from rich import print
|
#from rich import print
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from alpaca.common.exceptions import APIError
|
from alpaca.common.exceptions import APIError
|
||||||
@ -12,13 +13,15 @@ import copy
|
|||||||
from threading import Event
|
from threading import Event
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StrategyOrderLimitVykladaci(Strategy):
|
class StrategyOrderLimitVykladaci(Strategy):
|
||||||
def __init__(self, name: str, symbol: str, next: callable, init: callable, account: Account, mode: Mode = Mode.PAPER, stratvars: AttributeDict = None, open_rush: int = 30, close_rush: int = 30, pe: Event = None, se: Event = None) -> None:
|
def __init__(self, name: str, symbol: str, next: callable, init: callable, account: Account, mode: Mode = Mode.PAPER, stratvars: AttributeDict = None, open_rush: int = 30, close_rush: int = 30, pe: Event = None, se: Event = None) -> None:
|
||||||
super().__init__(name, symbol, next, init, account, mode, stratvars, open_rush, close_rush, pe, se)
|
super().__init__(name, symbol, next, init, account, mode, stratvars, open_rush, close_rush, pe, se)
|
||||||
|
|
||||||
async def orderUpdateBuy(self, data: TradeUpdate):
|
async def orderUpdateBuy(self, data: TradeUpdate):
|
||||||
o: Order = data.order
|
o: Order = data.order
|
||||||
self.state.ilog(e="Příchozí BUY notifikace", msg="order status:"+o.status, status=o.status, orderid=str(o.id))
|
##nejak to vymyslet, aby se dal poslat cely Trade a serializoval se
|
||||||
|
self.state.ilog(e="Příchozí BUY notifikace", msg="order status:"+o.status, trade=json.loads(json.dumps(data, default=json_serial)))
|
||||||
if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED:
|
if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED:
|
||||||
|
|
||||||
#pokud existuje objednavka v pendingbuys - vyhodime ji
|
#pokud existuje objednavka v pendingbuys - vyhodime ji
|
||||||
@ -68,6 +71,7 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
|
|
||||||
async def orderUpdateSell(self, data: TradeUpdate):
|
async def orderUpdateSell(self, data: TradeUpdate):
|
||||||
|
|
||||||
|
self.state.ilog(e="Příchozí SELL notifikace", msg="order status:"+data.order.status, trade=json.loads(json.dumps(data, default=json_serial)))
|
||||||
#PROFIT
|
#PROFIT
|
||||||
#profit pocitame z TradeUpdate.price a TradeUpdate.qty - aktualne provedene mnozstvi a cena
|
#profit pocitame z TradeUpdate.price a TradeUpdate.qty - aktualne provedene mnozstvi a cena
|
||||||
#naklady vypocteme z prumerne ceny, kterou mame v pozicich
|
#naklady vypocteme z prumerne ceny, kterou mame v pozicich
|
||||||
@ -117,19 +121,19 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
def buy(self, size = None, repeat: bool = False):
|
def buy(self, size = None, repeat: bool = False):
|
||||||
print("overriden method to size&check maximum ")
|
print("overriden method to size&check maximum ")
|
||||||
if int(self.state.positions) >= self.state.vars.maxpozic:
|
if int(self.state.positions) >= self.state.vars.maxpozic:
|
||||||
self.state.ilog(e="buy Maxim mnozstvi naplneno", curr_positions=self.state.positions)
|
self.state.ilog(e="buy Maxim mnozstvi naplneno", positions=self.state.positions)
|
||||||
print("max mnostvi naplneno")
|
print("max mnostvi naplneno")
|
||||||
return 0
|
return 0
|
||||||
if size is None:
|
if size is None:
|
||||||
sizer = self.state.vars.chunk
|
sizer = self.state.vars.chunk
|
||||||
else:
|
else:
|
||||||
sizer = size
|
sizer = size
|
||||||
|
|
||||||
self.state.blockbuy = 1
|
self.state.blockbuy = 1
|
||||||
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
|
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
|
||||||
ic(self.state.blockbuy)
|
self.state.ilog(e="send MARKET buy to if", msg="S:"+str(size), ltp=self.state.interface.get_last_price(self.state.symbol))
|
||||||
ic(self.state.vars.lastbuyindex)
|
|
||||||
return self.state.interface.buy(size=sizer)
|
return self.state.interface.buy(size=sizer)
|
||||||
|
|
||||||
def buy_l(self, price: float = None, size = None, repeat: bool = False):
|
def buy_l(self, price: float = None, size = None, repeat: bool = False):
|
||||||
print("entering overriden BUY")
|
print("entering overriden BUY")
|
||||||
if int(self.state.positions) >= self.state.vars.maxpozic:
|
if int(self.state.positions) >= self.state.vars.maxpozic:
|
||||||
@ -139,7 +143,7 @@ class StrategyOrderLimitVykladaci(Strategy):
|
|||||||
if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol)))
|
if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol)))
|
||||||
ic(price)
|
ic(price)
|
||||||
print("odesilame LIMIT s cenou/qty", price, size)
|
print("odesilame LIMIT s cenou/qty", price, size)
|
||||||
self.state.ilog(e="send buy to if", msg="S:"+str(size)+" P:"+str(price), price=price, size=size)
|
self.state.ilog(e="send LIMIT buy to if", msg="S:"+str(size)+" P:"+str(price), price=price, size=size)
|
||||||
order = self.state.interface.buy_l(price=price, size=size)
|
order = self.state.interface.buy_l(price=price, size=size)
|
||||||
print("ukladame pendingbuys")
|
print("ukladame pendingbuys")
|
||||||
self.state.vars.pendingbuys[str(order)]=price
|
self.state.vars.pendingbuys[str(order)]=price
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -17,6 +17,8 @@ from v2realbot.interfaces.backtest_interface import BacktestInterface
|
|||||||
from v2realbot.interfaces.live_interface import LiveInterface
|
from v2realbot.interfaces.live_interface import LiveInterface
|
||||||
from alpaca.trading.enums import OrderSide
|
from alpaca.trading.enums import OrderSide
|
||||||
from v2realbot.backtesting.backtester import Backtester
|
from v2realbot.backtesting.backtester import Backtester
|
||||||
|
from alpaca.trading.models import TradeUpdate
|
||||||
|
from alpaca.trading.enums import TradeEvent, OrderStatus
|
||||||
from threading import Event, current_thread
|
from threading import Event, current_thread
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -48,6 +50,7 @@ class Strategy:
|
|||||||
self.account = account
|
self.account = account
|
||||||
self.key = get_key(mode=self.mode, account=self.account)
|
self.key = get_key(mode=self.mode, account=self.account)
|
||||||
self.rtqueue = None
|
self.rtqueue = None
|
||||||
|
self.tradeList = []
|
||||||
|
|
||||||
|
|
||||||
#TODO predelat na dynamické queues
|
#TODO predelat na dynamické queues
|
||||||
@ -308,7 +311,7 @@ class Strategy:
|
|||||||
#for order updates from LIVE or BACKTEST
|
#for order updates from LIVE or BACKTEST
|
||||||
#updates are sent only for SYMBOL of strategy
|
#updates are sent only for SYMBOL of strategy
|
||||||
|
|
||||||
async def order_updates(self, data):
|
async def order_updates(self, data: TradeUpdate):
|
||||||
if self.mode == Mode.LIVE or self.mode == Mode.PAPER:
|
if self.mode == Mode.LIVE or self.mode == Mode.PAPER:
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
else:
|
else:
|
||||||
@ -316,10 +319,16 @@ class Strategy:
|
|||||||
|
|
||||||
print("NOTIFICATION ARRIVED AT:", now)
|
print("NOTIFICATION ARRIVED AT:", now)
|
||||||
|
|
||||||
|
#pokud jde o FILL zapisujeme do self.trades a notifikujeme
|
||||||
|
if data.event == TradeEvent.FILL:
|
||||||
|
self.tradeList.append(data)
|
||||||
|
|
||||||
##TradeUpdate objekt better?
|
##TradeUpdate objekt better?
|
||||||
order: Order = data.order
|
order: Order = data.order
|
||||||
if order.side == OrderSide.BUY: await self.orderUpdateBuy(data)
|
if order.side == OrderSide.BUY:
|
||||||
if order.side == OrderSide.SELL: await self.orderUpdateSell(data)
|
await self.orderUpdateBuy(data)
|
||||||
|
if order.side == OrderSide.SELL:
|
||||||
|
await self.orderUpdateSell(data)
|
||||||
|
|
||||||
async def orderUpdateBuy(self, data):
|
async def orderUpdateBuy(self, data):
|
||||||
print(data)
|
print(data)
|
||||||
|
|||||||
Binary file not shown.
@ -16,6 +16,24 @@ import tomli
|
|||||||
from v2realbot.config import DATA_DIR, QUIET_MODE
|
from v2realbot.config import DATA_DIR, QUIET_MODE
|
||||||
import requests
|
import requests
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
from enum import Enum
|
||||||
|
#from v2realbot.enums.enums import Order
|
||||||
|
from v2realbot.common.model import Order, TradeUpdate
|
||||||
|
|
||||||
|
def safe_get(collection, key, default=None):
|
||||||
|
"""Get values from a collection without raising errors"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return collection.get(key, default)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
return collection[key]
|
||||||
|
except (IndexError, TypeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
return default
|
||||||
|
|
||||||
def send_to_telegram(message):
|
def send_to_telegram(message):
|
||||||
apiToken = '5836666362:AAGPuzwp03tczMQTwTBiHW6VsZZ-1RCMAEE'
|
apiToken = '5836666362:AAGPuzwp03tczMQTwTBiHW6VsZZ-1RCMAEE'
|
||||||
@ -38,6 +56,12 @@ def json_serial(obj):
|
|||||||
return obj.timestamp()
|
return obj.timestamp()
|
||||||
if isinstance(obj, UUID):
|
if isinstance(obj, UUID):
|
||||||
return str(obj)
|
return str(obj)
|
||||||
|
if isinstance(obj, Enum):
|
||||||
|
return str(obj)
|
||||||
|
if type(obj) is Order:
|
||||||
|
return obj.__dict__
|
||||||
|
if type(obj) is TradeUpdate:
|
||||||
|
return obj.__dict__
|
||||||
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
||||||
|
|
||||||
def parse_toml_string(tomlst: str):
|
def parse_toml_string(tomlst: str):
|
||||||
|
|||||||
Reference in New Issue
Block a user