enables day by day bt run, bt market premium+inds
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@ -43,3 +43,12 @@ v2realbot/__pycache__/config.cpython-310.pyc
|
||||
.gitignore
|
||||
v2realbot/enums/__pycache__/enums.cpython-310.pyc
|
||||
v2realbot/common/__pycache__/model.cpython-310.pyc
|
||||
v2realbot/__pycache__/config.cpython-310.pyc
|
||||
v2realbot/backtesting/__pycache__/backtester.cpython-310.pyc
|
||||
v2realbot/common/__pycache__/model.cpython-310.pyc
|
||||
v2realbot/enums/__pycache__/enums.cpython-310.pyc
|
||||
v2realbot/indicators/__pycache__/indicators.cpython-310.pyc
|
||||
v2realbot/loader/__pycache__/aggregator.cpython-310.pyc
|
||||
v2realbot/loader/__pycache__/trade_offline_streamer.cpython-310.pyc
|
||||
v2realbot/loader/__pycache__/trade_ws_streamer.cpython-310.pyc
|
||||
v2realbot/strategy/__pycache__/base.cpython-310.pyc
|
||||
|
||||
18
testy/funkce.py
Normal file
18
testy/funkce.py
Normal file
@ -0,0 +1,18 @@
|
||||
# import os
|
||||
|
||||
# for filename in os.listdir("v2realbot/strategyblocks/indicators/custom"):
|
||||
# print(filename)
|
||||
|
||||
import os
|
||||
import importlib
|
||||
import v2realbot.strategyblocks.indicators.custom as ci
|
||||
|
||||
ci.opengap.opengap()
|
||||
|
||||
# for filename in os.listdir("v2realbot/strategyblocks/indicators/custom"):
|
||||
# if filename.endswith(".py") and filename != "__init__.py":
|
||||
# # __import__(filename[:-3])
|
||||
# #__import__(f"v2realbot.strategyblocks.indicators.custom.{filename[:-3]}")
|
||||
# __import__(f"{filename[:-3]}")
|
||||
# #importlib.import_module()
|
||||
|
||||
@ -43,7 +43,7 @@ from v2realbot.common.model import TradeUpdate, Order
|
||||
#from rich import print
|
||||
import threading
|
||||
import asyncio
|
||||
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.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,BT_FILL_PRICE_MARKET_ORDER_PREMIUM
|
||||
from v2realbot.utils.utils import AttributeDict, ltp, zoneNY, trunc, count_decimals, print
|
||||
from v2realbot.utils.tlog import tlog
|
||||
from v2realbot.enums.enums import FillCondition
|
||||
@ -311,6 +311,12 @@ class Backtester:
|
||||
#ic(i)
|
||||
fill_time = i[0]
|
||||
fill_price = i[1]
|
||||
#přičteme MARKET PREMIUM z konfigurace (do budoucna mozna rozdilne pro BUY/SELL a nebo mozna z konfigurace pro dany itutl)
|
||||
if o.side == OrderSide.BUY:
|
||||
fill_price = fill_price + BT_FILL_PRICE_MARKET_ORDER_PREMIUM
|
||||
elif o.side == OrderSide.SELL:
|
||||
fill_price = fill_price - BT_FILL_PRICE_MARKET_ORDER_PREMIUM
|
||||
|
||||
print("FILL ",o.side,"MARKET at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "cena", i[1])
|
||||
break
|
||||
else:
|
||||
|
||||
@ -2,7 +2,7 @@ from v2realbot.config import DATA_DIR
|
||||
import sqlite3
|
||||
import queue
|
||||
import threading
|
||||
from datetime import time
|
||||
import time
|
||||
|
||||
sqlite_db_file = DATA_DIR + "/v2trading.db"
|
||||
# Define the connection pool
|
||||
@ -44,6 +44,7 @@ def execute_with_retry(cursor: sqlite3.Cursor, statement: str, retry_interval: i
|
||||
return cursor.execute(statement)
|
||||
except sqlite3.OperationalError as e:
|
||||
if str(e) == "database is locked":
|
||||
print("database retry in 1s." + str(e))
|
||||
time.sleep(retry_interval)
|
||||
continue
|
||||
else:
|
||||
|
||||
@ -24,6 +24,15 @@ from alpaca.data.enums import Exchange
|
||||
# return user.id
|
||||
# raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")
|
||||
|
||||
class RunDay(BaseModel):
|
||||
"""
|
||||
Helper object for batch run - carries list of days in format required by run batch manager
|
||||
"""
|
||||
start: datetime
|
||||
end: datetime
|
||||
name: Optional[str] = None
|
||||
note: Optional[str] = None
|
||||
id: Optional[str] = None
|
||||
|
||||
# Define a Pydantic model for input data
|
||||
class ConfigItem(BaseModel):
|
||||
|
||||
@ -41,6 +41,23 @@ DATA_DIR = user_data_dir("v2realbot")
|
||||
PROFILING_NEXT_ENABLED = False
|
||||
PROFILING_OUTPUT_DIR = DATA_DIR
|
||||
|
||||
#FILL CONFIGURATION CLASS FOR BACKTESTING
|
||||
|
||||
#WIP
|
||||
class BT_FILL_CONF:
|
||||
""""
|
||||
Trida pro konfiguraci backtesting fillu pro dany symbol, pokud neexistuje tak fallback na obecny viz vyse-
|
||||
|
||||
MOžná udělat i separátní profil PAPER/LIVE. Nějak vymyslet profily a jejich správa.
|
||||
"""
|
||||
def __init__(self, symbol, BT_FILL_CONS_TRADES_REQUIRED, BT_FILL_CONDITION_BUY_LIMIT, BT_FILL_CONDITION_SELL_LIMIT,BT_FILL_PRICE_MARKET_ORDER_PREMIUM):
|
||||
self.symbol = symbol
|
||||
self.BT_FILL_CONS_TRADES_REQUIRED = BT_FILL_CONS_TRADES_REQUIRED
|
||||
self.BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT
|
||||
self.BT_FILL_CONDITION_SELL_LIMIT=BT_FILL_CONDITION_SELL_LIMIT
|
||||
self.BT_FILL_PRICE_MARKET_ORDER_PREMIUM=BT_FILL_PRICE_MARKET_ORDER_PREMIUM
|
||||
|
||||
|
||||
""""
|
||||
LATENCY DELAYS for LIVE eastcoast
|
||||
.000 trigger - last_trade_time (.4246266)
|
||||
|
||||
@ -6,20 +6,23 @@ 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, OrderSide
|
||||
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem
|
||||
from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, 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.ilog import delete_logs
|
||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||
from datetime import datetime
|
||||
from threading import Thread, current_thread, Event, enumerate
|
||||
from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN
|
||||
from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN
|
||||
import importlib
|
||||
from alpaca.trading.requests import GetCalendarRequest
|
||||
from alpaca.trading.client import TradingClient
|
||||
#from alpaca.trading.models import Calendar
|
||||
from queue import Queue
|
||||
from tinydb import TinyDB, Query, where
|
||||
from tinydb.operations import set
|
||||
import json
|
||||
from numpy import ndarray
|
||||
#from rich import print
|
||||
from rich import print
|
||||
import pandas as pd
|
||||
from traceback import format_exc
|
||||
from datetime import timedelta, time
|
||||
@ -339,38 +342,93 @@ def get_testlist_byID(record_id: str):
|
||||
return 0, TestList(id=row[0], name=row[1], dates=json.loads(row[2]))
|
||||
|
||||
|
||||
##TADY JSEM SKONCIL PROJIT - dodelat nastavni timezone
|
||||
#nejspis vse v RunDays by melo byt jiz lokalizovano na zoneNY
|
||||
#zaroven nejak vymyslet, aby bt_from/to uz bylo lokalizovano
|
||||
#ted jsem dal natvrdo v main rest lokalizaci
|
||||
#ale odtrasovat,ze vse funguje (nefunguje)
|
||||
|
||||
#volano pro batchove spousteni (BT,)
|
||||
def run_batch_stratin(id: UUID, runReq: RunRequest):
|
||||
#pozor toto je test interval id (batch id se pak generuje pro kazdy davkovy run tohoto intervalu)
|
||||
if runReq.test_batch_id is None:
|
||||
return (-1, "batch_id required for batch run")
|
||||
|
||||
#pozor test_batch_id je test interval id (batch id se pak generuje pro kazdy davkovy run tohoto intervalu)
|
||||
if runReq.test_batch_id is None and (runReq.bt_from is None or runReq.bt_from.date() == runReq.bt_to.date()):
|
||||
return (-1, "test interval or different days required for batch run")
|
||||
|
||||
if runReq.mode != Mode.BT:
|
||||
return (-1, "batch run only for backtest")
|
||||
|
||||
print("request values:", runReq)
|
||||
#print("request values:", runReq)
|
||||
|
||||
print("getting intervals")
|
||||
testlist: TestList
|
||||
#getting days to run into RunDays format
|
||||
if runReq.test_batch_id is not None:
|
||||
print("getting intervals days")
|
||||
testlist: TestList
|
||||
|
||||
res, testlist = get_testlist_byID(record_id=runReq.test_batch_id)
|
||||
res, testlist = get_testlist_byID(record_id=runReq.test_batch_id)
|
||||
|
||||
if res < 0:
|
||||
return (-1, f"not existing ID of testlists with {runReq.test_batch_id}")
|
||||
if res < 0:
|
||||
return (-1, f"not existing ID of testlists with {runReq.test_batch_id}")
|
||||
|
||||
print("test interval:", testlist)
|
||||
|
||||
cal_list = []
|
||||
#interval dame do formatu list(RunDays)
|
||||
#TODO do budoucna predelat Interval na RunDays a na zone aware datetime
|
||||
for intrvl in testlist.dates:
|
||||
start_time = zoneNY.localize(datetime.fromisoformat(intrvl.start))
|
||||
end_time = zoneNY.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: {cal_list}")
|
||||
#sem getting dates
|
||||
else:
|
||||
#getting dates from calendat
|
||||
clientTrading = TradingClient(ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, raw_data=False)
|
||||
if runReq.bt_to is None:
|
||||
runReq.bt_to = datetime.now().astimezone(zoneNY)
|
||||
|
||||
calendar_request = GetCalendarRequest(start=runReq.bt_from,end=runReq.bt_to)
|
||||
cal_dates = clientTrading.get_calendar(calendar_request)
|
||||
#list(Calendar)
|
||||
# Calendar
|
||||
# date: date
|
||||
# open: datetime
|
||||
# close: datetime
|
||||
cal_list = []
|
||||
for day in cal_dates:
|
||||
start_time = zoneNY.localize(day.open)
|
||||
end_time = zoneNY.localize(day.close)
|
||||
|
||||
#u prvni polozky
|
||||
if day == cal_dates[0]:
|
||||
#pokud je cas od od vetsi nez open marketu prvniho dne, pouzijeme tento pozdejis cas
|
||||
if runReq.bt_from > start_time:
|
||||
start_time = runReq.bt_from
|
||||
|
||||
#u posledni polozky
|
||||
if day == cal_dates[-1]:
|
||||
#cas do, je pred openenem market, nedavame tento den
|
||||
if runReq.bt_to < start_time:
|
||||
continue
|
||||
#pokud koncovy cas neni do konce marketu, pouzijeme tento drivejsi namisto konce posledniho dne
|
||||
if runReq.bt_to < end_time:
|
||||
end_time = runReq.bt_to
|
||||
cal_list.append(RunDay(start = start_time, end = end_time))
|
||||
|
||||
print(f"Getting interval dates from - to - RESULT: {cal_list}")
|
||||
|
||||
#spousti se vlakno s paralelnim behem a vracime ok
|
||||
ridici_vlakno = Thread(target=batch_run_manager, args=(id, runReq, testlist), name=f"Batch run controll thread started.")
|
||||
ridici_vlakno = Thread(target=batch_run_manager, args=(id, runReq, cal_list), name=f"Batch run control thread started.")
|
||||
ridici_vlakno.start()
|
||||
print(enumerate())
|
||||
|
||||
return 0, f"Batch run started"
|
||||
|
||||
|
||||
#thread, ktery bude ridit paralelni spousteni
|
||||
# bud ceka na dokonceni v runners nebo to bude ridit jinak a bude mit jednoho runnera?
|
||||
# nejak vymyslet.
|
||||
# logovani zatim jen do print
|
||||
def batch_run_manager(id: UUID, runReq: RunRequest, testlist: TestList):
|
||||
def batch_run_manager(id: UUID, runReq: RunRequest, rundays: list[RunDay]):
|
||||
#zde muzu iterovat nad intervaly
|
||||
#cekat az dobehne jeden interval a pak spustit druhy
|
||||
#pripadne naplanovat beh - to uvidim
|
||||
@ -379,30 +437,21 @@ def batch_run_manager(id: UUID, runReq: RunRequest, testlist: TestList):
|
||||
#mohl podporovat i BATCH RUNy.
|
||||
batch_id = str(uuid4())[:8]
|
||||
runReq.batch_id = batch_id
|
||||
print("Entering BATCH RUN MANAGER")
|
||||
print("generated batch_ID", batch_id)
|
||||
|
||||
print("test batch", testlist)
|
||||
|
||||
print("test date", testlist.dates)
|
||||
interval: Intervals
|
||||
cnt_max = len(testlist.dates)
|
||||
cnt_max = len(rundays)
|
||||
cnt = 0
|
||||
#promenna pro sdileni mezi runy jednotlivych batchů (např. daily profit)
|
||||
inter_batch_params = dict(batch_profit=0)
|
||||
note_from_run_request = runReq.note
|
||||
for intrvl in testlist.dates:
|
||||
for day in rundays:
|
||||
cnt += 1
|
||||
interval = intrvl
|
||||
if interval.note is not None:
|
||||
print("mame zde note")
|
||||
print("Datum od", interval.start)
|
||||
print("Datum do", interval.end)
|
||||
print("starting")
|
||||
|
||||
#předání atributů datetime.fromisoformat
|
||||
runReq.bt_from = datetime.fromisoformat(interval.start)
|
||||
runReq.bt_to = datetime.fromisoformat(interval.end)
|
||||
runReq.note = f"Batch {batch_id} #{cnt}/{cnt_max} {testlist.name} N:{interval.note} {note_from_run_request}"
|
||||
print("Datum od", day.start)
|
||||
print("Datum do", day.end)
|
||||
runReq.bt_from = day.start
|
||||
runReq.bt_to = day.end
|
||||
runReq.note = f"Batch {batch_id} #{cnt}/{cnt_max} {day.name} N:{day.note} {note_from_run_request}"
|
||||
|
||||
#protoze jsme v ridicim vlaknu, poustime za sebou jednotlive stratiny v synchronnim modu
|
||||
res, id_val = run_stratin(id=id, runReq=runReq, synchronous=True, inter_batch_params=inter_batch_params)
|
||||
@ -434,9 +483,9 @@ def run_stratin(id: UUID, runReq: RunRequest, synchronous: bool = False, inter_b
|
||||
return (-1, "stratvars invalid")
|
||||
res, adp = parse_toml_string(i.add_data_conf)
|
||||
if res < 0:
|
||||
return (-1, "add data conf invalid")
|
||||
print("jsme uvnitr")
|
||||
return (-1, "add data conf invalid")
|
||||
id = uuid4()
|
||||
print(f"RUN {id} INITIATED")
|
||||
name = i.name
|
||||
symbol = i.symbol
|
||||
open_rush = i.open_rush
|
||||
@ -1114,6 +1163,7 @@ def get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetim
|
||||
#bars.data[symbol]
|
||||
return 0, result
|
||||
except Exception as e:
|
||||
print(str(e) + format_exc())
|
||||
return -2, str(e)
|
||||
|
||||
# change_archived_runner
|
||||
|
||||
@ -24,7 +24,7 @@ from queue import Queue, Empty
|
||||
from threading import Thread
|
||||
import asyncio
|
||||
from v2realbot.common.db import insert_queue, insert_conn, pool
|
||||
from v2realbot.utils.utils import json_serial, send_to_telegram
|
||||
from v2realbot.utils.utils import json_serial, send_to_telegram, zoneNY, zonePRG
|
||||
from uuid import uuid4
|
||||
from sqlite3 import OperationalError
|
||||
from time import sleep
|
||||
@ -226,7 +226,14 @@ def _get_stratin(stratin_id) -> StrategyInstance:
|
||||
@app.put("/stratins/{stratin_id}/run", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
||||
def _run_stratin(stratin_id: UUID, runReq: RunRequest):
|
||||
#print(runReq)
|
||||
if runReq.test_batch_id is not None:
|
||||
if runReq.bt_from is not None:
|
||||
runReq.bt_from = zonePRG.localize(runReq.bt_from)
|
||||
|
||||
if runReq.bt_to is not None:
|
||||
runReq.bt_to = zonePRG.localize(runReq.bt_to)
|
||||
#pokud jedeme nad test intervaly anebo je požadováno více dní - pouštíme jako batch day by day
|
||||
#do budoucna dát na FE jako flag
|
||||
if runReq.test_batch_id is not None or (runReq.bt_from.date() != runReq.bt_to.date()):
|
||||
res, id = cs.run_batch_stratin(id=stratin_id, runReq=runReq)
|
||||
else:
|
||||
res, id = cs.run_stratin(id=stratin_id, runReq=runReq)
|
||||
|
||||
@ -82,6 +82,19 @@
|
||||
<link rel="stylesheet" data-name="vs/editor/editor.main" href="/static/js/libs/monaco/vs/editor/editor.main.css">
|
||||
<script src="/static/js/libs/monaco/vs/loader.js"></script>
|
||||
|
||||
<!-- <link rel="stylesheet" href="/static/js/libs/atom-dark.css">
|
||||
<link rel="stylesheet" href="/static/js/libs/speedhighlight/dist/themes/atom-dark.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@speed-highlight/core@1.2.4/dist/themes/default.css">
|
||||
-->
|
||||
<!--
|
||||
<script type="module">
|
||||
import { highlightAll, highlightText } from '/static/js/libs/speedhighlight/dist/index.js';
|
||||
|
||||
// import { detectLanguage } from 'https://unpkg.com/@speed-highlight/core/dist/detect.js';
|
||||
// import e from 'https://unpkg.com/@speed-highlight/core@1.2.4/dist/languages/log.js';
|
||||
// loadLanguage('log', e);
|
||||
highlightAll();
|
||||
</script> -->
|
||||
|
||||
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/editor/editor.main.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/loader.min.js"></script> -->
|
||||
|
||||
@ -298,6 +298,8 @@ function prepare_data(archRunner, timeframe_amount, timeframe_unit, archivedRunn
|
||||
//$("#statusStratvars").text(JSON.stringify(data.stratvars,null,2))
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
oneMinuteBars = null
|
||||
chart_archived_run(archRunner, archivedRunnerDetail, oneMinuteBars);
|
||||
var err = eval("(" + xhr.responseText + ")");
|
||||
window.alert(JSON.stringify(xhr));
|
||||
console.log(JSON.stringify(xhr));
|
||||
@ -357,6 +359,7 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
||||
|
||||
candlestickSeries = null
|
||||
|
||||
//v pripade, ze neprojde get bars, nastavit na intervals[0]
|
||||
switch_to_interval(intervals[1])
|
||||
chart.timeScale().fitContent();
|
||||
|
||||
@ -963,11 +966,11 @@ function display_log(iterLogList, timestamp) {
|
||||
|
||||
highlighted = (parseInt(logLine.time) == parseInt(timestamp)) ? "highlighted" : ""
|
||||
logcnt++;
|
||||
row = '<div data-bs-toggle="collapse" class="'+ highlighted + '" onclick="set_timestamp(' + logLine.time + ')" data-bs-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ (logLine.message == undefined ? "" : logLine.message) +'</div>'
|
||||
row = '<div data-bs-toggle="collapse" class="'+ highlighted + ' shj-lang-log" onclick="set_timestamp(' + logLine.time + ')" data-bs-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ (logLine.message == undefined ? "" : logLine.message) +'</div>'
|
||||
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>'
|
||||
row_detail = '<div id="rec'+logcnt+'" class="collapse pidi shj-lang-log"><pre>' + str_row + '</pre></div>'
|
||||
|
||||
var lines = document.getElementById('lines')
|
||||
var line = document.createElement('div')
|
||||
|
||||
157
v2realbot/static/js/libs/atom-dark.css
Normal file
157
v2realbot/static/js/libs/atom-dark.css
Normal file
@ -0,0 +1,157 @@
|
||||
[class*=shj-lang-] {
|
||||
white-space: pre;
|
||||
/* margin: 10px 0; */
|
||||
/* border-radius: 10px; */
|
||||
/* padding: 30px 20px; */
|
||||
background: white;
|
||||
color: #112;
|
||||
box-shadow: 0 0 5px #0001;
|
||||
text-shadow: none;
|
||||
font: 11px Consolas,Courier New,Monaco,Andale Mono,Ubuntu Mono,monospace;
|
||||
line-height: 15px;
|
||||
box-sizing: border-box;
|
||||
/* max-width: min(100%,100vw); */
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.shj-inline {
|
||||
margin: 0;
|
||||
padding: 2px 5px;
|
||||
display: inline-block;
|
||||
border-radius: 5px
|
||||
}
|
||||
|
||||
[class*=shj-lang-]::selection,[class*=shj-lang-] ::selection {
|
||||
background: #bdf5
|
||||
}
|
||||
|
||||
[class*=shj-lang-]>div {
|
||||
display: flex;
|
||||
overflow: auto
|
||||
}
|
||||
|
||||
[class*=shj-lang-]>div :last-child {
|
||||
flex: 1;
|
||||
outline: none
|
||||
}
|
||||
|
||||
.shj-numbers {
|
||||
padding-left: 5px;
|
||||
counter-reset: line
|
||||
}
|
||||
|
||||
.shj-numbers div {
|
||||
padding-right: 5px
|
||||
}
|
||||
|
||||
.shj-numbers div:before {
|
||||
color: #999;
|
||||
display: block;
|
||||
content: counter(line);
|
||||
opacity: .5;
|
||||
text-align: right;
|
||||
margin-right: 5px;
|
||||
counter-increment: line
|
||||
}
|
||||
|
||||
.shj-syn-cmnt {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.shj-syn-err,.shj-syn-kwd {
|
||||
color: #e16
|
||||
}
|
||||
|
||||
.shj-syn-num,.shj-syn-class {
|
||||
color: #f60
|
||||
}
|
||||
|
||||
.shj-numbers,.shj-syn-cmnt {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.shj-syn-insert,.shj-syn-str {
|
||||
color: #7d8
|
||||
}
|
||||
|
||||
.shj-syn-bool {
|
||||
color: #3bf
|
||||
}
|
||||
|
||||
.shj-syn-type,.shj-syn-oper {
|
||||
color: #5af
|
||||
}
|
||||
|
||||
.shj-syn-section,.shj-syn-func {
|
||||
color: #84f
|
||||
}
|
||||
|
||||
.shj-syn-deleted,.shj-syn-var {
|
||||
color: #f44
|
||||
}
|
||||
|
||||
.shj-oneline {
|
||||
padding: 12px 10px
|
||||
}
|
||||
|
||||
.shj-lang-http.shj-oneline .shj-syn-kwd {
|
||||
background: #25f;
|
||||
color: #fff;
|
||||
padding: 5px 7px;
|
||||
border-radius: 5px
|
||||
}
|
||||
|
||||
.shj-multiline.shj-mode-header {
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.shj-multiline.shj-mode-header:before {
|
||||
content: attr(data-lang);
|
||||
color: #58f;
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
background: #58f3;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px
|
||||
}
|
||||
|
||||
[class*=shj-lang-] {
|
||||
color: #abb2bf;
|
||||
background: #161b22
|
||||
}
|
||||
|
||||
[class*=shj-lang-]:before {
|
||||
color: #6f9aff
|
||||
}
|
||||
|
||||
.shj-syn-deleted,.shj-syn-err,.shj-syn-var {
|
||||
color: #e06c75
|
||||
}
|
||||
|
||||
.shj-syn-section,.shj-syn-oper,.shj-syn-kwd {
|
||||
color: #c678dd
|
||||
}
|
||||
|
||||
.shj-syn-class {
|
||||
color: #e5c07b
|
||||
}
|
||||
|
||||
.shj-numbers,.shj-syn-cmnt {
|
||||
color: #76839a
|
||||
}
|
||||
|
||||
.shj-syn-insert {
|
||||
color: #98c379
|
||||
}
|
||||
|
||||
.shj-syn-type {
|
||||
color: #56b6c2
|
||||
}
|
||||
|
||||
.shj-syn-num,.shj-syn-bool {
|
||||
color: #d19a66
|
||||
}
|
||||
|
||||
.shj-syn-str,.shj-syn-func {
|
||||
color: #61afef
|
||||
}
|
||||
@ -278,7 +278,7 @@ html {
|
||||
height: 568px;
|
||||
flex-direction: column-reverse;
|
||||
margin-left: 28px;
|
||||
width: 100%;
|
||||
width: 130%;
|
||||
}
|
||||
|
||||
#lowercontainer {
|
||||
|
||||
@ -63,27 +63,30 @@ def trail_SL_management(state: StrategyState, data):
|
||||
def_SL = get_override_for_active_trade(state=state, directive_name=directive_name, default_value=safe_get(options, directive_name, 0.01))
|
||||
directive_name = "SL_trailing_offset_"+str(smer)
|
||||
offset = get_override_for_active_trade(state=state, directive_name=directive_name, default_value=safe_get(options, directive_name, 0.01))
|
||||
directive_name = "SL_trailing_step_"+str(smer)
|
||||
step = get_override_for_active_trade(state=state, directive_name=directive_name, default_value=safe_get(options, directive_name, offset))
|
||||
|
||||
#pokud je pozadovan trail jen do breakeven a uz prekroceno
|
||||
if (direction == TradeDirection.LONG and stop_breakeven and state.vars.activeTrade.stoploss_value >= float(state.avgp)) or (direction == TradeDirection.SHORT and stop_breakeven and state.vars.activeTrade.stoploss_value <= float(state.avgp)):
|
||||
state.ilog(lvl=1,e=f"SL trail STOP at breakeven {str(smer)} SL:{state.vars.activeTrade.stoploss_value} UNCHANGED", stop_breakeven=stop_breakeven)
|
||||
return
|
||||
|
||||
#IDEA: Nyni posouvame SL o offset, mozna ji posunout jen o direktivu step ?
|
||||
#Aktivace SL pokud vystoupa na "offset", a nasledne posunuti o "step"
|
||||
|
||||
offset_normalized = normalize_tick(state, data, offset) #to ticks and from options
|
||||
step_normalized = normalize_tick(state, data, step)
|
||||
def_SL_normalized = normalize_tick(state, data, def_SL)
|
||||
if direction == TradeDirection.LONG:
|
||||
move_SL_threshold = state.vars.activeTrade.stoploss_value + offset_normalized + def_SL_normalized
|
||||
state.ilog(lvl=1,e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||
state.ilog(lvl=1,e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, step_normalized=step_normalized, def_SL_normalized=def_SL_normalized)
|
||||
if (move_SL_threshold) < data['close']:
|
||||
state.vars.activeTrade.stoploss_value += offset_normalized
|
||||
state.vars.activeTrade.stoploss_value += step_normalized
|
||||
insert_SL_history(state)
|
||||
state.ilog(lvl=1,e=f"SL TRAIL TH {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||
state.ilog(lvl=1,e=f"SL TRAIL TH {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, step_normalized=step_normalized, def_SL_normalized=def_SL_normalized)
|
||||
elif direction == TradeDirection.SHORT:
|
||||
move_SL_threshold = state.vars.activeTrade.stoploss_value - offset_normalized - def_SL_normalized
|
||||
state.ilog(lvl=0,e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||
state.ilog(lvl=0,e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, step_normalized=step_normalized, def_SL_normalized=def_SL_normalized)
|
||||
if (move_SL_threshold) > data['close']:
|
||||
state.vars.activeTrade.stoploss_value -= offset_normalized
|
||||
state.vars.activeTrade.stoploss_value -= step_normalized
|
||||
insert_SL_history(state)
|
||||
state.ilog(lvl=1,e=f"SL TRAIL GOAL {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||
state.ilog(lvl=1,e=f"SL TRAIL GOAL {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, step_normalized=step_normalized, def_SL_normalized=def_SL_normalized)
|
||||
|
||||
@ -1 +1,10 @@
|
||||
from . import *
|
||||
import os
|
||||
# import importlib
|
||||
# from v2realbot.strategyblocks.indicators.custom.opengap import opengap
|
||||
|
||||
for filename in os.listdir("v2realbot/strategyblocks/indicators/custom"):
|
||||
if filename.endswith(".py") and filename != "__init__.py":
|
||||
# __import__(filename[:-3])
|
||||
__import__(f"v2realbot.strategyblocks.indicators.custom.{filename[:-3]}")
|
||||
#importlib.import_module()
|
||||
|
||||
|
||||
@ -35,6 +35,32 @@ def basestats(state, params):
|
||||
val = np.amax(source_array)
|
||||
elif func == "mean":
|
||||
val = np.mean(source_array)
|
||||
elif func == "var":
|
||||
data = np.array(source_array)
|
||||
mean_value = np.mean(data)
|
||||
# Calculate the variance of the data
|
||||
val = np.mean((data - mean_value) ** 2)
|
||||
elif func == "angle":
|
||||
delka_pole = len(source_array)
|
||||
if delka_pole < 2:
|
||||
return 0,0
|
||||
|
||||
x = np.arange(delka_pole)
|
||||
y = np.array(source_array)
|
||||
|
||||
# Fit a linear polynomial to the data
|
||||
coeffs = np.polyfit(x, y, 1)
|
||||
|
||||
# Calculate the angle in radians angle_rad
|
||||
val = np.arctan(coeffs[0]) * 1000
|
||||
|
||||
# Convert the angle to degrees angle_deg
|
||||
#angle_deg = np.degrees(angle_rad)
|
||||
|
||||
# Normalize the degrees between -1 and 1
|
||||
#val = 2 * (angle_deg / 180) - 1
|
||||
elif func =="stdev":
|
||||
val = np.std(source_array)
|
||||
else:
|
||||
return -2, "wrong function"
|
||||
|
||||
|
||||
26
v2realbot/strategyblocks/indicators/custom/ema.py
Normal file
26
v2realbot/strategyblocks/indicators/custom/ema.py
Normal file
@ -0,0 +1,26 @@
|
||||
from v2realbot.utils.utils import isrising, isfalling,zoneNY, price2dec, print, safe_get, is_still, is_window_open, eval_cond_dict, crossed_down, crossed_up, crossed, is_pivot, json_serial, pct_diff, create_new_bars, slice_dict_lists
|
||||
from v2realbot.strategy.base import StrategyState
|
||||
from v2realbot.indicators.indicators import ema as ext_ema
|
||||
from v2realbot.strategyblocks.indicators.helpers import get_source_series
|
||||
from rich import print as printanyway
|
||||
from traceback import format_exc
|
||||
from v2realbot.ml.ml import ModelML
|
||||
import numpy as np
|
||||
from collections import defaultdict
|
||||
from v2realbot.strategyblocks.indicators.helpers import value_or_indicator
|
||||
#strength, absolute change of parameter between current value and lookback value (n-past)
|
||||
#used for example to measure unusual peaks
|
||||
def ema(state, params):
|
||||
funcName = "ema"
|
||||
source = safe_get(params, "source", None)
|
||||
lookback = safe_get(params, "lookback",14)
|
||||
|
||||
#lookback muze byt odkaz na indikator, pak berem jeho hodnotu
|
||||
lookback = int(value_or_indicator(state, lookback))
|
||||
|
||||
source_series = get_source_series(state, source)[-lookback:]
|
||||
ema_value = ext_ema(source_series, lookback)
|
||||
val = round(ema_value[-1],4)
|
||||
|
||||
state.ilog(lvl=1,e=f"INSIDE {funcName} {val} {source=} {lookback=}", **params)
|
||||
return 0, val
|
||||
@ -15,13 +15,16 @@ def mathop(state, params):
|
||||
|
||||
if source1 is None or source2 is None or operator is None:
|
||||
return -2, "required source1 source2 operator"
|
||||
druhy = float(value_or_indicator(state, source2))
|
||||
if operator == "+":
|
||||
val = round(float(source1_series[-1] + value_or_indicator(state, source2)),4)
|
||||
val = round(float(source1_series[-1] + druhy),4)
|
||||
elif operator == "-":
|
||||
val = round(float(source1_series[-1] - value_or_indicator(state, source2)),4)
|
||||
val = round(float(source1_series[-1] - druhy),4)
|
||||
elif operator == "*":
|
||||
val = round(float(source1_series[-1] * druhy),4)
|
||||
else:
|
||||
return -2, "unknow operator"
|
||||
#state.ilog(lvl=0,e=f"INSIDE {funcName} {source1=} {source2=} {val}", **params)
|
||||
state.ilog(lvl=1,e=f"INSIDE {funcName} {source1=} {source2=} {val} {druhy=}", **params)
|
||||
return 0, val
|
||||
|
||||
|
||||
|
||||
52
v2realbot/strategyblocks/indicators/custom/sameprice.py
Normal file
52
v2realbot/strategyblocks/indicators/custom/sameprice.py
Normal file
@ -0,0 +1,52 @@
|
||||
from v2realbot.utils.utils import isrising, isfalling,zoneNY, price2dec, print, safe_get, is_still, is_window_open, eval_cond_dict, crossed_down, crossed_up, crossed, is_pivot, json_serial, pct_diff, create_new_bars, slice_dict_lists
|
||||
from v2realbot.strategy.base import StrategyState
|
||||
from v2realbot.indicators.indicators import ema, natr, roc
|
||||
from v2realbot.strategyblocks.indicators.helpers import get_source_series
|
||||
from rich import print as printanyway
|
||||
from traceback import format_exc
|
||||
from v2realbot.ml.ml import ModelML
|
||||
import numpy as np
|
||||
from collections import defaultdict
|
||||
import bisect
|
||||
|
||||
#strength, absolute change of parameter between current value and lookback value (n-past)
|
||||
#used for example to measure unusual peaks
|
||||
def sameprice(state, params):
|
||||
funcName = "sameprice"
|
||||
typ = safe_get(params, "type", None)
|
||||
|
||||
def find_first_bigger_than_lastitem_backwards(list1):
|
||||
last_item = list1[-1]
|
||||
for i in range(len(list1) - 2, -1, -1):
|
||||
if list1[i] > last_item:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def find_first_smaller_than_lastitem_backwards(list1):
|
||||
last_item = list1[-1]
|
||||
for i in range(len(list1) - 2, -1, -1):
|
||||
if list1[i] < last_item:
|
||||
return i
|
||||
return -1
|
||||
|
||||
if typ == "up":
|
||||
pozice_prvniho_vetsiho = find_first_bigger_than_lastitem_backwards(state.bars["vwap"])
|
||||
elif typ == "down":
|
||||
pozice_prvniho_vetsiho = find_first_smaller_than_lastitem_backwards(state.bars["vwap"])
|
||||
else:
|
||||
return -2, "unknow type"
|
||||
|
||||
celkova_delka = len(state.bars["vwap"])
|
||||
|
||||
#jde o daily high
|
||||
if pozice_prvniho_vetsiho == -1:
|
||||
state.ilog(lvl=1,e=f"INSIDE {funcName} {typ} {pozice_prvniho_vetsiho=} vracime 1")
|
||||
return 0, celkova_delka
|
||||
|
||||
delka_k_predchozmu = celkova_delka - pozice_prvniho_vetsiho
|
||||
normalizovano = delka_k_predchozmu/celkova_delka
|
||||
|
||||
state.ilog(lvl=1,e=f"INSIDE {funcName} {typ} {pozice_prvniho_vetsiho=} {celkova_delka=} {delka_k_predchozmu=} {normalizovano=}", pozice_prvniho_vetsiho=pozice_prvniho_vetsiho, celkova_delka=celkova_delka, delka_k_predchozmu=delka_k_predchozmu, **params)
|
||||
|
||||
return 0, delka_k_predchozmu
|
||||
|
||||
@ -8,15 +8,16 @@ import importlib
|
||||
|
||||
#TODO TENTO IMPORT VYMYSLET, abych naloadoval package custom a nemusel nic pridat (vymyslet dynamicke volani z cele package ci)
|
||||
#from v2realbot.strategyblocks.indicators.custom._upscaled_rsi_wip import upscaledrsi
|
||||
from v2realbot.strategyblocks.indicators.custom.barparams import barparams
|
||||
from v2realbot.strategyblocks.indicators.custom.basestats import basestats
|
||||
from v2realbot.strategyblocks.indicators.custom.delta import delta
|
||||
from v2realbot.strategyblocks.indicators.custom.divergence import divergence
|
||||
from v2realbot.strategyblocks.indicators.custom.model import model
|
||||
from v2realbot.strategyblocks.indicators.custom.opengap import opengap
|
||||
from v2realbot.strategyblocks.indicators.custom.slope import slope
|
||||
from v2realbot.strategyblocks.indicators.custom.conditional import conditional
|
||||
from v2realbot.strategyblocks.indicators.custom.mathop import mathop
|
||||
import v2realbot.strategyblocks.indicators.custom as ci
|
||||
# from v2realbot.strategyblocks.indicators.custom.barparams import barparams
|
||||
# from v2realbot.strategyblocks.indicators.custom.basestats import basestats
|
||||
# from v2realbot.strategyblocks.indicators.custom.delta import delta
|
||||
# from v2realbot.strategyblocks.indicators.custom.divergence import divergence
|
||||
# from v2realbot.strategyblocks.indicators.custom.model import model
|
||||
# from v2realbot.strategyblocks.indicators.custom.opengap import opengap
|
||||
# from v2realbot.strategyblocks.indicators.custom.slope import slope
|
||||
# from v2realbot.strategyblocks.indicators.custom.conditional import conditional
|
||||
# from v2realbot.strategyblocks.indicators.custom.mathop import mathop
|
||||
|
||||
# import v2realbot.strategyblocks.indicators.custom as ci
|
||||
|
||||
@ -143,7 +144,7 @@ def populate_dynamic_custom_indicator(data, state: StrategyState, name):
|
||||
#pozor jako defaultní hodnotu dává engine 0 - je to ok?
|
||||
try:
|
||||
|
||||
#subtype = "ci."+subtype
|
||||
subtype = "ci."+subtype+"."+subtype
|
||||
custom_function = eval(subtype)
|
||||
res_code, new_val = custom_function(state, custom_params)
|
||||
if res_code == 0:
|
||||
@ -1,4 +1,4 @@
|
||||
from v2realbot.utils.utils import isrising, isfalling,zoneNY, price2dec, print, safe_get, is_still, is_window_open, eval_cond_dict, crossed_down, crossed_up, crossed, is_pivot, json_serial, pct_diff, create_new_bars, slice_dict_lists
|
||||
from v2realbot.utils.utils import isrising, isfalling,isfallingc, isrisingc, zoneNY, price2dec, print, safe_get, is_still, is_window_open, eval_cond_dict, crossed_down, crossed_up, crossed, is_pivot, json_serial, pct_diff, create_new_bars, slice_dict_lists
|
||||
from v2realbot.strategy.base import StrategyState
|
||||
from traceback import format_exc
|
||||
|
||||
@ -9,13 +9,16 @@ from traceback import format_exc
|
||||
def value_or_indicator(state,value):
|
||||
#preklad direktivy podle typu, pokud je int anebo float - je to primo hodnota
|
||||
#pokud je str, jde o indikator a dotahujeme posledni hodnotu z nej
|
||||
if isinstance(value, (int, float)):
|
||||
if isinstance(value, (float, int)):
|
||||
return value
|
||||
elif isinstance(value, str):
|
||||
try:
|
||||
#pokud existuje v indikatoru MA bereme MA jinak indikator, pokud neexistuje bereme bar
|
||||
ret = get_source_or_MA(state, indicator=value)[-1]
|
||||
state.ilog(lvl=0,e=f"Pro porovnani bereme posledni hodnotu {ret} z indikatoru {value}")
|
||||
lvl = 0
|
||||
if ret == 0:
|
||||
lvl = 1
|
||||
state.ilog(lvl=lvl,e=f"Pro porovnani bereme posledni hodnotu {ret} z indikatoru {value}")
|
||||
except Exception as e :
|
||||
ret = 0
|
||||
state.ilog(lvl=1,e=f"Neexistuje indikator s nazvem {value} vracime 0" + str(e) + format_exc())
|
||||
@ -38,6 +41,8 @@ def evaluate_directive_conditions(state, work_dict, cond_type):
|
||||
"above": lambda ind, val: get_source_or_MA(state, ind)[-1] > value_or_indicator(state,val),
|
||||
"equals": lambda ind, val: get_source_or_MA(state, ind)[-1] == value_or_indicator(state,val),
|
||||
"below": lambda ind, val: get_source_or_MA(state, ind)[-1] < value_or_indicator(state,val),
|
||||
"fallingc": lambda ind, val: isfallingc(get_source_or_MA(state, ind), val),
|
||||
"risingc": lambda ind, val: isrisingc(get_source_or_MA(state, ind), val),
|
||||
"falling": lambda ind, val: isfalling(get_source_or_MA(state, ind), val),
|
||||
"rising": lambda ind, val: isrising(get_source_or_MA(state, ind), val),
|
||||
"crossed_down": lambda ind, val: buy_if_crossed_down(state, ind, value_or_indicator(state,val)),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
from v2realbot.strategy.base import StrategyState
|
||||
from v2realbot.strategyblocks.indicators.cbar_price import populate_cbar_tick_price_indicator
|
||||
from v2realbot.strategyblocks.indicators.custom.custom_hub import populate_dynamic_custom_indicator
|
||||
from v2realbot.strategyblocks.indicators.custom_hub import populate_dynamic_custom_indicator
|
||||
from v2realbot.strategyblocks.indicators.slope import populate_dynamic_slope_indicator
|
||||
from v2realbot.strategyblocks.indicators.slopeLP import populate_dynamic_slopeLP_indicator
|
||||
from v2realbot.strategyblocks.indicators.ema import populate_dynamic_ema_indicator
|
||||
|
||||
@ -33,18 +33,18 @@ def go_conditions_met(state, data, signalname: str, direction: TradeDirection):
|
||||
#dont_buy_above = value nebo hazev indikatoru
|
||||
|
||||
#TESTUJEME SPECIFICKY DONT_GO -
|
||||
#u techto ma smysl pouze OR
|
||||
#jak OR tak i AND
|
||||
cond_dict = state.vars.conditions[KW.dont_go][signalname][smer]
|
||||
result, conditions_met = evaluate_directive_conditions(state, cond_dict, "OR")
|
||||
state.ilog(lvl=1,e=f"SPECIFIC PRECOND {smer} {result}", **conditions_met, cond_dict=cond_dict)
|
||||
state.ilog(lvl=1,e=f"SPECIFIC PRECOND =OR= {smer} {result}", **conditions_met, cond_dict=cond_dict)
|
||||
if result:
|
||||
return False
|
||||
|
||||
#OR neprosly testujeme AND
|
||||
result, conditions_met = evaluate_directive_conditions(state, cond_dict, "AND")
|
||||
state.ilog(lvl=1,e=f"SPECIFIC PRECOND =AND={smer} {result}", **conditions_met, cond_dict=cond_dict)
|
||||
if result:
|
||||
return False
|
||||
|
||||
# #OR neprosly testujeme AND
|
||||
# result, conditions_met = evaluate_directive_conditions(cond_dict, "AND")
|
||||
# state.ilog(lvl=0,e=f"EXIT CONDITIONS of activeTrade {smer} =AND= {result}", **conditions_met, cond_dict=cond_dict)
|
||||
# if result:
|
||||
# return True
|
||||
|
||||
#tyto timto nahrazeny - dat do konfigurace (dont_short_when, dont_long_when)
|
||||
#dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
||||
@ -110,7 +110,7 @@ def common_go_preconditions_check(state, data, signalname: str, options: dict):
|
||||
if state.vars.last_exit_index is not None:
|
||||
index_to_compare = int(state.vars.last_exit_index)+int(next_signal_offset)
|
||||
if index_to_compare > int(data["index"]):
|
||||
state.ilog(lvl=1,e=f"NEXT SIGNAL OFFSET from EXIT {next_signal_offset} waiting - TOO SOON", currindex=data["index"], index_to_compare=index_to_compare, last_exit_index=state.vars.last_exit_index)
|
||||
state.ilog(lvl=1,e=f"NEXT SIGNAL OFFSET from EXIT {next_signal_offset} waiting - TOO SOON {signalname}", currindex=data["index"], index_to_compare=index_to_compare, last_exit_index=state.vars.last_exit_index)
|
||||
return False
|
||||
|
||||
# if is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), open_rush) or is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), close_rush):
|
||||
|
||||
@ -45,7 +45,7 @@ def execute_prescribed_trades(state: StrategyState, data):
|
||||
res = state.buy(size=size)
|
||||
if isinstance(res, int) and res < 0:
|
||||
raise Exception(f"error in required operation LONG {res}")
|
||||
#nastaveni SL az do notifikace, kdy je známá
|
||||
#TODO nastaveni SL az do notifikace, kdy je známá
|
||||
#pokud neni nastaveno SL v prescribe, tak nastavuji default dle stratvars
|
||||
if state.vars.activeTrade.stoploss_value is None:
|
||||
sl_defvalue = get_default_sl_value(state, direction=state.vars.activeTrade.direction)
|
||||
|
||||
@ -38,7 +38,7 @@ def signal_search(state: StrategyState, data):
|
||||
# to vse za predpokladu, ze neni aktivni trade
|
||||
|
||||
def execute_signal_generator(state, data, name):
|
||||
state.ilog(lvl=0,e=f"SIGNAL SEARCH for {name}", cond_go=state.vars.conditions[KW.go][name], cond_dontgo=state.vars.conditions[KW.dont_go][name], cond_activate=state.vars.conditions[KW.activate][name] )
|
||||
state.ilog(lvl=1,e=f"SIGNAL SEARCH for {name}", cond_go=state.vars.conditions[KW.go][name], cond_dontgo=state.vars.conditions[KW.dont_go][name], cond_activate=state.vars.conditions[KW.activate][name] )
|
||||
options = safe_get(state.vars.signals, name, None)
|
||||
|
||||
if options is None:
|
||||
@ -60,7 +60,7 @@ def execute_signal_generator(state, data, name):
|
||||
custom_function = eval(signal_plugin)
|
||||
custom_function()
|
||||
except NameError:
|
||||
state.ilog(lvl=1,e="Custom plugin {signal_plugin} not found")
|
||||
state.ilog(lvl=1,e=f"Custom plugin {signal_plugin} not found")
|
||||
else:
|
||||
short_enabled = safe_get(options, "short_enabled",safe_get(state.vars, "short_enabled",True))
|
||||
long_enabled = safe_get(options, "long_enabled",safe_get(state.vars, "long_enabled",True))
|
||||
|
||||
@ -408,6 +408,8 @@ qu = Queue()
|
||||
#zoneNY = tz.gettz('America/New_York')
|
||||
zoneNY = pytz.timezone('US/Eastern')
|
||||
|
||||
zonePRG = pytz.timezone('Europe/Amsterdam')
|
||||
|
||||
def print(*args, **kwargs):
|
||||
if QUIET_MODE:
|
||||
pass
|
||||
@ -567,8 +569,8 @@ def is_open_hours(dt, business_hours: dict = None):
|
||||
and dt.date() not in holidays \
|
||||
and business_hours["from"] <= dt.time() < business_hours["to"]
|
||||
|
||||
#vraci zda dane pole je klesajici (bud cele a nebo jen pocet poslednich)
|
||||
def isfalling_old(pole: list, pocet: int = None):
|
||||
#vraci zda dane pole je klesajici (bud cele a nebo jen pocet poslednich) - no same values
|
||||
def isfallingc(pole: list, pocet: int = None):
|
||||
if pocet is None: pocet = len(pole)
|
||||
if len(pole)<pocet: return False
|
||||
pole = pole[-pocet:]
|
||||
@ -599,8 +601,8 @@ def isfalling(pole: list, pocet: int = None):
|
||||
res = all(i > j for i, j in zip(new_pole, new_pole[1:]))
|
||||
return res
|
||||
|
||||
#vraci zda dane pole je roustouci (bud cele a nebo jen pocet poslednich)
|
||||
def isrising_old(pole: list, pocet: int = None):
|
||||
#vraci zda dane pole je roustouci (bud cele a nebo jen pocet poslednich) - no same values
|
||||
def isrisingc(pole: list, pocet: int = None):
|
||||
if pocet is None: pocet = len(pole)
|
||||
if len(pole)<pocet: return False
|
||||
pole = pole[-pocet:]
|
||||
|
||||
Reference in New Issue
Block a user