brighter-trading/archived_code/json_generators.js

644 lines
22 KiB
JavaScript

// client/json_generators.js
export function defineJsonGenerators() {
// Initialize the JSON generator if not already initialized
if (!Blockly.JSON) {
Blockly.JSON = new Blockly.Generator('JSON');
}
// Define order constants needed for the JSON generator
Blockly.JSON.ORDER_ATOMIC = 0; // Highest precedence
Blockly.JSON.ORDER_NONE = 99; // Lowest precedence
/**
* Override the default blockToCode method to generate JSON.
*/
Blockly.JSON.blockToCode = function(block) {
if (!block) {
return '';
}
var func = this[block.type];
if (typeof func !== 'function') {
throw Error('JSON generator does not know how to generate code for block type "' + block.type + '".');
}
var code = func.call(this, block);
return code;
};
/**
* Generate JSON for a value input.
* @param {Blockly.Block} block Block to generate code from.
* @param {string} name Name of the input.
* @param {number} outerOrder The current operation order.
* @returns {string} JSON string of the input value.
*/
Blockly.JSON.valueToCode = function(block, name, outerOrder) {
if (isNaN(outerOrder)) {
throw Error('Expecting valid order from block: ' + block);
}
var targetBlock = block.getInputTargetBlock(name);
if (!targetBlock) {
return '';
}
var code = this.blockToCode(targetBlock);
if (code === '') {
return '';
}
return code;
};
/**
* Generate JSON for a statement input.
* @param {Blockly.Block} block Block to generate code from.
* @param {string} name Name of the input.
* @returns {string} JSON string of the statement.
*/
Blockly.JSON.statementToCode = function(block, name) {
var targetBlock = block.getInputTargetBlock(name);
var code = '';
while (targetBlock) {
var line = this.blockToCode(targetBlock);
if (line) {
code += line;
}
targetBlock = targetBlock.getNextBlock();
}
return code;
};
/**
* Helper function to safely parse JSON strings.
* Returns an empty object if parsing fails.
* @param {string} jsonString The JSON string to parse.
* @returns {Object} Parsed JSON object or empty object on failure.
*/
function safeParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch (e) {
console.error("JSON Parsing Error:", e);
return {};
}
}
/************************************************
* VALUE BLOCKS *
************************************************/
/**
* last_candle_value
* Retrieves a specific part of the last candle (Open, High, Low, Close) from a given source.
* Generates a JSON object with type, candle_part, and source.
*/
Blockly.JSON['last_candle_value'] = function(block) {
const candlePart = block.getFieldValue('candle_part'); // e.g., 'open', 'high', 'low', 'close'
const provided_source = Blockly.JSON.valueToCode(block, 'source', Blockly.JSON.ORDER_ATOMIC) || null;
let defined_source;
if (!provided_source){
const symbolElement = document.getElementById('symbol');
const timeframeElement = document.getElementById('timeframe');
const exchangeElement = document.getElementById('exchange_name');
if (symbolElement && timeframeElement && exchangeElement) {
defined_source = {
symbol: symbolElement.value,
timeframe: timeframeElement.value,
exchange_name: exchangeElement.value
};
} else {
console.error('One or more source elements are missing in the DOM.');
defined_source = {};
}
} else {
// Assume `provided_source` is a JSON string or JavaScript code that represents a source object
defined_source = safeParse(provided_source);
}
const json = {
type: 'last_candle_value',
candle_part: candlePart,
source: defined_source
};
return JSON.stringify(json); // Ensure that Blockly expects a JSON string
};
/**
* strategy_profit_loss
* Evaluates the total strategy's profit or loss with comparison operators.
* Generates a JSON object with type, metric, operator, and value.
*/
Blockly.JSON['strategy_profit_loss'] = function(block) {
const metric = block.getFieldValue('METRIC'); // 'profit' or 'loss'
const operator = block.getFieldValue('OPERATOR'); // '>', '<', '>=', '<=', '==', '!='
const valueCode = Blockly.JSON.valueToCode(block, 'VALUE', Blockly.JSON.ORDER_ATOMIC) || "0";
const value = safeParse(valueCode) || parseFloat(valueCode);
const json = {
type: 'strategy_profit_loss',
metric: metric,
operator: operator,
value: value
};
return JSON.stringify(json);
};
/**
* current_balance
* Retrieves the current balance of the strategy.
* Generates a JSON object with type.
* If 'NEXT' is connected, includes additional balance information.
*/
Blockly.JSON['current_balance'] = function(block) {
const json = {
type: 'current_balance'
};
const nextBlock = block.getInputTargetBlock('NEXT');
if (nextBlock) {
const nextCode = this.blockToCode(nextBlock);
const nextJson = safeParse(nextCode);
json.next = nextJson;
}
return JSON.stringify(json);
};
/**
* starting_balance
* Retrieves the starting balance of the strategy.
* Generates a JSON object with type.
* If 'NEXT' is connected, includes additional starting balance information.
*/
Blockly.JSON['starting_balance'] = function(block) {
const json = {
type: 'starting_balance'
};
const nextBlock = block.getInputTargetBlock('NEXT');
if (nextBlock) {
const nextCode = this.blockToCode(nextBlock);
const nextJson = safeParse(nextCode);
json.next = nextJson;
}
return JSON.stringify(json);
};
/**
* active_trades
* Gets the number of active trades currently open.
* Generates a JSON object with type.
* If 'NEXT' is connected, includes additional active trades information.
*/
Blockly.JSON['active_trades'] = function(block) {
const json = {
type: 'active_trades'
};
const nextBlock = block.getInputTargetBlock('NEXT');
if (nextBlock) {
const nextCode = this.blockToCode(nextBlock);
const nextJson = safeParse(nextCode);
json.next = nextJson;
}
return JSON.stringify(json);
};
/**
* math_operation
* Performs basic arithmetic operations between two values.
* Generates a JSON object with type, operator, left_operand, and right_operand.
*/
Blockly.JSON['math_operation'] = function(block) {
const operator = block.getFieldValue('operator'); // '+', '-', '*', '/'
const leftCode = Blockly.JSON.valueToCode(block, 'left', Blockly.JSON.ORDER_ATOMIC) || "0";
const rightCode = Blockly.JSON.valueToCode(block, 'right', Blockly.JSON.ORDER_ATOMIC) || "0";
const leftValue = safeParse(leftCode) || leftCode;
const rightValue = safeParse(rightCode) || rightCode;
const json = {
type: 'math_operation',
operator: operator,
left_operand: leftValue,
right_operand: rightValue
};
return JSON.stringify(json);
};
/**
* value_input
* Allows users to input numerical values and chain multiple values for list creation.
* Generates a JSON object with type and value.
* If 'NEXT' is connected, includes additional values.
*/
Blockly.JSON['value_input'] = function(block) {
const value = parseFloat(block.getFieldValue('VALUE')) || 0;
const json = {
type: 'value_input',
value: value
};
const nextBlock = block.getInputTargetBlock('NEXT');
if (nextBlock) {
const nextCode = this.blockToCode(nextBlock);
const nextJson = safeParse(nextCode);
if (Array.isArray(json.next_values)) {
json.next_values.push(nextJson);
} else {
json.next_values = [json.value, nextJson.value];
}
}
return JSON.stringify(json);
};
/**
* source
* Defines the data source with Time Frame (TF), Exchange (Ex), and Symbol (Sym).
* Generates a JSON object with timeframe, exchange, and symbol.
*/
Blockly.JSON['source'] = function(block) {
const timeframe = block.getFieldValue('TF'); // e.g., '5m', '1h'
const exchange = block.getFieldValue('EXC'); // e.g., 'Binance'
const symbol = block.getFieldValue('SYM'); // e.g., 'BTCUSD'
const json = {
timeframe: timeframe,
exchange: exchange,
symbol: symbol
};
return JSON.stringify(json);
};
/************************************************
* LOGICAL BLOCKS *
************************************************/
/**
* logical_and
* Performs a logical AND operation between two Boolean conditions.
* Generates a JSON object with type and conditions.
*/
Blockly.JSON['logical_and'] = function(block) {
const condition1Code = Blockly.JSON.valueToCode(block, 'left', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition2Code = Blockly.JSON.valueToCode(block, 'right', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition1 = safeParse(condition1Code) || condition1Code;
const condition2 = safeParse(condition2Code) || condition2Code;
const json = {
type: 'logical_and',
conditions: [condition1, condition2]
};
return JSON.stringify(json);
};
/**
* logical_or
* Performs a logical OR operation between two Boolean conditions.
* Generates a JSON object with type and conditions.
*/
Blockly.JSON['logical_or'] = function(block) {
const condition1Code = Blockly.JSON.valueToCode(block, 'left', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition2Code = Blockly.JSON.valueToCode(block, 'right', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition1 = safeParse(condition1Code) || condition1Code;
const condition2 = safeParse(condition2Code) || condition2Code;
const json = {
type: 'logical_or',
conditions: [condition1, condition2]
};
return JSON.stringify(json);
};
/**
* is_false
* Checks if a given Boolean condition is false.
* Generates a JSON object with type and condition.
*/
Blockly.JSON['is_false'] = function(block) {
const conditionCode = Blockly.JSON.valueToCode(block, 'condition', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition = safeParse(conditionCode) || conditionCode;
const json = {
type: 'is_false',
condition: condition
};
return JSON.stringify(json);
};
/**
* comparison
* Compares two numerical or dynamic values using operators like >, <, ==.
* Generates a JSON object with type, operator, left_operand, and right_operand.
*/
Blockly.JSON['comparison'] = function(block) {
const operator = block.getFieldValue('operator'); // '>', '<', '=='
const leftCode = Blockly.JSON.valueToCode(block, 'left', Blockly.JSON.ORDER_ATOMIC) || "0";
const rightCode = Blockly.JSON.valueToCode(block, 'right', Blockly.JSON.ORDER_ATOMIC) || "0";
const leftValue = safeParse(leftCode) || leftCode;
const rightValue = safeParse(rightCode) || rightCode;
const json = {
type: 'comparison',
operator: operator,
left_operand: leftValue,
right_operand: rightValue
};
return JSON.stringify(json);
};
/************************************************
* TRADE ORDER BLOCKS *
************************************************/
/**
* trade_action
* Executes a trade action (Buy/Sell) based on a Boolean condition, specifying the amount and optional trade options.
* Generates a JSON object with type, condition, trade_type, size, and trade_options.
*/
Blockly.JSON['trade_action'] = function(block) {
const conditionCode = Blockly.JSON.valueToCode(block, 'condition', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition = safeParse(conditionCode) || conditionCode;
const tradeType = block.getFieldValue('tradeType'); // 'buy' or 'sell'
const sizeCode = Blockly.JSON.valueToCode(block, 'size', Blockly.JSON.ORDER_ATOMIC) || "0";
const size = safeParse(sizeCode) || parseFloat(sizeCode);
const tradeOptionsCode = Blockly.JSON.statementToCode(block, 'trade_options').trim();
let tradeOptions = [];
if (tradeOptionsCode) {
try {
tradeOptions = JSON.parse(tradeOptionsCode);
if (!Array.isArray(tradeOptions)) {
tradeOptions = [tradeOptions];
}
} catch (e) {
console.error("Trade Options Parsing Error:", e);
tradeOptions = [];
}
}
const json = {
type: 'trade_action',
condition: condition,
trade_type: tradeType,
size: size,
trade_options: tradeOptions
};
return JSON.stringify(json);
};
/**
* time_in_force
* Sets the time in force for the order (GTC, FOK, IOC).
* Generates a JSON object with type and tif.
*/
Blockly.JSON['time_in_force'] = function(block) {
const tif = block.getFieldValue('tif'); // 'gtc', 'fok', 'ioc'
const json = {
type: 'time_in_force',
tif: tif
};
return JSON.stringify(json);
};
/**
* stop_loss
* Sets the Stop Loss parameter for a trade.
* Generates a JSON object with type and stop_loss.
*/
Blockly.JSON['stop_loss'] = function(block) {
const stopLossCode = Blockly.JSON.valueToCode(block, 'stop_loss_input', Blockly.JSON.ORDER_ATOMIC) || "0";
const stop_loss = safeParse(stopLossCode) || parseFloat(stopLossCode);
const json = {
type: 'stop_loss',
stop_loss: stop_loss
};
return JSON.stringify(json);
};
/**
* take_profit
* Sets the Take Profit parameter for a trade.
* Generates a JSON object with type and take_profit.
*/
Blockly.JSON['take_profit'] = function(block) {
const takeProfitCode = Blockly.JSON.valueToCode(block, 'take_profit_input', Blockly.JSON.ORDER_ATOMIC) || "0";
const take_profit = safeParse(takeProfitCode) || parseFloat(takeProfitCode);
const json = {
type: 'take_profit',
take_profit: take_profit
};
return JSON.stringify(json);
};
/**
* limit
* Sets the Limit parameter for a trade order.
* Generates a JSON object with type and limit_price.
*/
Blockly.JSON['limit'] = function(block) {
const limitCode = Blockly.JSON.valueToCode(block, 'limit_input', Blockly.JSON.ORDER_ATOMIC) || "0";
const limit_price = safeParse(limitCode) || parseFloat(limitCode);
const json = {
type: 'limit',
limit_price: limit_price
};
return JSON.stringify(json);
};
/**
* target_market
* Defines the target market for executing trades with specified Time Frame, Exchange, and Symbol.
* Generates a JSON object with type, timeframe, exchange, and symbol.
*/
Blockly.JSON['target_market'] = function(block) {
const timeframe = block.getFieldValue('TF'); // e.g., '5m', '1h'
const exchange = block.getFieldValue('EXC'); // e.g., 'Binance'
const symbol = block.getFieldValue('SYM'); // e.g., 'BTCUSD'
const json = {
type: 'target_market',
timeframe: timeframe,
exchange: exchange,
symbol: symbol
};
return JSON.stringify(json);
};
/************************************************
* CONTROL BLOCKS *
************************************************/
/**
* strategy_pause
* Overrides all and pauses the strategy. No new orders will be placed while the condition is true.
* Generates a JSON object with type and pause_condition.
*/
Blockly.JSON['strategy_pause'] = function(block) {
const conditionCode = Blockly.JSON.valueToCode(block, 'condition', Blockly.JSON.ORDER_ATOMIC) || "false";
const pause_condition = safeParse(conditionCode) || conditionCode;
const json = {
type: 'strategy_pause',
pause_condition: pause_condition
};
return JSON.stringify(json);
};
/**
* strategy_exit
* Overrides all, pauses the strategy, and exits trades based on configuration.
* Generates a JSON object with type, exit_condition, and exit_option.
*/
Blockly.JSON['strategy_exit'] = function(block) {
const conditionCode = Blockly.JSON.valueToCode(block, 'condition', Blockly.JSON.ORDER_ATOMIC) || "false";
const exit_condition = safeParse(conditionCode) || conditionCode;
const exit_option = block.getFieldValue('option_value'); // 'all', 'in_profit', 'in_loss'
const json = {
type: 'strategy_exit',
exit_condition: exit_condition,
exit_option: exit_option
};
return JSON.stringify(json);
};
/************************************************
* INFO BLOCKS *
************************************************/
/**
* notify_user
* Sends a notification message to the user.
* Generates a JSON object with type and message.
*/
Blockly.JSON['notify_user'] = function(block) {
const messageCode = Blockly.JSON.valueToCode(block, 'MESSAGE', Blockly.JSON.ORDER_ATOMIC) || '"Your message here"';
const message = safeParse(messageCode) || messageCode;
const json = {
type: 'notify_user',
message: message
};
return JSON.stringify(json);
};
/**
* get_variable
* Retrieves the value of a specified variable.
* Generates a JSON object with type, variable_name, and next_value.
*/
Blockly.JSON['get_variable'] = function(block) {
const variableName = block.getFieldValue('variable_name'); // e.g., 'my_var'
const json = {
type: 'get_variable',
variable_name: variableName
};
const nextBlock = block.getInputTargetBlock('NEXT');
if (nextBlock) {
const nextCode = this.blockToCode(nextBlock);
const nextJson = safeParse(nextCode);
json.next_value = nextJson;
}
return JSON.stringify(json);
};
/**
* set_variable
* Sets a specified variable to a given value.
* Generates a JSON object with type, variable_name, and value.
*/
Blockly.JSON['set_variable'] = function(block) {
const variableName = block.getFieldValue('variable_name'); // e.g., 'my_var'
const valueCode = Blockly.JSON.valueToCode(block, 'value', Blockly.JSON.ORDER_ATOMIC) || "0";
const value = safeParse(valueCode) || parseFloat(valueCode);
const json = {
type: 'set_variable',
variable_name: variableName,
value: value
};
return JSON.stringify(json);
};
/**
* flag_is_set
* Checks if a specified flag is set to True.
* Generates a JSON object with type and flag_name.
*/
Blockly.JSON['flag_is_set'] = function(block) {
const flagName = block.getFieldValue('flag_name'); // e.g., 'flag1'
const json = {
type: 'flag_is_set',
flag_name: flagName
};
return JSON.stringify(json);
};
/**
* set_flag
* Sets a specified flag to True or False based on a Boolean condition.
* Generates a JSON object with type, condition, flag_name, and flag_value.
*/
Blockly.JSON['set_flag'] = function(block) {
const conditionCode = Blockly.JSON.valueToCode(block, 'condition', Blockly.JSON.ORDER_ATOMIC) || "false";
const condition = safeParse(conditionCode) || conditionCode;
const flagName = block.getFieldValue('flag_name'); // e.g., 'flag1'
const flagValue = block.getFieldValue('flag_value'); // 'True' or 'False'
const flag_value_bool = flagValue === 'True' ? true : false;
const json = {
type: 'set_flag',
condition: condition,
flag_name: flagName,
flag_value: flag_value_bool
};
return JSON.stringify(json);
};
/************************************************
* END OF json_generators.js *
************************************************/
console.log('Custom JSON generators defined successfully.');
}