Strtegies submit an are editable.
This commit is contained in:
parent
50bcfa05cd
commit
9d830fe8fa
|
|
@ -5,218 +5,57 @@
|
|||
"type": "strategy",
|
||||
"statements": [
|
||||
{
|
||||
"type": "execute_if",
|
||||
"type": "set_available_strategy_balance",
|
||||
"inputs": {
|
||||
"CONDITION": {
|
||||
"type": "comparison",
|
||||
"operator": "<",
|
||||
"BALANCE": {
|
||||
"type": "math_operation",
|
||||
"inputs": {
|
||||
"LEFT": {
|
||||
"type": "risk_ratio",
|
||||
"inputs": {}
|
||||
"operator": "add",
|
||||
"left_operand": 1,
|
||||
"right_operand": {
|
||||
"type": "math_operation",
|
||||
"inputs": {
|
||||
"operator": "add",
|
||||
"left_operand": {
|
||||
"type": "power",
|
||||
"inputs": {
|
||||
"base": 2,
|
||||
"exponent": 3
|
||||
}
|
||||
},
|
||||
"RIGHT": {
|
||||
"type": "dynamic_value",
|
||||
"values": [
|
||||
"right_operand": {
|
||||
"type": "math_operation",
|
||||
"inputs": {
|
||||
"operator": "multiply",
|
||||
"left_operand": {
|
||||
"type": "min",
|
||||
"inputs": {
|
||||
"numbers": [
|
||||
{
|
||||
"type": "current_balance",
|
||||
"inputs": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statements": {
|
||||
"DO": [
|
||||
{
|
||||
"type": "max_position_size",
|
||||
"inputs": {
|
||||
"MAX_SIZE": {
|
||||
"type": "available_balance",
|
||||
"inputs": {}
|
||||
}
|
||||
},
|
||||
"next": {
|
||||
"type": "execute_if",
|
||||
"inputs": {
|
||||
"CONDITION": {
|
||||
"type": "is_false",
|
||||
"inputs": {
|
||||
"condition": {
|
||||
"type": "order_status",
|
||||
"inputs": {
|
||||
"order_name": "order_name",
|
||||
"status": "filled"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statements": {
|
||||
"DO": [
|
||||
{
|
||||
"type": "execute_if",
|
||||
"inputs": {
|
||||
"CONDITION": {
|
||||
"type": "comparison",
|
||||
"operator": ">",
|
||||
"inputs": {
|
||||
"LEFT": {
|
||||
"type": "dynamic_value",
|
||||
"values": [
|
||||
{
|
||||
"type": "last_candle_value",
|
||||
"inputs": {
|
||||
"source": {},
|
||||
"candle_part": "open"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"RIGHT": {
|
||||
"type": "dynamic_value",
|
||||
"values": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statements": {
|
||||
"DO": [
|
||||
{
|
||||
"type": "trade_action",
|
||||
"trade_type": "buy",
|
||||
"inputs": {
|
||||
"size": {
|
||||
"type": "math_operation",
|
||||
"inputs": {
|
||||
"operator": "divide",
|
||||
"left_operand": {
|
||||
"type": "starting_balance",
|
||||
"inputs": {}
|
||||
},
|
||||
"right_operand": 15
|
||||
}
|
||||
}
|
||||
},
|
||||
"trade_options": [
|
||||
{
|
||||
"type": "name_order",
|
||||
"inputs": {
|
||||
"order_name": "order_name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "target_market",
|
||||
"inputs": {
|
||||
"time_frame": "15m",
|
||||
"exchange": "binance",
|
||||
"symbol": "ETH/BTC"
|
||||
}
|
||||
}
|
||||
5,
|
||||
6
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "execute_if",
|
||||
"inputs": {
|
||||
"CONDITION": {
|
||||
"type": "is_false",
|
||||
"inputs": {
|
||||
"condition": {
|
||||
"type": "order_status",
|
||||
"inputs": {
|
||||
"order_name": "order_name",
|
||||
"status": "filled"
|
||||
"right_operand": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statements": {
|
||||
"DO": [
|
||||
{
|
||||
"type": "execute_if",
|
||||
"inputs": {
|
||||
"CONDITION": {
|
||||
"type": "comparison",
|
||||
"operator": ">",
|
||||
"inputs": {
|
||||
"LEFT": {
|
||||
"type": "dynamic_value",
|
||||
"values": [
|
||||
{
|
||||
"type": "last_candle_value",
|
||||
"inputs": {
|
||||
"source": {},
|
||||
"candle_part": "open"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"RIGHT": {
|
||||
"type": "dynamic_value",
|
||||
"values": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"statements": {
|
||||
"DO": [
|
||||
{
|
||||
"type": "trade_action",
|
||||
"trade_type": "buy",
|
||||
"inputs": {
|
||||
"size": {
|
||||
"type": "math_operation",
|
||||
"inputs": {
|
||||
"operator": "divide",
|
||||
"left_operand": {
|
||||
"type": "starting_balance",
|
||||
"inputs": {}
|
||||
},
|
||||
"right_operand": 15
|
||||
}
|
||||
}
|
||||
},
|
||||
"trade_options": [
|
||||
{
|
||||
"type": "name_order",
|
||||
"inputs": {
|
||||
"order_name": "order_name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "target_market",
|
||||
"inputs": {
|
||||
"time_frame": "15m",
|
||||
"exchange": "binance",
|
||||
"symbol": "ETH/BTC"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"workspace": "<xml xmlns=\"https://developers.google.com/blockly/xml\"><block type=\"execute_if\" id=\"MsS{sEm446Tq-9cZ?LEM\" x=\"50\" y=\"110\"><comment pinned=\"false\" h=\"80\" w=\"160\">Execute the enclosed statements if the condition is true.</comment><value name=\"CONDITION\"><block type=\"comparison\" id=\"o$er@YT|44pRfD2*;kC%\"><field name=\"OPERATOR\"><</field><comment pinned=\"false\" h=\"80\" w=\"160\">Compare two values using operators like >, <, ==.</comment><value name=\"LEFT\"><block type=\"risk_ratio\" id=\"-{)}8vrsu.uQ`,}~MEf-\"><comment pinned=\"false\" h=\"80\" w=\"160\">Calculate and retrieve the current risk ratio.</comment></block></value><value name=\"RIGHT\"><block type=\"current_balance\" id=\"rG=}HE!*$H|BWca!-G+%\"><comment pinned=\"false\" h=\"80\" w=\"160\">Retrieve the current balance of the strategy.</comment></block></value></block></value><statement name=\"DO\"><block type=\"max_position_size\" id=\"p{Do;wN=r3%T.7QD!]H@\"><comment pinned=\"false\" h=\"80\" w=\"160\">Set a maximum limit on the number of positions the strategy can hold.</comment><value name=\"MAX_SIZE\"><block type=\"available_balance\" id=\"H;h(SZy-/g/;;|S_]YQb\"><comment pinned=\"false\" h=\"80\" w=\"160\">Retrieve the overall available (liquid) balance of the user.</comment></block></value><next><block type=\"execute_if\" id=\"85pyvJR)Fr*LmqgKnIUm\"><comment pinned=\"false\" h=\"80\" w=\"160\">Execute the enclosed statements if the condition is true.</comment><value name=\"CONDITION\"><block type=\"is_false\" id=\"(vRWbh:/a=bX}${W4(/t\"><comment pinned=\"false\" h=\"80\" w=\"160\">Check if a condition is false.</comment><value name=\"condition\"><block type=\"order_status\" id=\"v#j1BnPG5pKC$M?csI)8\"><field name=\"ORDER_NAME\">order_name</field><field name=\"order_status\">partial</field><comment pinned=\"false\" h=\"80\" w=\"160\">Get the status of a named order.</comment></block></value></block></value><statement name=\"DO\"><block type=\"execute_if\" id=\"+dPkaDvC^21ylWseCZV;\"><comment pinned=\"false\" h=\"80\" w=\"160\">Execute the enclosed statements if the condition is true.</comment><value name=\"CONDITION\"><block type=\"comparison\" id=\"YTu*wGkeOU0k4]D|(j*:\"><field name=\"OPERATOR\">></field><comment pinned=\"false\" h=\"80\" w=\"160\">Compare two values using operators like >, <, ==.</comment><value name=\"LEFT\"><block type=\"last_candle_value\" id=\"8h3nZn?#t3UXcuU}icCC\"><field name=\"candle_part\">open</field><comment pinned=\"false\" h=\"80\" w=\"160\">Retrieve a specific part (Open, High, Low, Close) of the last candle from a given source.</comment></block></value><value name=\"RIGHT\"><block type=\"value_input\" id=\"i|%1Z,IK5~WCR5t~[T=J\"><field name=\"VALUE\">44</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value></block></value><statement name=\"DO\"><block type=\"trade_action\" id=\"CYMHOlTFGfsK|l:ce{bX\"><field name=\"tradeType\">buy</field><comment pinned=\"false\" h=\"80\" w=\"160\">Execute a Buy/Sell trade based on a condition with specified size and options.</comment><value name=\"size\"><block type=\"math_operation\" id=\"^+dd,6d[Yg#w+bS|C{{S\"><field name=\"operator\">DIVIDE</field><comment pinned=\"false\" h=\"80\" w=\"160\">Perform basic arithmetic operations between two values.</comment><value name=\"LEFT\"><block type=\"starting_balance\" id=\"Bi5*6JEj#xP`DK9M1-p^\"><comment pinned=\"false\" h=\"80\" w=\"160\">Retrieve the starting balance of the strategy.</comment></block></value><value name=\"RIGHT\"><block type=\"value_input\" id=\".kd4Xeke%72-6/tdATz(\"><field name=\"VALUE\">15</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value></block></value><statement name=\"trade_options\"><block type=\"name_order\" id=\"c;$K`P/c1nf2Ut)yJf=]\"><field name=\"order_name\">order_name</field><comment pinned=\"false\" h=\"80\" w=\"160\">Assign a custom name to the current order.</comment><next><block type=\"target_market\" id=\"FsX9_==AQf?DKtj]1C`]\"><field name=\"TF\">15m</field><field name=\"EXC\">binance</field><field name=\"SYM\">ETH/BTC</field><comment pinned=\"false\" h=\"80\" w=\"160\">Choose the target market for posting orders.</comment></block></next></block></statement></block></statement></block></statement></block></next></block></statement></block></xml>"
|
||||
"workspace": "<xml xmlns=\"https://developers.google.com/blockly/xml\"><block type=\"set_available_strategy_balance\" id=\"AC+~IeO;#NLcE`*p`-{8\" x=\"-250\" y=\"130\"><comment pinned=\"false\" h=\"80\" w=\"160\">Set the balance allocated to the strategy.</comment><value name=\"BALANCE\"><block type=\"math_operation\" id=\"|-W{hIFm.z5Bd#m-OZs}\"><field name=\"operator\">ADD</field><comment pinned=\"false\" h=\"80\" w=\"160\">Perform basic arithmetic operations between two values.</comment><value name=\"LEFT\"><block type=\"value_input\" id=\"3`4X?VL:]|2FbEiMRz]f\"><field name=\"VALUE\">1</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value><value name=\"RIGHT\"><block type=\"math_operation\" id=\"%~{X-%0Q37cn0L2aul,8\"><field name=\"operator\">ADD</field><comment pinned=\"false\" h=\"80\" w=\"160\">Perform basic arithmetic operations between two values.</comment><value name=\"LEFT\"><block type=\"power\" id=\"3;*+0$b19;lFVk%5iR({\"><comment pinned=\"false\" h=\"80\" w=\"160\">Raise a number to the power of another number (x^y).</comment><value name=\"VALUES\"><block type=\"value_input\" id=\"z`L(+hvv*Fu#slvL`yDj\"><field name=\"VALUE\">2</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment><value name=\"NEXT\"><block type=\"value_input\" id=\"r6%+3l|2TezFf/hj^5:o\"><field name=\"VALUE\">3</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value></block></value></block></value><value name=\"RIGHT\"><block type=\"math_operation\" id=\"(O686k#xdA9_nW5]s4*;\"><field name=\"operator\">MULTIPLY</field><comment pinned=\"false\" h=\"80\" w=\"160\">Perform basic arithmetic operations between two values.</comment><value name=\"LEFT\"><block type=\"min\" id=\"{XPyvd;n_o~??i(P65Yi\"><comment pinned=\"false\" h=\"80\" w=\"160\">Determine the minimum value among given numbers.</comment><value name=\"VALUES\"><block type=\"current_balance\" id=\"BapPJm/W8_)QeI98~JF6\"><comment pinned=\"false\" h=\"80\" w=\"160\">Retrieve the current balance of the strategy.</comment><value name=\"VALUES\"><block type=\"value_input\" id=\"4:wZlOvQQJ}b)cO6MSh~\"><field name=\"VALUE\">5</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment><value name=\"NEXT\"><block type=\"value_input\" id=\"L.Hk_E@2r6#_F)1UrrZG\"><field name=\"VALUE\">6</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value></block></value></block></value></block></value><value name=\"RIGHT\"><block type=\"value_input\" id=\"xjq($pfgII*[?r|Mu:*F\"><field name=\"VALUE\">4</field><comment pinned=\"false\" h=\"80\" w=\"160\">Enter a numerical value. Chain multiple for a list.</comment></block></value></block></value></block></value></block></value></block></xml>"
|
||||
}
|
||||
"""
|
||||
|
|
@ -345,11 +345,10 @@ class BrighterTrades:
|
|||
return {"success": False, "message": "Invalid or empty strategy name"}
|
||||
if not isinstance(data['workspace'], str) or not data['workspace'].strip():
|
||||
return {"success": False, "message": "Invalid or empty workspace data"}
|
||||
if not isinstance(data['code'], list) or not data['code']:
|
||||
if not isinstance(data['code'], dict) or not data['code']:
|
||||
return {"success": False, "message": "Invalid or empty strategy code"}
|
||||
|
||||
# Serialize code to JSON string for storage
|
||||
import json
|
||||
code_json = json.dumps(data['code'])
|
||||
|
||||
# Prepare the strategy data for insertion
|
||||
|
|
|
|||
|
|
@ -744,7 +744,15 @@ class Strategies:
|
|||
if not node_type:
|
||||
continue # Skip nodes without a type
|
||||
|
||||
if node_type == 'trade_action':
|
||||
if node_type == 'strategy':
|
||||
# Process the 'strategy' node
|
||||
statements = node.get('statements', [])
|
||||
if statements:
|
||||
code_lines.extend(self.generate_code_from_json(statements, default_source, indent_level))
|
||||
elif node_type == 'execute_if':
|
||||
# Handle 'execute_if' node
|
||||
code_lines.extend(self.handle_execute_if(node, default_source, indent_level))
|
||||
elif node_type == 'trade_action':
|
||||
code_lines.extend(self.handle_trade_action(node, default_source, indent_level))
|
||||
elif node_type == 'set_flag':
|
||||
code_lines.extend(self.handle_set_flag(node, indent_level))
|
||||
|
|
@ -783,6 +791,9 @@ class Strategies:
|
|||
:param condition_node: The condition node.
|
||||
:return: A string representing the condition.
|
||||
"""
|
||||
if not isinstance(condition_node, dict):
|
||||
# If condition_node is not a dict, return its string representation
|
||||
return str(condition_node)
|
||||
node_type = condition_node.get('type')
|
||||
if not node_type:
|
||||
return 'False' # Default to False if node type is missing
|
||||
|
|
@ -790,8 +801,9 @@ class Strategies:
|
|||
# Handling different condition types
|
||||
if node_type == 'comparison':
|
||||
operator = condition_node.get('operator')
|
||||
left_node = condition_node.get('left_operand') # Ensure consistent key
|
||||
right_node = condition_node.get('right_operand')
|
||||
inputs = condition_node.get('inputs', {})
|
||||
left_node = inputs.get('LEFT')
|
||||
right_node = inputs.get('RIGHT')
|
||||
left_expr = self.generate_condition_code(left_node)
|
||||
right_expr = self.generate_condition_code(right_node)
|
||||
operator_map = {
|
||||
|
|
@ -805,6 +817,19 @@ class Strategies:
|
|||
python_operator = operator_map.get(operator, operator)
|
||||
return f"({left_expr} {python_operator} {right_expr})"
|
||||
|
||||
elif node_type == 'dynamic_value':
|
||||
values = condition_node.get('values', [])
|
||||
if len(values) == 1:
|
||||
value = values[0]
|
||||
if isinstance(value, dict):
|
||||
return self.generate_condition_code(value)
|
||||
else:
|
||||
# If value is not a dict, return its string representation
|
||||
return str(value)
|
||||
else:
|
||||
# Handle lists of values if necessary
|
||||
return '0'
|
||||
|
||||
elif node_type == 'logical_and':
|
||||
conditions = condition_node.get('conditions', [])
|
||||
condition_exprs = [self.generate_condition_code(cond) for cond in conditions]
|
||||
|
|
@ -1084,8 +1109,11 @@ class Strategies:
|
|||
|
||||
# Return the inputted value.
|
||||
elif node_type == 'value_input':
|
||||
value = condition_node.get('value', 0)
|
||||
return str(value)
|
||||
values = condition_node.get('values', [])
|
||||
if len(values) == 1:
|
||||
return str(values[0])
|
||||
else:
|
||||
return '0'
|
||||
|
||||
# Return a number
|
||||
elif node_type == 'number':
|
||||
|
|
@ -1101,6 +1129,23 @@ class Strategies:
|
|||
logger.warning(f"Unhandled condition node type: {node_type}")
|
||||
return 'False' # Default to False for unhandled types
|
||||
|
||||
def handle_execute_if(self, node: dict, default_source: dict, indent_level: int) -> list[str]:
|
||||
code_lines = []
|
||||
indent = ' ' * indent_level
|
||||
|
||||
condition_node = node.get('inputs', {}).get('CONDITION')
|
||||
if not condition_node:
|
||||
logger.error("Condition missing in 'execute_if' node.")
|
||||
return code_lines
|
||||
|
||||
condition_code = self.generate_condition_code(condition_node)
|
||||
code_lines.append(f"{indent}if {condition_code}:")
|
||||
# Process the 'DO' statements under this condition
|
||||
do_statements = node.get('statements', {}).get('DO', [])
|
||||
code_lines.extend(self.generate_code_from_json(do_statements, default_source, indent_level + 1))
|
||||
|
||||
return code_lines
|
||||
|
||||
def handle_strategy_pause(self, node: dict, indent_level: int) -> list[str]:
|
||||
"""
|
||||
Handles the 'strategy_pause' node type.
|
||||
|
|
@ -1146,8 +1191,16 @@ class Strategies:
|
|||
nested_actions = node.get('statements', {}).get('DO', [])
|
||||
resume_conditions.extend(self.extract_resume_conditions(nested_actions))
|
||||
elif 'statements' in node:
|
||||
resume_conditions.extend(self.extract_resume_conditions(node['statements'].get('DO', [])))
|
||||
|
||||
statements = node['statements']
|
||||
if isinstance(statements, dict):
|
||||
do_statements = statements.get('DO', [])
|
||||
resume_conditions.extend(self.extract_resume_conditions(do_statements))
|
||||
elif isinstance(statements, list):
|
||||
for sub_node in statements:
|
||||
resume_conditions.extend(self.extract_resume_conditions(sub_node))
|
||||
else:
|
||||
# Handle other possible types if necessary
|
||||
pass
|
||||
return resume_conditions
|
||||
|
||||
def handle_strategy_exit(self, node: dict, indent_level: int) -> list[str]:
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ class StratUIManager {
|
|||
try {
|
||||
await this.workspaceManager.initWorkspace();
|
||||
console.log("Blockly workspace initialized.");
|
||||
// Restore workspace from XML if editing
|
||||
if (action === 'edit' && strategyData && strategyData.workspace) {
|
||||
this.workspaceManager.loadWorkspaceFromXml(strategyData.workspace);
|
||||
console.log("Workspace restored from XML.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize Blockly workspace:", error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue