rel profit first version
This commit is contained in:
@ -6,6 +6,7 @@ from uuid import UUID
|
||||
class TradeStatus(str, Enum):
|
||||
READY = "ready"
|
||||
ACTIVATED = "activated"
|
||||
CLOSED = "closed"
|
||||
#FINISHED = "finished"
|
||||
|
||||
class TradeDirection(str, Enum):
|
||||
@ -28,4 +29,6 @@ class Trade(BaseModel):
|
||||
stoploss_value: Optional[float] = None
|
||||
profit: Optional[float] = 0
|
||||
profit_sum: Optional[float] = 0
|
||||
rel_profit: Optional[float] = 0
|
||||
rel_profit_cum: Optional[float] = 0
|
||||
|
||||
|
||||
@ -79,7 +79,7 @@ def row_to_runarchiveview(row: dict) -> RunArchiveView:
|
||||
trade_count=int(row['trade_count']),
|
||||
end_positions=int(row['end_positions']),
|
||||
end_positions_avgp=float(row['end_positions_avgp']),
|
||||
metrics=json.loads(row['metrics']),
|
||||
metrics=json.loads(row['metrics']) if row['metrics'] else None
|
||||
)
|
||||
|
||||
#prevede dict radku zpatky na objekt vcetme retypizace
|
||||
|
||||
@ -191,6 +191,8 @@ class TradeUpdate(BaseModel):
|
||||
pos_avg_price: Optional[float]
|
||||
profit: Optional[float]
|
||||
profit_sum: Optional[float]
|
||||
rel_profit: Optional[float]
|
||||
rel_profit_cum: Optional[float]
|
||||
signal_name: Optional[str]
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ from alpaca.data.enums import DataFeed
|
||||
from alpaca.data.timeframe import TimeFrame
|
||||
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
||||
from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem
|
||||
from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
||||
from v2realbot.utils.utils import AttributeDict, zoneNY, zonePRG, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
||||
from v2realbot.utils.ilog import delete_logs
|
||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||
from datetime import datetime
|
||||
@ -21,6 +21,7 @@ from queue import Queue
|
||||
from tinydb import TinyDB, Query, where
|
||||
from tinydb.operations import set
|
||||
import json
|
||||
import numpy as np
|
||||
from numpy import ndarray
|
||||
from rich import print
|
||||
import pandas as pd
|
||||
@ -374,9 +375,10 @@ def run_batch_stratin(id: UUID, runReq: RunRequest):
|
||||
cal_list = []
|
||||
#interval dame do formatu list(RunDays)
|
||||
#TODO do budoucna predelat Interval na RunDays a na zone aware datetime
|
||||
#zatim testlisty dávám v cz casu
|
||||
for intrvl in testlist.dates:
|
||||
start_time = zoneNY.localize(datetime.fromisoformat(intrvl.start))
|
||||
end_time = zoneNY.localize(datetime.fromisoformat(intrvl.end))
|
||||
start_time = zonePRG.localize(datetime.fromisoformat(intrvl.start))
|
||||
end_time = zonePRG.localize(datetime.fromisoformat(intrvl.end))
|
||||
cal_list.append(RunDay(start = start_time, end = end_time, note=intrvl.note, id=testlist.id))
|
||||
|
||||
print(f"Getting intervals - RESULT ({len(cal_list)}): {cal_list}")
|
||||
@ -443,7 +445,7 @@ def batch_run_manager(id: UUID, runReq: RunRequest, rundays: list[RunDay]):
|
||||
cnt_max = len(rundays)
|
||||
cnt = 0
|
||||
#promenna pro sdileni mezi runy jednotlivych batchů (např. daily profit)
|
||||
inter_batch_params = dict(batch_profit=0)
|
||||
inter_batch_params = dict(batch_profit=0, batch_rel_profit=0)
|
||||
note_from_run_request = runReq.note
|
||||
for day in rundays:
|
||||
cnt += 1
|
||||
@ -636,6 +638,12 @@ def populate_metrics_output_directory(strat: StrategyInstance, inter_batch_param
|
||||
#naplneni batch sum profitu
|
||||
if inter_batch_params is not None:
|
||||
res["profit"]["batch_sum_profit"] = inter_batch_params["batch_profit"]
|
||||
res["profit"]["batch_sum_rel_profit"] = inter_batch_params["batch_rel_profit"]
|
||||
|
||||
#rel_profit rozepsane zisky
|
||||
res["profit"]["rel_profits"] = strat.state.rel_profit_cum
|
||||
#rel_profit zprumerovane
|
||||
res["profit"]["rel_profit_cum"] = float(np.mean(strat.state.rel_profit_cum)) if len(strat.state.rel_profit_cum) > 0 else 0
|
||||
|
||||
#metrikz z prescribedTrades, pokud existuji
|
||||
try:
|
||||
@ -691,8 +699,10 @@ def populate_metrics_output_directory(strat: StrategyInstance, inter_batch_param
|
||||
|
||||
mpt_string = "PT"+str(max_profit_time.hour)+":"+str(max_profit_time.minute) if max_profit_time is not None else ""
|
||||
mlt_string ="LT"+str(max_loss_time.hour)+":"+str(max_loss_time.minute) if max_loss_time is not None else ""
|
||||
rp_string = "RP" + str(float(np.mean(strat.state.rel_profit_cum))) if len(strat.state.rel_profit_cum) >0 else "noRP"
|
||||
|
||||
##summary pro rychle zobrazeni P333L-222 PT9:30 PL10:30
|
||||
res["profit"]["sum"]="P"+str(int(max_profit))+"L"+str(int(max_loss))+" "+ mpt_string+" " + mlt_string
|
||||
res["profit"]["sum"]="P"+str(int(max_profit))+"L"+str(int(max_loss))+" "+ mpt_string+" " + mlt_string + rp_string + " "+str(strat.state.rel_profit_cum)
|
||||
#vlozeni celeho listu
|
||||
res["prescr_trades"]=json.loads(json.dumps(strat.state.vars.prescribedTrades, default=json_serial))
|
||||
|
||||
@ -729,6 +739,8 @@ def archive_runner(runner: Runner, strat: StrategyInstance, inter_batch_params:
|
||||
#add profit of this batch iteration to batch_sum_profit
|
||||
if inter_batch_params is not None:
|
||||
inter_batch_params["batch_profit"] += round(float(strat.state.profit),2)
|
||||
inter_batch_params["batch_rel_profit"] += float(np.mean(strat.state.rel_profit_cum)) if len(strat.state.rel_profit_cum) > 0 else 0
|
||||
|
||||
|
||||
#WIP
|
||||
#populate result metrics dictionary (max drawdown etc.)
|
||||
|
||||
@ -710,7 +710,7 @@ var archiveRecords =
|
||||
//zobrazujeme jen kratkou summary pokud mame, jinak davame vse, do titlu davame vzdy vse
|
||||
//console.log(data)
|
||||
short = null
|
||||
if ((data.profit) && (data.profit.sum)) {
|
||||
if ((data) && (data.profit) && (data.profit.sum)) {
|
||||
short = data.profit.sum
|
||||
}
|
||||
else {
|
||||
|
||||
@ -28,7 +28,7 @@ Prism.languages.log = {
|
||||
alias: ['error', 'important']
|
||||
},
|
||||
{
|
||||
pattern: /\b(?:WARN|WARNING|WRN|ENTRY|LP|SL)\b/,
|
||||
pattern: /\b(?:WARN|WARNING|WRN|ENTRY|LP|SL|PROFIT|profit|profit_rel)\b/,
|
||||
alias: ['warning', 'important']
|
||||
},
|
||||
{
|
||||
|
||||
@ -12,7 +12,7 @@ from datetime import datetime
|
||||
#from rich import print
|
||||
from random import randrange
|
||||
from alpaca.common.exceptions import APIError
|
||||
import copy
|
||||
import numpy as np
|
||||
from threading import Event
|
||||
from uuid import UUID, uuid4
|
||||
from v2realbot.strategyblocks.indicators.indicators_hub import populate_all_indicators
|
||||
@ -100,7 +100,19 @@ class StrategyClassicSL(Strategy):
|
||||
|
||||
trade_profit = round((avg_costs-bought_amount),2)
|
||||
self.state.profit += trade_profit
|
||||
self.state.ilog(e=f"BUY notif - SHORT PROFIT:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)}", msg=str(data.event), bought_amount=bought_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
|
||||
|
||||
rel_profit = 0
|
||||
#spoctene celkovy relativni profit za trade v procentech ((trade_profit/vstup_naklady)*100)
|
||||
if vstup_cena != 0 and int(data.order.qty) != 0:
|
||||
rel_profit = (trade_profit / (vstup_cena * float(data.order.qty))) * 100
|
||||
|
||||
#pokud jde o finalni FILL - pridame do pole tento celkovy relativnich profit (ze ktereho se pocita kumulativni relativni profit)
|
||||
rel_profit_cum_calculated = 0
|
||||
if data.event == TradeEvent.FILL:
|
||||
self.state.rel_profit_cum.append(rel_profit)
|
||||
rel_profit_cum_calculated = np.mean(self.state.rel_profit_cum)
|
||||
|
||||
self.state.ilog(e=f"BUY notif - SHORT PROFIT:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)} rel:{float(rel_profit)} rel_cum:{round(rel_profit_cum_calculated,7)}", msg=str(data.event), rel_profit_cum=str(self.state.rel_profit_cum), bought_amount=bought_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
|
||||
|
||||
#zapsat profit do prescr.trades
|
||||
for trade in self.state.vars.prescribedTrades:
|
||||
@ -110,7 +122,11 @@ class StrategyClassicSL(Strategy):
|
||||
#pro ulozeni do tradeData scitame vsechen zisk z tohoto tradu (kvuli partialum)
|
||||
trade_profit = trade.profit
|
||||
trade.profit_sum = self.state.profit
|
||||
trade.rel_profit = rel_profit
|
||||
trade.rel_profit_cum = rel_profit_cum_calculated
|
||||
signal_name = trade.generated_by
|
||||
if data.event == TradeEvent.FILL:
|
||||
trade.status == TradeStatus.CLOSED
|
||||
break
|
||||
|
||||
if data.event == TradeEvent.FILL:
|
||||
@ -124,6 +140,8 @@ class StrategyClassicSL(Strategy):
|
||||
setattr(tradeData, "profit_sum", self.state.profit)
|
||||
setattr(tradeData, "signal_name", signal_name)
|
||||
#self.state.ilog(f"updatnut tradeList o profit", tradeData=json.loads(json.dumps(tradeData, default=json_serial)))
|
||||
setattr(tradeData, "rel_profit", rel_profit)
|
||||
setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated)
|
||||
|
||||
#test na maximalni profit/loss, pokud vypiname pak uz nedelame pripdany reverzal
|
||||
if await self.stop_when_max_profit_loss() is False:
|
||||
@ -142,7 +160,7 @@ class StrategyClassicSL(Strategy):
|
||||
if trade.id == self.state.vars.pending:
|
||||
signal_name = trade.generated_by
|
||||
|
||||
#zapsat update profitu do tradeList
|
||||
#zapsat do tradeList
|
||||
for tradeData in self.state.tradeList:
|
||||
if tradeData.execution_id == data.execution_id:
|
||||
setattr(tradeData, "signal_name", signal_name)
|
||||
@ -194,7 +212,19 @@ class StrategyClassicSL(Strategy):
|
||||
|
||||
trade_profit = round((sold_amount - avg_costs),2)
|
||||
self.state.profit += trade_profit
|
||||
self.state.ilog(e=f"SELL notif - PROFIT:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)}", msg=str(data.event), sold_amount=sold_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
|
||||
|
||||
rel_profit = 0
|
||||
#spoctene celkovy relativni profit za trade v procentech ((trade_profit/vstup_naklady)*100)
|
||||
if vstup_cena != 0 and data.order.qty != 0:
|
||||
rel_profit = (trade_profit / (vstup_cena * float(data.order.qty))) * 100
|
||||
|
||||
rel_profit_cum_calculated = 0
|
||||
#pokud jde o finalni FILL - pridame do pole relativnich profit (ze ktereho se pocita kumulativni relativni profit)
|
||||
if data.event == TradeEvent.FILL:
|
||||
self.state.rel_profit_cum.append(rel_profit)
|
||||
rel_profit_cum_calculated = np.mean(self.state.rel_profit_cum)
|
||||
|
||||
self.state.ilog(e=f"SELL notif - PROFIT:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)} rel:{float(rel_profit)} rel_cum:{round(rel_profit_cum_calculated,7)}", msg=str(data.event), rel_profit_cum = str(self.state.rel_profit_cum), sold_amount=sold_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
|
||||
|
||||
#zapsat profit do prescr.trades
|
||||
for trade in self.state.vars.prescribedTrades:
|
||||
@ -204,7 +234,11 @@ class StrategyClassicSL(Strategy):
|
||||
#pro ulozeni do tradeData scitame vsechen zisk z tohoto tradu (kvuli partialum)
|
||||
trade_profit = trade.profit
|
||||
trade.profit_sum = self.state.profit
|
||||
trade.rel_profit = rel_profit
|
||||
trade.rel_profit_cum = rel_profit_cum_calculated
|
||||
signal_name = trade.generated_by
|
||||
if data.event == TradeEvent.FILL:
|
||||
trade.status == TradeStatus.CLOSED
|
||||
break
|
||||
|
||||
if data.event == TradeEvent.FILL:
|
||||
@ -218,6 +252,9 @@ class StrategyClassicSL(Strategy):
|
||||
setattr(tradeData, "profit_sum", self.state.profit)
|
||||
setattr(tradeData, "signal_name", signal_name)
|
||||
#self.state.ilog(f"updatnut tradeList o profi {str(tradeData)}")
|
||||
setattr(tradeData, "rel_profit", rel_profit)
|
||||
setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated)
|
||||
#sem nejspis update skutecne vstupni ceny (celk.mnozstvi(order.qty) a avg_costs), to same i druhy smer
|
||||
|
||||
if await self.stop_when_max_profit_loss() is False:
|
||||
|
||||
|
||||
@ -705,7 +705,10 @@ class StrategyState:
|
||||
self.sell_l = self.interface.sell_l
|
||||
self.cancel_pending_buys = None
|
||||
self.iter_log_list = []
|
||||
#celkovy profit (prejmennovat na profit_cum)
|
||||
self.profit = 0
|
||||
#celkovy relativni profit (obsahuje pole relativnich zisku, z jeho meanu se spocita celkovy rel_profit_cu,)
|
||||
self.rel_profit_cum = []
|
||||
self.tradeList = []
|
||||
#nova promenna pro externi data do ArchiveDetaili, napr. pro zobrazeni v grafu, je zde např. SL history
|
||||
self.extData = {}
|
||||
|
||||
@ -53,9 +53,9 @@ def populate_all_indicators(data, state: StrategyState):
|
||||
state.ilog(lvl=1,e=f"{conf} {data['index']}-{conf_bar}--delta:{last_update_delta}---AVGdelta:{avg_delta}", data=data)
|
||||
|
||||
#TODO tento lof patri spis do nextu classic SL - je poplatny typu stratefie
|
||||
#TODO na toto se podivam, nejak moc zajasonovani a zpatky
|
||||
#TODO na toto se podivam, nejak moc zajasonovani a zpatky -
|
||||
#PERF PROBLEM
|
||||
state.ilog(lvl=1,e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} SL:{state.vars.activeTrade.stoploss_value if state.vars.activeTrade is not None else None} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} pend:{state.vars.pending}", activeTrade=json.loads(json.dumps(state.vars.activeTrade, default=json_serial)), prescribedTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)), pending=str(state.vars.pending))
|
||||
state.ilog(lvl=1,e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} SL:{state.vars.activeTrade.stoploss_value if state.vars.activeTrade is not None else None} profit:{round(float(state.profit),2)} profit_rel:{round(np.mean(state.rel_profit_cum),6) if len(state.rel_profit_cum)>0 else 0} Trades:{len(state.tradeList)} pend:{state.vars.pending}", rel_profit_cum=str(state.rel_profit_cum), activeTrade=json.loads(json.dumps(state.vars.activeTrade, default=json_serial)), prescribedTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)), pending=str(state.vars.pending))
|
||||
|
||||
#kroky pro CONFIRMED BAR only
|
||||
if conf_bar == 1:
|
||||
|
||||
@ -97,7 +97,7 @@ def common_go_preconditions_check(state, data, signalname: str, options: dict):
|
||||
window_close = safe_get(options, "window_close",safe_get(state.vars, "window_close",390))
|
||||
|
||||
if is_window_open(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), window_open, window_close) is False:
|
||||
state.ilog(lvl=1,e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{window_open=} {window_close=} ")
|
||||
state.ilog(lvl=1,e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{window_open=} {window_close=} ", time=str(datetime.fromtimestamp(data['updated']).astimezone(zoneNY)))
|
||||
return False
|
||||
|
||||
min_bar_index = safe_get(options, "min_bar_index",safe_get(state.vars, "min_bar_index",0))
|
||||
|
||||
@ -6,6 +6,7 @@ from datetime import datetime
|
||||
import json
|
||||
from v2realbot.strategyblocks.activetrade.helpers import insert_SL_history, get_default_sl_value, normalize_tick
|
||||
|
||||
#TODO nad prescribed trades postavit vstupni funkce
|
||||
def execute_prescribed_trades(state: StrategyState, data):
|
||||
##evaluate prescribed trade, prvni eligible presuneme do activeTrade, zmenime stav and vytvorime objednavky
|
||||
|
||||
|
||||
Reference in New Issue
Block a user