profit modifier (boost)
This commit is contained in:
parent
e421e9bbde
commit
0d191edb9e
|
|
@ -1,3 +1,7 @@
|
|||
2024.11.08:
|
||||
. Added boosted take profit level: If the trader is actively closing deals, the expected profit level is raised by x%.
|
||||
Defaults are: Four deals in one hour, 1% raise.
|
||||
|
||||
2024.11.06b:
|
||||
. Added /switch_to_long_price endpoint: It displays the price at which the automatic switch_to_long routine is triggered.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,5 +18,8 @@
|
|||
"check_old_long_price": true, #Compares the current price with the old_long price. (check strategy documentation for more details)
|
||||
"dynamic_so_deviance": true, #Uses a non-linear safety order deviance algorithm. (check strategy documentation for more details)
|
||||
"dsd_range": 1, #Range of the dynamic deviance algorithm. (check strategy documentation for more details)
|
||||
"bias": -0.5 #Bias of the dynamic deviance algorithm. (check strategy documentation for more details)
|
||||
"bias": -0.5, #Bias of the dynamic deviance algorithm. (check strategy documentation for more details)
|
||||
"boosted_deals_range": 4, #Amount of deals within a timespan to trigger the boost algorithm.
|
||||
"boosted_time_range": 3600, #Timespan in seconds to count closed trades.
|
||||
"boosted_amount": .1 #Amount of percentage to add to the profit target if boosted.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,11 +87,35 @@ class broker:
|
|||
return 1
|
||||
|
||||
|
||||
def return_last_n_deals_timestamps(self, pair, amount, no_retries=False):
|
||||
'''
|
||||
Returns a list containing the last n deals timestamps.
|
||||
'''
|
||||
|
||||
retries = self.retries
|
||||
while retries>0:
|
||||
try:
|
||||
database_connection = sqlite3.connect("profits/profits_database.db")
|
||||
database_cursor = database_connection.cursor()
|
||||
database_cursor.execute(f"SELECT * FROM profits_table WHERE pair = '{pair}' ORDER BY timestamp DESC LIMIT {amount};")
|
||||
rows = database_cursor.fetchall()
|
||||
database_connection.close()
|
||||
return [item[0] for item in rows]
|
||||
except Exception as e:
|
||||
self.logger.log_this(f"Exception in return_last_n_deals_timestamps: {e}",1)
|
||||
if no_retries:
|
||||
break
|
||||
retries-=1
|
||||
time.sleep(self.wait_time)
|
||||
return []
|
||||
|
||||
|
||||
def check_for_duplicate_profit_in_db(self,order,no_retries=False):
|
||||
'''
|
||||
SQLite implementation of check_for_duplicate_profit():
|
||||
Compares the id of the last profit order with the one in the database.
|
||||
'''
|
||||
|
||||
retries = self.retries
|
||||
while retries>0:
|
||||
try:
|
||||
|
|
|
|||
2
main.py
2
main.py
|
|
@ -22,7 +22,7 @@ In case the permissions of the certificate changes, reset them this way:
|
|||
# ll /etc/letsencrypt/
|
||||
'''
|
||||
|
||||
version = "2024.11.06b"
|
||||
version = "2024.11.08"
|
||||
|
||||
'''
|
||||
Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import time
|
|||
import json
|
||||
|
||||
# Connect to the SQLite database
|
||||
conn = sqlite3.connect('profits/profits_database.db')
|
||||
conn = sqlite3.connect('profits_database.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Execute a SELECT query to retrieve data from the database
|
||||
|
|
@ -17,8 +17,8 @@ rows = cursor.fetchall()
|
|||
#human_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(row[0])))
|
||||
#print(human_time,row[1],round(row[2],2),row[3]) # Or do whatever processing you need
|
||||
|
||||
data = json.loads(rows[-3][-1])
|
||||
print(data[-1])
|
||||
#data = json.loads(rows[-3][-1])
|
||||
print([item[0] for item in rows[-4:]])
|
||||
print(f"Number of entries: {len(rows)}")
|
||||
|
||||
# Close the connection
|
||||
|
|
|
|||
13
todo.txt
13
todo.txt
|
|
@ -5,13 +5,8 @@ Mandatory:
|
|||
2. Instead of giving a list of order_ids to each trader, give a list of the open orders and that's it (for easier future development, partial order fills for example)
|
||||
3. Maintain local orderbooks for each trading pair, which enables:
|
||||
3a. Smart order pricing: Prioritization of fill speed over instant profit or vice versa
|
||||
4. Round-robin trading pairs: Instead of a fixed list of trading pairs, after n closed deals the trader is terminated and a new one spawns, picking the trading pair
|
||||
from a pre-populated list (the trading pairs can be selected by using Yang-Zhang, Parkinson or another volatility indicator)
|
||||
This could be very benefitial, since it limits the long time commitment to a small list of trading pairs, enabling the instance to react to market trends very
|
||||
rapidly.
|
||||
5. Consolidate vocabulary (trader, pair and bot; instance & trader)
|
||||
6. Base add for short traders.
|
||||
7. Dynamic take_profit level: If a trading pair is closing deals frequently, raise the take profit level to take advantage of the volatility.
|
||||
4. Consolidate vocabulary (trader, pair and bot; instance & trader)
|
||||
5. Base add for short traders.
|
||||
|
||||
|
||||
Would be nice to have:
|
||||
|
|
@ -19,6 +14,10 @@ Would be nice to have:
|
|||
0. Trader order: alphabetical; by uptime; by safety orders, by percentage_to_completion. (Although this may be more suitable for the web and mobile apps)
|
||||
1. Local implementation of amount_to_precision, cost_to_precision and price_to_precision. (Unless the plan is to continue to use CCXT forever)
|
||||
2. Instead of cancelling and resending the take profit order, you could just edit it (Kucoin only supports editing on high frequency orders)
|
||||
3. Round-robin trading pairs: Instead of a fixed list of trading pairs, after n closed deals the trader is terminated and a new one spawns, picking the trading pair
|
||||
from a pre-populated list (the trading pairs can be selected by using Yang-Zhang, Parkinson or another volatility indicator)
|
||||
This could be very benefitial, since it limits the long time commitment to a small list of trading pairs, enabling the instance to react to market trends very
|
||||
rapidly.
|
||||
|
||||
|
||||
Maybe it's a good idea?:
|
||||
|
|
|
|||
34
trader.py
34
trader.py
|
|
@ -27,6 +27,7 @@ class trader:
|
|||
self.check_slippage = True
|
||||
if "check_slippage" in self.config_dict:
|
||||
self.check_slippage = self.config_dict["check_slippage"]
|
||||
self.is_boosted = False
|
||||
self.start_time = int(time.time())
|
||||
self.total_amount_of_quote=0
|
||||
self.total_amount_of_base=1
|
||||
|
|
@ -344,6 +345,7 @@ class trader:
|
|||
|
||||
if self.so is not None and self.so["price"] is not None and self.so!=self.broker.get_empty_order():
|
||||
self.status_dict["next_so_price"]=self.so["price"]
|
||||
self.status_dict["is_boosted"]=self.is_boosted
|
||||
self.status_dict["is_short"]=self.is_short
|
||||
self.status_dict["quote_spent"]=self.total_amount_of_quote
|
||||
self.status_dict["base_bought"]=self.total_amount_of_base
|
||||
|
|
@ -1276,7 +1278,32 @@ class trader:
|
|||
2. Custom percentage table
|
||||
3. Linear percentage table
|
||||
'''
|
||||
|
||||
tp_level = 1
|
||||
boost = 0
|
||||
|
||||
#BOOST ROUTINE: If the trader closed certain amount of deals within the last t timespan, raise the take profit level by x%
|
||||
#Default values
|
||||
boosted_deals_range = 4
|
||||
boosted_time_range = 3600
|
||||
boosted_amount = .01
|
||||
|
||||
#Load config values (if present)
|
||||
if "boosted_deals_range" in self.config_dict:
|
||||
boosted_deals_range = self.config_dict["boosted_deals_range"]
|
||||
if "boosted_time_range" in self.config_dict:
|
||||
boosted_time_range = self.config_dict["boosted_time_range"]
|
||||
if "boosted_amount" in self.config_dict:
|
||||
boosted_amount = self.config_dict["boosted_amount"]
|
||||
|
||||
self.is_boosted = False
|
||||
|
||||
if not self.is_short:
|
||||
last_deals_timestamps = self.broker.return_last_n_deals_timestamps(self.pair,boosted_deals_range)
|
||||
if len(last_deals_timestamps)==boosted_deals_range and all(item >= time.time()-boosted_time_range for item in last_deals_timestamps):
|
||||
self.is_boosted = True
|
||||
boost+=boosted_amount
|
||||
|
||||
if self.is_short or self.config_dict["tp_mode"]==0: #Fixed take profit percentage
|
||||
tp_level = self.config_dict["tp_level"]
|
||||
elif self.config_dict["tp_mode"]==1: #Variable percentage
|
||||
|
|
@ -1300,7 +1327,7 @@ class trader:
|
|||
tp_level = profit_table[-1]
|
||||
if order_index<len(profit_table): #If more safety orders were added, instead of recalculating the whole table
|
||||
tp_level = profit_table[order_index] #it just returns the last value. Otherwise, the percentage gets very small.
|
||||
return 1+((tp_level-1)*multiplier)
|
||||
return 1+((tp_level+boost-1)*multiplier)
|
||||
|
||||
|
||||
def seconds_to_time(self, total_seconds: float) -> str:
|
||||
|
|
@ -1701,10 +1728,13 @@ class trader:
|
|||
|
||||
prices = f"{red}{low_boundary}{white}|{price_color}{mid_boundary}{white}|{target_price_color}{high_boundary}{white}|{pct_color}{pct_to_profit_str}%{white}"
|
||||
line1 = f"{p}{pair_color}{self.pair.center(13)}{white}| {safety_order_string} |{prices}| Uptime: {self.seconds_to_time(self.status_dict['deal_uptime'])}"
|
||||
if self.is_boosted:
|
||||
line1 = f"{line1} | BOOSTED"
|
||||
if self.config_dict["autoswitch"]:
|
||||
line1 = f"{line1} | AUTO"
|
||||
if self.is_short and "old_long" in self.status_dict:
|
||||
try:
|
||||
#When adding a trader, this line always throws an exception since status_dict["price"] is not yet populated
|
||||
percentage_to_switch = (self.status_dict["old_long"]["tp_price"]-self.status_dict["price"])*100/self.status_dict["price"]
|
||||
#line1 = f"{line1} {round(percentage_to_switch,2)}%"
|
||||
multiplier = int(percentage_to_switch/100)+1
|
||||
|
|
@ -1748,6 +1778,8 @@ class trader:
|
|||
self.start_time = self.status_dict["start_time"]
|
||||
self.deal_start_time = self.status_dict["deal_start_time"]
|
||||
self.stop_when_profit = self.status_dict["stop_when_profit"]
|
||||
if "is_boosted" in self.status_dict:
|
||||
self.is_boosted = self.status_dict["is_boosted"]
|
||||
if "deal_order_history" not in self.status_dict: #No longer needed?
|
||||
self.status_dict["deal_order_history"] = []
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue