Introduction
FEBE is a new kind of command set that aims to fill the gap (or place itself) between Managed and Unmanaged Trading commands. This command set is designed to provide the ease-of-use from Managed Trading and the power + flexibility of the Unmanaged side of things. The engine uses Unmanaged Trading commands, but everything has been done for you; all you need to do, is to give the engine “commands” with parameters to execute and the engine does the rest!
I sincerely hope this system will help you create awesome bots without too much of a headache! 🙂
I won’t be providing much examples or tutorials for the system at the time being. There will be more later on, stay tuned!
Related Scripts
The Blocks
By default, FEBE contains 6 commands to work with – and that’s all you need to get started! There is a “tutorial” below on how to create a Trailing Stop-Loss command for FEBE.
- CC_FEBE_Orders: Defines settings for orders
- CC_FEBE_Buy: Defines settings for buying/long
- CC_FEBE_Sell: Defines settings for selling/short
- CC_FEBE_TakeProfit: Defines settings for take-profit
- CC_FEBE_StopLoss: Defines settings for stop-loss
- CC_FEBE_Execute: Contains the core logic which reads the information array and acts based on it
Ease-of-Use
I hope FEBE will be loved by the great people of VE. It is designed to help creating bots using HaasScript’s Visual Editor, but of course it also works in Script Editor.
Here are few example bots created using FEBE:
Simple RSI Scalper
Simple Market Maker
MadHatter Clone
Hopefully these give some idea of what is possible and how powerful FEBE is…
Expandable
The core idea of FEBE is really simple: build an array of arguments and provide them for the execution command to handle. There is only one thing that has to exist in all commands that control FEBE: the command must be able to input and output the parameters array.
Here is the CC_FEBE_Buy() command for example:
DefineCommand('FEBE_Buy', 'Used to set buy settings for FEBE')
-- the input for parameters
local params = DefineParameter(ListDynamicType, 'params', 'Parameters for FEBE', true, {}, 'NewArray')
-- command related parameters
local order_timeout = DefineParameter(NumberType, 'order_timeout',
'Order timeout in seconds. Default: 600 (10 minutes)', false, 600, 'Input, Number')
local order_refill = DefineParameter(BooleanType, 'order_refill',
'Whether or not the filled/cancelled orders should be refilled. Default: false', false, false, 'True, False')
local order_type = DefineParameter(EnumType, 'order_type',
'Order type used for the buy orders. If MarketOrderType is used, the buy order(s) will execute immediately'
.. ' and will re-trigger after order_timeout if order_refill is set to TRUE. Default: LimitOrderType',
false, LimitOrderType, 'LimitOrderType, MarketOrderType, MakerOrCancelOrderType')
-- a little hack to bypass private vs shared resources error
local p = {}
for i=1, #params do
p[i] = params[i]
end
p[#p + 1] = {
's_buy', -- the command for CC_FEBE_Execute()
{
-- the parameters for this particular block
{'order_timeout', order_timeout},
{'order_refill', order_refill},
{'order_type', CC_FEBE_ParseOrderType(order_type)}
}
}
-- the output for parameters, for easy continuation
DefineOutput(ListDynamicType, p, 'Input parameters with added buy information')
That command above would be the one that activates the buying module within the CC_FEBE_Execute(). There is a section for supported commands:
-- supported modules array
local supported_modules = {
's_orders',
's_tp',
's_sl',
's_buy',
's_sell'
}
And later in the execution command, we check if this command exists in the input parameters and act based on the parameters we got from it:
---------------------------------------------------------------------
-- setup and run buying
module = {}
module.name = supported_modules[4]
module.order_timeout = 'order_timeout'
module.order_refill = 'order_refill'
module.order_type = 'order_type'
if active_modules[ module.name ] == true then
log('Found buy settings')
local module_params = params[ module.name ]
-- grab settings
local buy = {}
buy.active = true
buy.order_timeout = module_params[ module.order_timeout ]
buy.order_refill = module_params[ module.order_refill ]
buy.order_type = module_params[ module.order_type ]
buy.order_count = orders.max_open
buy.order_size = orders.size
buy.order_spread = orders.spread
buy.order_cancel_dist = orders.cancel_dist
-- update orders with buy settings
updateOrderBundle( true, 'buy', buy )
else
-- grab settings
local buy = {}
buy.active = false
buy.order_count = orders.max_open
-- cancel all open orders and reset
updateOrderBundle( true, 'buy', buy )
end
If you want to for example create trailing stop-loss for FEBE, you would simply have something like this:
DefineCommand('FEBE_TrailingStopLoss', 'Used to set TSL settings for FEBE')
-- the input for parameters
local params = DefineParameter(ListDynamicType, 'params', 'Parameters for FEBE', true, {}, 'NewArray')
-- command related parameters
local percentage = DefineParameter(NumberType, 'percentage',
'Distance for trailing, set in percentages. Default: 1', false, 1, 'Input, Number')
-- a little hack to bypass private vs shared resources error
local p = {}
for i=1, #params do
p[i] = params[i]
end
p[#p + 1] = {
's_tsl', -- the command for CC_FEBE_Execute()
{
-- the parameters for this particular block
{'percentage', percentage}
}
}
-- the output for parameters, for easy continuation
DefineOutput(ListDynamicType, p, 'Input parameters with added TSL information')
…and this
-- supported modules array
local supported_modules = {
's_orders',
's_tp',
's_sl',
's_buy',
's_sell',
's_tsl' -- our new command must be supported
}
…aaaand this
---------------------------------------------------------------------
-- setup and run trailing stop loss
module.name = supported_modules[6]
module.percentage = 'percentage' -- our parameters
module.order_type = 'order_type'
if active_modules[ module.name ] == true then
log('Found TSL settings')
local module_params = params[ module.name ]
-- grab settings
local tsl = {}
tsl.active = false -- this tells if TSL was triggered or not
tsl.percentage = module_params[ module.percentage ]
tsl.order_type = module_params[ module.order_type ]
tsl.price = 0
-- regular order types
if tsl.order_type <= 4 then
-- wait until TSL triggers before activating order
if TrailingStopLoss(tsl.percentage) then
tsl.active = true
if pos.dir == PositionLong then
tsl.price = cp.ask
elseif pos.dir == PositionShort then
tsl.price = cp.bid
end
end
-- native stop types
elseif tsl.order_type > 4 and tsl.order_type < 7 then
-- place TSL beforehand when using native stops.
-- the updateExitOrder() function will handle replacing
-- order when ever the price or position size changes.
tsl.active = true
-- calculate trigger price
if pos.dir == PositionLong then
tsl.price = SubPerc( pos.aep, tsl.percentage )
elseif pos.dir == PositionShort then
tsl.price = AddPerc( pos.aep, tsl.percentage )
end
else
error('Native Take-Profit order types not supported for Trailing Stop-Loss')
end
-- if we got a price, parse it properly
if tsl.price > 0 then
tsl.price = ParseTradePrice(PriceMarket(), tsl.price)
end
-- we want to only activate TSL when we have an open position
tsl.active = tsl.active and pos.dir != NoPosition
-- run
updateExitOrder('tsl', 'Trailing Stop-Loss', tsl.price, tsl.order_type, tsl.active)
end