Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
psemdel committed Feb 29, 2024
2 parents 0918de5 + 133142a commit 9b25bf2
Show file tree
Hide file tree
Showing 46 changed files with 1,284 additions and 416 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ RUN pip install --quiet --no-cache-dir \
'quantstats>=0.0.37' \
'PyPortfolioOpt>=1.5.1' \
'Riskfolio-Lib>=3.3.0' \
'python-telegram-bot>=13.4' \
'python-telegram-bot==13.5' \
'dill' \
'lz4' \
'blosc'
Expand Down
6 changes: 5 additions & 1 deletion docs/docker_readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ If you want to read the logs of the bot:
kubectl logs <name of the worker pod>

Optional: Go in the admin panel and delete the user admin and testdb, that are completely unnecessary.
Note: The

#Troubleshooting
#Troubleshooting
If kubectl command is not found replace in the script the "kubectl" by "minikube kubectl -- ".

If for any reason the sequence_start_first_time.sh lead to an error, you need to clean properly Kubernetes before repeating the step. It means obviously removing the deployments with

kubectl delete deployment <name of the deployment>
Expand All @@ -64,6 +67,7 @@ In addition, in kubernetes/postgres.yml, the hostPath under PersistentVolume
path: /data/py-trading-bot-postgres-pv
Needs to be changed, otherwise the same data will be loaded again when the permanent volumes are recreated.


## Error auth_user_username_key
In the logs of py-trading-bot pod (kubectl logs <name of py-trading-bot>) you find:
Expand Down
1 change: 1 addition & 0 deletions docs/toubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ We try to make the code as robust as possible, but some errors cannot be avoided
|Nothing happens in Telegram when starting the bot | A chat id is added upon receiving the "/start" command. So try the command /start in Telegram, it should be displayed in the shell of the bot|
|Telegram does not find the bot| Check that you inserted the token in a file trading_bot/etc/TELEGRAM_TOKEN ? |
|Several chats are found and no message goes out | Go in reporting/telegram_sub.py and modify the function send_to_all. Replace the for loop by a chat_id=self.chat_ids[index_of_your_choice]. |
|You don't understand why an order was not performed | Have a look in the trade log, it is there for this purpose |

3 changes: 2 additions & 1 deletion py-trading-bot/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@
Delisting date of the stocks if relevant
'''
NASDAQ_DELIST={
"ATVI":"2023-10-20"
"ATVI":"2023-10-20",
"SGEN":"2023-12-15"
}

'''
Expand Down
6 changes: 3 additions & 3 deletions py-trading-bot/core/data_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def save_data(
data=vbt.YFData.fetch(symbols,start=start_date,end=end_date,\
timeframe='1d',missing_index="drop")
BASE_DIR = Path(__file__).resolve().parent.parent
data.to_hdf(file_path=os.path.join(BASE_DIR,'saved_cours/'+selector.upper()+'_period.h5'))
data.to_hdf(path_or_buf=os.path.join(BASE_DIR,'saved_cours/'+selector.upper()+'_period.h5'))

def retrieve_data_offline(
o,
Expand Down Expand Up @@ -168,9 +168,9 @@ def retrieve_debug(
'''
import constants

selector="industry"
selector="NASDAQ"
start_date='2007-01-01'
end_date='2023-08-01'
end_date='2024-01-03'

if selector=="CAC40":
all_symbols=constants.CAC40
Expand Down
24 changes: 13 additions & 11 deletions py-trading-bot/core/presel.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,6 @@ def symbols_simple_to_complex(self,symbol_simple,ent_or_ex):
'''
if "entries" not in self.ust.__dir__():
self.ust.run()



return self.ust.symbols_simple_to_complex(symbol_simple,ent_or_ex)
#UnderlyingStrat
Expand Down Expand Up @@ -233,7 +231,7 @@ def calculate(
if ((not self.no_ust and not short and self.ust.exits.loc[i, symbol_complex]) or #not short and
(not self.no_ust and short and self.ust.exits_short.loc[i, symbol_complex]) or
(self.no_ust and symbol_simple not in self.candidates[short_to_str[short]][i])):

self.pf[short_to_str[short]].remove(symbol_simple)
self.capital+=self.order_size

Expand Down Expand Up @@ -347,6 +345,8 @@ def sub_sub(self,
((not self.blocked and not self.blocked_im) or
((self.blocked or self.blocked_im) and not short))):
self.candidates[short_to_str[short]][i].append(symbol_simple)
return True
return False

def sub(
self,
Expand All @@ -361,6 +361,7 @@ def sub(
i: index
short: order direction
'''

self.sorting(i, short=short)
if self.sorted is not None:
for e in self.sorted:
Expand All @@ -374,7 +375,11 @@ def sub(
if len(t)>0:
symbol=t.index[0]
v=self.sorting_criterium.loc[i,symbol]
self.sub_sub(i, symbol,v, short)
pursue=self.sub_sub(i, symbol,v, short)
if not pursue:
break
else:
break
else:
raise ValueError("both sorted and sorted_df are None")

Expand Down Expand Up @@ -651,7 +656,7 @@ def __init__(self,period: str,**kwargs):
self.dur=ic.VBTKAMATREND.run(self.close).duration
#self.dur=ic.VBTSUPERTREND.run(self.high,self.low,self.close).duration
self.no_ust=True
self.calc_all=True
self.calc_all=True #otherwise it is not possible to determine what is excluded
self.last_short=False

def sorting(
Expand Down Expand Up @@ -686,7 +691,8 @@ def perform(self, r, keep:bool=False, **kwargs):

r.concat(self.st.name.capitalize()+", " + "direction " + direction + ", stockex: " + self.ust.exchange +\
", action duration: " +str(self.out))

r.concat("Present "+ self.st.name + " candidates: "+str(candidates) + " hold since: "+ str(self.hold_dur) + " days")

r.ss_m.clean_excluded(self.st.name, self.excluded)
r.ss_m.order_nosubstrat(candidates_to_YF(self.ust.symbols_to_YF,candidates), self.ust.exchange, self.st.name, self.last_short,keep=keep)

Expand Down Expand Up @@ -811,11 +817,7 @@ def underlying(self):
def sorting_g(self):
self.sorted_rank=self.divergence.rank(axis=1, ascending=True) #small divergence better
self.sorting_criterium=self.divergence

class PreselDivergenceSecond(PreselDivergence):
def underlying(self):
self.underlying_creator("StratDiv")


class PreselDivergenceBlocked(PreselDivergence):
'''
Like preselect_divergence, but the mechanism is blocked when macro_trend is bear
Expand Down
16 changes: 10 additions & 6 deletions py-trading-bot/core/presel_classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,24 @@ def fill_allocations_underlying(self):

#transform the entries and exits in 1 and 0
t=SIGNALTOSIZE.run(
self.ust.entries,
self.ust.exits,
self.ust.entries_short,
self.ust.exits_short,
self.ust_classic.entries,
self.ust_classic.exits,
self.ust_classic.entries_short,
self.ust_classic.exits_short,
idx_arr=[idx_arr]
)

self.expanded_allocations= self.expand_alloc(idx_arr, self.pf_opt._allocations) #add the weight
self.used_allocations=remove_multi(t.bought-t.sold)*remove_multi(self.expanded_allocations)
self.max_alloc()
self.size=self.new_alloc #remove_multi(self.new_alloc)* remove_multi(size_underlying)
self.size=self.new_alloc

def apply_underlying_strat(self, strat_name):
self.ust=name_to_ust_or_presel(strat_name,self.period, symbol_index=self.symbol_index)
if "ust" in self.__dir__(): #for handle "live" strategy
self.ust_classic=name_to_ust_or_presel(strat_name,self.period, input_ust=self.ust)
else:
self.ust_classic=name_to_ust_or_presel(strat_name,self.period, symbol_index=self.symbol_index)

self.fill_allocations_underlying()

#as function from_optimizer
Expand Down
53 changes: 35 additions & 18 deletions py-trading-bot/core/strat.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,19 +498,21 @@ def get_return(self):
#benchmark_return makes sense only for bull
delta=pf.total_return().values[0]
return delta
def perform_StratCandidates(self, r, st_name):

def perform(self, r):
'''
Perform during the report an underlying strategy on the candidates belonging to StratCandidates
Arguments
----------
r: report
st_name: name of the strategy
'''
from orders.models import Strategy, StratCandidates #needs to be loaded here, as it will work only if Django is loaded
st, _=Strategy.objects.get_or_create(name=st_name)
st_actions, _=StratCandidates.objects.get_or_create(strategy=st) #.id
from orders.models import StratCandidates #needs to be loaded here, as it will work only if Django is loaded

if self.st is None:
raise ValueError("st should be defined to use perform on underlying strategy")

st_actions, _=StratCandidates.objects.get_or_create(strategy=self.st) #.id
st_symbols=st_actions.retrieve()

for symbol in intersection(self.symbols,st_symbols):
Expand All @@ -520,17 +522,9 @@ def perform_StratCandidates(self, r, st_name):
symbol_complex_ent_normal=self.symbols_simple_to_complex(symbol,"ent")
symbol_complex_ex_normal=self.symbols_simple_to_complex(symbol,"ex")
target_order=self.get_last_decision(symbol_complex_ent_normal,symbol_complex_ex_normal)
r.display_last_decision(symbol,target_order, st_name)
r.display_last_decision(symbol,target_order, self.st.name)

r.ss_m.add_target_quantity(symbol, st_name, target_order)

def perform(self, r, st_name:str=None): #default
'''
See perform_StratCandidates
'''
if st_name is None:
raise ValueError("perform for underlying strategy should have an argument st_name")
self.perform_StratCandidates(r, st_name)
r.ss_m.add_target_quantity(symbol, self.st.name, target_order)

###production functions
def get_last_decision(self, symbol_complex_ent: str, symbol_complex_ex: str) -> int:
Expand Down Expand Up @@ -640,8 +634,8 @@ def __init__(self,
}

super().__init__(period,strat_arr=a,**kwargs )
class StratDiv(UnderlyingStrat):

class StratDiv2(UnderlyingStrat):
'''
Underlying strategy for divergence preselection
'''
Expand All @@ -654,6 +648,29 @@ def __init__(self,
"CDL3BLACKCROWS"]
}}

super().__init__(period,strat_arr=a,**kwargs )

class StratDiv(UnderlyingStrat):
'''
Underlying strategy for divergence preselection
'''
def __init__(self,
period: numbers.Number,
**kwargs):
a={'bull': {
'ent': ['BBANDS', 'CDL3BLACKCROWS'],
'ex': ['ULTOSC20', 'CDLHIKKAKE','CDLABANDONEDBABY', 'CDL3BLACKCROWS','CDLHIKKAKEMOD']
},
'bear': {
'ent': ['CDLHANGINGMAN', 'CDLSTICKSANDWICH', 'CDL3LINESTRIKE'],
'ex': ['STOCH', 'BBANDS', 'CDLBELTHOLD', 'CDLXSIDEGAP3METHODS']
},
'uncertain': {
'ent': ['KAMA'],
'ex': ['WILLR','ULTOSC20','ULTOSC25','CDL3LINESTRIKE','CDLDARKCLOUDCOVER', 'CDL3INSIDE']
}
}

super().__init__(period,strat_arr=a,**kwargs )

class StratTestSimple(UnderlyingStrat):
Expand Down
Loading

0 comments on commit 9b25bf2

Please sign in to comment.