665 lines
20 KiB
JavaScript
665 lines
20 KiB
JavaScript
// custom_blocks.js
|
|
// Define custom Blockly blocks and JSON code generation
|
|
|
|
export function defineCustomBlocks() {
|
|
|
|
// Register a new type for dynamic values if not already defined
|
|
Blockly.Types = Blockly.Types || {};
|
|
Blockly.Types.DYNAMIC_VALUE = 'dynamic_value';
|
|
|
|
// Generate dropdown options based on available data
|
|
const timeframeOptions = bt_data.intervals.map(interval => [interval, interval]);
|
|
const exchangeOptions = window.UI.exchanges.connected_exchanges.map(exchange => [exchange, exchange]);
|
|
const symbolOptions = bt_data.symbols.map(symbol => [symbol, symbol]);
|
|
|
|
/************************************************
|
|
* VALUE BLOCKS *
|
|
************************************************/
|
|
|
|
/**
|
|
* last_candle_value
|
|
* Retrieves a specific part of the last candle (Open, High, Low, Close) from a given source.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "last_candle_value",
|
|
"message0": "Last candle %1 value (Src): %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "candle_part",
|
|
"options": [
|
|
["Open", "open"],
|
|
["High", "high"],
|
|
["Low", "low"],
|
|
["Close", "close"]
|
|
]
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "source",
|
|
"check": "source"
|
|
}
|
|
],
|
|
"inputsInline": true,
|
|
"output": "dynamic_value",
|
|
"colour": 230,
|
|
"tooltip": "Retrieve the specified part of the last candle from the given source.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* strategy_profit_loss
|
|
* Evaluates the total strategy's profit or loss.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "strategy_profit_loss",
|
|
"message0": "Total Strategy %1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "METRIC",
|
|
"options": [
|
|
["profit", "profit"],
|
|
["loss", "loss"]
|
|
]
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value"
|
|
}
|
|
],
|
|
"inputsInline": true,
|
|
"output": "dynamic_value",
|
|
"colour": 230,
|
|
"tooltip": "Choose to evaluate the strategy's profit or loss.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* current_balance
|
|
* Retrieves the current balance of the strategy.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "current_balance",
|
|
"message0": "Current Balance %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value"
|
|
}
|
|
],
|
|
"output": "dynamic_value",
|
|
"colour": 230,
|
|
"tooltip": "Retrieve the current balance of the strategy.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* starting_balance
|
|
* Retrieves the starting balance of the strategy.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "starting_balance",
|
|
"message0": "Starting Balance %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value"
|
|
}
|
|
],
|
|
"output": "dynamic_value",
|
|
"colour": 230,
|
|
"tooltip": "Retrieve the starting balance of the strategy.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* active_trades
|
|
* Gets the number of active trades currently open.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "active_trades",
|
|
"message0": "Number of active trades %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value"
|
|
}
|
|
],
|
|
"output": "dynamic_value",
|
|
"colour": 230,
|
|
"tooltip": "Get the number of active trades currently open.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* math_operation
|
|
* Performs basic arithmetic operations between two values.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "math_operation",
|
|
"message0": "%1 %2 %3",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "left",
|
|
"check": ["number", "dynamic_value"]
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "operator",
|
|
"options": [
|
|
["+", "ADD"],
|
|
["-", "SUBTRACT"],
|
|
["*", "MULTIPLY"],
|
|
["/", "DIVIDE"]
|
|
]
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "right",
|
|
"check": ["number", "dynamic_value"]
|
|
}
|
|
],
|
|
"inputsInline": true,
|
|
"output": "dynamic_value",
|
|
"colour": 160,
|
|
"tooltip": "Perform basic arithmetic operations.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* value_input
|
|
* Allows users to input numerical values and chain multiple values for list creation.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "value_input",
|
|
"message0": "Value %1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_number",
|
|
"name": "VALUE",
|
|
"value": 0,
|
|
"min": 0
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value" // Accepts single or list of values
|
|
}
|
|
],
|
|
"output": "dynamic_value", // Custom type to handle single or list
|
|
"colour": 330,
|
|
"tooltip": "Enter a numerical value. Chain multiple for a list.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
/**
|
|
* source
|
|
* Defines the data source with Time Frame (TF), Exchange (Ex), and Symbol (Sym).
|
|
* Use with last_candle_value or any block that returns exchange related values.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "source",
|
|
"message0": "src: TF %1 Ex %2 Sym %3",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "TF",
|
|
"options": timeframeOptions
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "EXC",
|
|
"options": exchangeOptions
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "SYM",
|
|
"options": symbolOptions
|
|
}
|
|
],
|
|
"output": "source", // Allows connection to blocks expecting a 'source' type
|
|
"colour": 230,
|
|
"tooltip": "Choose the data feed source for the trade or value.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/************************************************
|
|
* LOGICAL BLOCKS *
|
|
************************************************/
|
|
|
|
/**
|
|
* logical_and
|
|
* Performs a logical AND operation between two Boolean conditions.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "logical_and",
|
|
"message0": "%1 AND %2",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "left",
|
|
"check": "Boolean"
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "right",
|
|
"check": "Boolean"
|
|
}
|
|
],
|
|
"inputsInline": true,
|
|
"output": "Boolean",
|
|
"colour": 210,
|
|
"tooltip": "Logical AND of two conditions.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* logical_or
|
|
* Performs a logical OR operation between two Boolean conditions.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "logical_or",
|
|
"message0": "%1 OR %2",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "left",
|
|
"check": "Boolean"
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "right",
|
|
"check": "Boolean"
|
|
}
|
|
],
|
|
"inputsInline": true,
|
|
"output": "Boolean",
|
|
"colour": 210,
|
|
"tooltip": "Logical OR of two conditions.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* is_false
|
|
* Checks if a given Boolean condition is false.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "is_false",
|
|
"message0": "%1 is false",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "condition",
|
|
"check": "Boolean"
|
|
}
|
|
],
|
|
"output": "Boolean",
|
|
"colour": 160,
|
|
"tooltip": "Checks if the condition is false.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/************************************************
|
|
* TRADE ORDER BLOCKS *
|
|
************************************************/
|
|
|
|
/**
|
|
* trade_action
|
|
* Executes a trade action (Buy/Sell) based on a Boolean condition, specifying the amount and optional trade options.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "trade_action",
|
|
"message0": "if %1 then %2 amount %3 %4 (Options) %5",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "condition",
|
|
"check": "Boolean"
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "tradeType",
|
|
"options": [
|
|
["Buy", "buy"],
|
|
["Sell", "sell"]
|
|
]
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "size",
|
|
"check": "dynamic_value" // Accepts single value or list
|
|
},
|
|
{
|
|
"type": "input_statement",
|
|
"name": "trade_options",
|
|
"check": "trade_option"
|
|
},
|
|
{
|
|
"type": "field_dummy" // Placeholder for alignment
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 230,
|
|
"tooltip": "Executes a trade with specified size and optional trade options.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
|
|
/**
|
|
* time_in_force
|
|
* Sets the time in force for the order (GTC, FOK, IOC).
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "time_in_force",
|
|
"message0": "Time in Force %1",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "tif",
|
|
"options": [
|
|
["GTC (Good Till Canceled)", "gtc"],
|
|
["FOK (Fill or Kill)", "fok"],
|
|
["IOC (Immediate or Cancel)", "ioc"]
|
|
]
|
|
}
|
|
],
|
|
"previousStatement": "trade_option",
|
|
"nextStatement": "trade_option",
|
|
"colour": 230,
|
|
"tooltip": "Select time in force for the order.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* stop_loss
|
|
* Sets the Stop Loss parameter for a trade.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "stop_loss",
|
|
"message0": "Stop Loss %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "stop_loss_input",
|
|
"check": ["number", "dynamic_value"] // Accepts numerical value or dynamic value
|
|
}
|
|
],
|
|
"previousStatement": "trade_option",
|
|
"nextStatement": "trade_option",
|
|
"colour": 230,
|
|
"tooltip": "Set Stop Loss parameters.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
|
|
/**
|
|
* take_profit
|
|
* Sets the Take Profit parameter for a trade.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "take_profit",
|
|
"message0": "Take Profit %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "take_profit_input",
|
|
"check": ["number", "dynamic_value"] // Accepts numerical value or dynamic value
|
|
}
|
|
],
|
|
"previousStatement": "trade_option",
|
|
"nextStatement": "trade_option",
|
|
"colour": 230,
|
|
"tooltip": "Set Take Profit parameters.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
|
|
/**
|
|
* limit
|
|
* Sets the Price parameter for a trade order.
|
|
* Accepts numerical value or dynamic value if a single value is provided
|
|
* the limit order will buy/sell at market price if the price reaches the
|
|
* provided value. If two values are provided a limit order will be set for the
|
|
* second value if the price reaches the first value.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "limit",
|
|
"message0": "Limit %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "limit_input",
|
|
"check": ["number", "dynamic_value"]
|
|
}
|
|
],
|
|
"previousStatement": "trade_option",
|
|
"nextStatement": "trade_option",
|
|
"colour": 230,
|
|
"tooltip": "Set Limit parameters.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
/**
|
|
* target_market
|
|
* Defines the target market for executing trades with specified Time Frame, Exchange, and Symbol.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "target_market",
|
|
"message0": "Target market: TF %1 Ex %2 Sym %3",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "TF",
|
|
"options": timeframeOptions
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "EXC",
|
|
"options": exchangeOptions
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "SYM",
|
|
"options": symbolOptions
|
|
}
|
|
],
|
|
"previousStatement": "trade_option", // Allows chaining with other trade options
|
|
"nextStatement": "trade_option",
|
|
"colour": 230,
|
|
"tooltip": "Choose the target market for executing trades.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/************************************************
|
|
* CONTROL BLOCKS *
|
|
************************************************/
|
|
|
|
/**
|
|
* Overrides all and pauses the strategy.
|
|
* No new orders will be placed while true.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "strategy_pause",
|
|
"message0": "If %1 halt strategy",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "flag_value",
|
|
"options": [["True", "True"], ["False", "False"]]
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 230,
|
|
"tooltip": "Set the flag to True to stop placing orders.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* Overrides all and pauses the strategy and exits trades.
|
|
* No new orders will be placed. The strategies open trades
|
|
* will be closed depending on the configuration.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "strategy_exit",
|
|
"message0": "If %1 exit strategy close %2 trades",
|
|
"args0": [
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "flag_value",
|
|
"options": [["True", "True"], ["False", "False"]]
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "option_value",
|
|
"options": [["all", "all"], ["in_profit", "in_profit"], ["in_loss", "in_loss"]]
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 230,
|
|
"tooltip": "Set the flag to True to stop placing orders.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/***************************************************
|
|
* INFO (FLAGS, VARIABLE, AND NOTIFICATION BLOCKS) *
|
|
***************************************************/
|
|
/**
|
|
* notify_user
|
|
* Sends a notification message to the user.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "notify_user",
|
|
"message0": "Notify User with Message %1",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "MESSAGE",
|
|
"text": "Your message here"
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 120,
|
|
"tooltip": "Sends a notification message to the user.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* get_variable
|
|
* Retrieves the value of a specified variable.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "get_variable",
|
|
"message0": "Get variable %1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "variable_name",
|
|
"text": "my_var"
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "NEXT",
|
|
"check": "dynamic_value"
|
|
}
|
|
],
|
|
"output": "dynamic_value",
|
|
"colour": 330,
|
|
"tooltip": "Get the value of a variable.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* set_variable
|
|
* Sets a specified variable to a given value.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "set_variable",
|
|
"message0": "Set variable %1 to %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "variable_name",
|
|
"text": "my_var"
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "value",
|
|
"check": ["number", "dynamic_value"] // Accepts numerical value or dynamic value
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 330,
|
|
"tooltip": "Set a variable to a value.",
|
|
"helpUrl": ""
|
|
}]);
|
|
/**
|
|
* flag_is_set
|
|
* Checks if a specified flag is set to True.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "flag_is_set",
|
|
"message0": "flag %1 is set",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "flag_name",
|
|
"text": "flag_name"
|
|
}
|
|
],
|
|
"output": "Boolean",
|
|
"colour": 160,
|
|
"tooltip": "Check if the specified flag is set to True.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
/**
|
|
* set_flag
|
|
* Sets a specified flag to True or False based on a Boolean condition.
|
|
*/
|
|
Blockly.defineBlocksWithJsonArray([{
|
|
"type": "set_flag",
|
|
"message0": "If %1 then set flag %2 to %3",
|
|
"args0": [
|
|
{
|
|
"type": "input_value", // Boolean condition
|
|
"name": "condition",
|
|
"check": "Boolean"
|
|
},
|
|
{
|
|
"type": "field_input",
|
|
"name": "flag_name",
|
|
"text": "flag_name"
|
|
},
|
|
{
|
|
"type": "field_dropdown",
|
|
"name": "flag_value",
|
|
"options": [["True", "True"], ["False", "False"]]
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 230,
|
|
"tooltip": "Set a flag to True or False if the condition is met.",
|
|
"helpUrl": ""
|
|
}]);
|
|
|
|
// Final log to confirm block definitions
|
|
console.log('Custom blocks defined with dynamic_value support and proper categorization');
|
|
}
|