// Define Python generators for custom blocks export function definePythonGenerators() { // Python Generator for target_market Blockly.Python['target_market'] = Blockly.Python.forBlock['target_market'] = function(block) { var timeframe = block.getFieldValue('TF'); var exchange = block.getFieldValue('EXC'); var symbol = block.getFieldValue('SYM'); var code = `target_market(timeframe='${timeframe}', exchange='${exchange}', symbol='${symbol}')`; return code; }; // Generator for last_candle_value Blockly.Python['last_candle_value'] = Blockly.Python.forBlock['last_candle_value'] = function(block) { var candlePart = block.getFieldValue('CANDLE_PART'); var source = Blockly.Python.valueToCode(block, 'SOURCE', Blockly.Python.ORDER_ATOMIC) || 'None'; // Handle optional source var code; if (source !== 'None') { // Use the provided source feed if available code = `get_last_candle_value('${candlePart}', source=${source})`; } else { // Fallback to default source code = `get_last_candle_value('${candlePart}')`; } return [code, Blockly.Python.ORDER_ATOMIC]; }; // Comparison block to Python code Blockly.Python['comparison'] = Blockly.Python.forBlock['comparison'] = function(block) { const left = Blockly.Python.valueToCode(block, 'LEFT', Blockly.Python.ORDER_ATOMIC); const right = Blockly.Python.valueToCode(block, 'RIGHT', Blockly.Python.ORDER_ATOMIC); const operator = block.getFieldValue('OPERATOR'); return [left + ' ' + operator + ' ' + right, Blockly.Python.ORDER_ATOMIC]; }; // Logical OR block to Python code Blockly.Python['logical_or'] = Blockly.Python.forBlock['logical_or'] = function(block) { var left = Blockly.Python.valueToCode(block, 'LEFT', Blockly.Python.ORDER_ATOMIC); var right = Blockly.Python.valueToCode(block, 'RIGHT', Blockly.Python.ORDER_ATOMIC); var code = `${left} or ${right}`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Logical AND block to Python code Blockly.Python['logical_and'] = Blockly.Python.forBlock['logical_and'] = function(block) { var left = Blockly.Python.valueToCode(block, 'LEFT', Blockly.Python.ORDER_ATOMIC); var right = Blockly.Python.valueToCode(block, 'RIGHT', Blockly.Python.ORDER_ATOMIC); var code = `${left} and ${right}`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Stop Loss block to Python code Blockly.Python['stop_loss'] = Blockly.Python.forBlock['stop_loss'] = function(block) { var stopLoss = Blockly.Python.valueToCode(block, 'STOP_LOSS', Blockly.Python.ORDER_ATOMIC); return [stopLoss, Blockly.Python.ORDER_ATOMIC]; }; // Take Profit block to Python code Blockly.Python['take_profit'] = Blockly.Python.forBlock['take_profit'] = function(block) { var takeProfit = Blockly.Python.valueToCode(block, 'TAKE_PROFIT', Blockly.Python.ORDER_ATOMIC); return [takeProfit, Blockly.Python.ORDER_ATOMIC]; }; // Python generator for is_false block Blockly.Python['is_false'] =Blockly.Python.forBlock['is_false']= function(block) { var condition = Blockly.Python.valueToCode(block, 'CONDITION', Blockly.Python.ORDER_ATOMIC); var code = `not ${condition}`; return [code, Blockly.Python.ORDER_ATOMIC]; }; Blockly.Python['trade_action'] = Blockly.Python.forBlock['trade_action'] = function(block) { const condition = Blockly.Python.valueToCode(block, 'CONDITION', Blockly.Python.ORDER_ATOMIC); const tradeType = block.getFieldValue('TRADE_TYPE'); const size = Blockly.Python.valueToCode(block, 'SIZE', Blockly.Python.ORDER_ATOMIC) || 'None'; const stopLoss = Blockly.Python.valueToCode(block, 'STOP_LOSS', Blockly.Python.ORDER_ATOMIC) || 'None'; const takeProfit = Blockly.Python.valueToCode(block, 'TAKE_PROFIT', Blockly.Python.ORDER_ATOMIC) || 'None'; // Process trade options let tradeOptionsCode = Blockly.Python.statementToCode(block, 'TRADE_OPTIONS').trim(); tradeOptionsCode = tradeOptionsCode.split('\n').filter(line => line.trim() !== ''); // Collect all arguments into an array const argsList = [`size=${size}`, `stop_loss=${stopLoss}`, `take_profit=${takeProfit}`]; if (tradeOptionsCode.length > 0) { argsList.push(...tradeOptionsCode); } const args = argsList.join(', '); const code = `if ${condition}:\n self.${tradeType}(${args})\n`; return code; }; // Order Type block to Python code Blockly.Python['order_type'] = Blockly.Python.forBlock['order_type'] = function(block) { const orderType = block.getFieldValue('ORDER_TYPE'); const limitPrice = Blockly.Python.valueToCode(block, 'LIMIT_PRICE', Blockly.Python.ORDER_ATOMIC) || 'None'; let code = `order_type='${orderType}'`; if (orderType === 'limit') { code += `, limit_price=${limitPrice}`; } return code; }; // Value Input block to Python code Blockly.Python['value_input'] = Blockly.Python.forBlock['value_input'] = function(block) { var value = block.getFieldValue('VALUE'); return [value.toString(), Blockly.Python.ORDER_ATOMIC]; // Returning both value and precedence }; // Time in Force block to Python code Blockly.Python['time_in_force'] = Blockly.Python.forBlock['time_in_force'] = function(block) { const tif = block.getFieldValue('TIF'); const code = `tif='${tif}'`; return code; }; Blockly.Python['source'] = Blockly.Python.forBlock['source'] = function(block) { var timeframe = block.getFieldValue('TF'); var exchange = block.getFieldValue('EXC'); var symbol = block.getFieldValue('SYM'); // Return the source information as an object or string var code = `{'timeframe': '${timeframe}', 'exchange': '${exchange}', 'symbol': '${symbol}'}`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Generator code for strategy_profit_loss block Blockly.Python['strategy_profit_loss'] = Blockly.Python.forBlock['strategy_profit_loss'] = function(block) { var direction = block.getFieldValue('DIRECTION'); var code = `strategy_profit_loss('${direction}')`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Generator code for current_balance block Blockly.Python['current_balance'] = Blockly.Python.forBlock['current_balance'] = function() { var code = 'get_current_balance()'; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Generator code for starting_balance block Blockly.Python['starting_balance'] = Blockly.Python.forBlock['starting_balance'] = function() { var code = 'get_starting_balance()'; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Generator code for arithmetic_operator block Blockly.Python['arithmetic_operator'] = Blockly.Python.forBlock['arithmetic_operator'] = function(block) { var operator = block.getFieldValue('OPERATOR'); var left = Blockly.Python.valueToCode(block, 'LEFT', Blockly.Python.ORDER_ATOMIC); var right = Blockly.Python.valueToCode(block, 'RIGHT', Blockly.Python.ORDER_ATOMIC); var code = `${left} ${operator} ${right}`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Python generator for the active_trades block Blockly.Python['active_trades'] = Blockly.Python.forBlock['active_trades'] = function(block) { var code = `get_active_trades()`; // You would define this method in your Python backtesting engine return [code, Blockly.Python.ORDER_ATOMIC]; }; // Python generator for the flag_is_set block Blockly.Python['flag_is_set'] = Blockly.Python.forBlock['flag_is_set'] = function(block) { var flagName = block.getFieldValue('FLAG_NAME'); var code = `flag_is_set('${flagName}')`; return [code, Blockly.Python.ORDER_ATOMIC]; }; // Python generator for set_flag block Blockly.Python['set_flag'] = Blockly.Python.forBlock['set_flag'] = function(block) { var condition = Blockly.Python.valueToCode(block, 'CONDITION', Blockly.Python.ORDER_ATOMIC); var flagName = block.getFieldValue('FLAG_NAME'); var flagValue = block.getFieldValue('FLAG_VALUE') === 'True' ? 'True' : 'False'; var code = `if ${condition}:\n set_flag('${flagName}', ${flagValue})\n`; return code; }; console.log('Python generators defined'); }