libKageBot
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © marcelokg

//@version=5

// @description Functions to generate command strings for bots FrostyBot and Zignally. This version ONLY WORKS WITH FROSTYBOT.
library("libKageBot", overlay = true)


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//#region Constants

string GLOBAL_SERVER_FROSTYBOT  = "FrostyBot"
string GLOBAL_SERVER_ZIGNALY    = "Zignaly"
string GLOBAL_DIRECTION_LONG    = "long"
string GLOBAL_DIRECTION_SHORT   = "short"
string GLOBAL_LEVERAGE_CROSS    = "cross"
string GLOBAL_LEVERAGE_ISOLATED = "isolated"

// @type                    Constants to be used in both in internal and external code
// @field SERVER_FROSTBOT   (string) Identifier to FrostyBot
// @field SERVER_ZIGNALY    (string) Identifier to Zignaly
// @field DIRECTION_LONG    (string) Flag to open a long position
// @field DIRECTION_SHORT   (string) Flag to open a short position
// @field LEVERAGE_CROSS    (string) Flag to set leverage to cross
// @field LEVERAGE_ISOLATED (string) Flag to set leverage to isolated
export type Constants
	string SERVER_FROSTBOT
	string SERVER_ZIGNALY
    string DIRECTION_LONG
    string DIRECTION_SHORT
    string LEVERAGE_CROSS    
    string LEVERAGE_ISOLATED 

BOT = Constants.new( GLOBAL_SERVER_FROSTYBOT,
                     GLOBAL_SERVER_ZIGNALY,
                     GLOBAL_DIRECTION_LONG,
                     GLOBAL_DIRECTION_SHORT,
                     GLOBAL_LEVERAGE_CROSS,
                     GLOBAL_LEVERAGE_ISOLATED)

//#endregion Constants


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//#region Bot's user defined types

// @type           Bot type to handle bot's essential information 
// @field server   (string) Type o server. Must me one of the SERVER_* constant values
// @field id       (string) Id of the account in the server (Stub for FrostyBot or Key to Zignally)
// @field symbol   (string) Symbol of the pair to be negotiated (example: ETH/USDT)
// @field leverage (int)    Leverage coeficient. Default is 1  
export type TradeBot
	string server
	string id
	string symbol
    int    leverage = 1

//#endregion UDTs


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//#region Bot's functions to generate command strings

// @function            Converts a float to a formated string suitable to position size in percentage or currency. At leaste one parameter must be given
// @param _sizePercent  (float)  Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param _sizeCurrency (float)  Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.
// @returns             (string) A formated string containing the position size
export strSize(float _sizePercent = na, float _sizeCurrency = na) =>
    string stringSize = ""
    if na(_sizeCurrency) and not na(_sizePercent)
        stringSize := str.tostring(_sizePercent, "#.##") + "%"
    else if na(_sizePercent) and not na(_sizeCurrency)
        stringSize := str.tostring(_sizeCurrency, "#.##")
    else
        stringSize := "[stringSize ERROR]"
    stringSize

// @function               Generates a simple entry command string for a bot
// @param    _bot          (TradeBot) Previously instancied bot type variable
// @param    _direction    (string)   Flag to opena long or a short position. Must be either DIRECTION_LONG or DIRECTION_SHORT constant
// @param    _sizePercent  (float)    Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param    _sizeCurrency (float)    Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.
// @returns                (string)   A string of a simple open position command
export entry(TradeBot _bot, string _direction, float _sizePercent = na, float _sizeCurrency = na) =>
	string cmdLong = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => "trade:" + _bot.id + ":" + _direction + " " + "symbol=" + _bot.symbol + " " + "size=" + strSize(_sizePercent, _sizeCurrency)
		GLOBAL_SERVER_ZIGNALY   => ""

// @function               Generates a simple exit command string for a bot
// @param    _bot          (TradeBot) Previously instancied bot type variable
// @param    _sizePercent  (float)    Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param    _sizeCurrency (float)    Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.
// @param    _reduce       (bool)     Flag to use Ruce Only option on Binance positions. Optional. Default = true
// @returns                (string)   A string of a simple close position command
export exit(TradeBot _bot, float _sizePercent = na, float _sizeCurrency = na, bool _reduce = true) =>
	string cmdClose = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => "trade:" + _bot.id + ":" + "close" + " " + "symbol=" + _bot.symbol + " " + "size=" + strSize(_sizePercent, _sizeCurrency) + " " + "reduce=" + str.tostring(_reduce)
		GLOBAL_SERVER_ZIGNALY   => ""

// @function      Generates a command string for a bot that cancels all open orders
// @param    _bot (TradeBot) Previously instancied bot type variable
// @returns       (string)   A string of a command to cancel all open orders
export cancelAll(TradeBot _bot) =>
	string cmdCancelAll = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => "trade:" + _bot.id + ":" + "cancelall" + " " + "symbol=" + _bot.symbol
		GLOBAL_SERVER_ZIGNALY   => ""

// @function           Generates a command string for a bot to set leverage
// @param    _bot      (TradeBot) Previously instancied bot type variable
// @param    _leverage (int)      The amount of leverage to be used when opening a position. Optional. If does not given, the bot's default will be used
// @param    _type     (string)   Type of leverage. Must be either LEVERAGE_CROSS or LEVERAGE_ISOLATED. Optional. Default is LEVERAGE_CROSS.
// @returns            (string)   A string of a simple leverage command
export leverage(TradeBot _bot, int _leverage = na, string _type = "cross") =>
	int newLeverage = 0
    if na(_leverage)
        newLeverage := _bot.leverage
    else
        newLeverage := _leverage

    string cmdLeverage = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => "trade:" + _bot.id + ":" + "leverage" + " " + "symbol=" + _bot.symbol + " " + "type=" + _type + " " + "leverage=" + str.tostring(newLeverage, "#")
		GLOBAL_SERVER_ZIGNALY   => ""

// @function               Generates a complete long entry command string for a bot
// @param    _bot          (TradeBot) Previously instancied bot type variable
// @param    _leverage     (int)      The amount of leverage to be used when opening a position. Optional. If does not given, the bot's default will be used
// @param    _leverageType (string)   Type of leverage. Must be either LEVERAGE_CROSS or LEVERAGE_ISOLATED. Optional. Default is LEVERAGE_CROSS.
// @param    _sizePercent  (float)    Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param    _sizeCurrency (float)    Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.  
// @returns                (string)   A string of a complete open long position command
export entryLong(TradeBot _bot, int _leverage = na, string _leverageType = "cross", float _sizePercent = na, float _sizeCurrency = na) =>
	string cmdEntryLong = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => cancelAll(_bot) + "\n" + leverage(_bot, _leverage, _leverageType) + "\n" + entry(_bot, BOT.DIRECTION_LONG, _sizePercent, _sizeCurrency)
		GLOBAL_SERVER_ZIGNALY   => ""

// @function               Generates a complete short entry command string for a bot
// @param    _bot          (TradeBot) Previously instancied bot type variable
// @param    _leverage     (int)      The amount of leverage to be used when opening a position. Optional. If does not given, the bot's default will be used
// @param    _type         (string)   Type of leverage. Must be either LEVERAGE_CROSS or LEVERAGE_ISOLATED. Optional. Default is LEVERAGE_CROSS.
// @param    _sizePercent  (float)    Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param    _sizeCurrency (float)    Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.
// @returns                (string)   A string of a complete open short position command
export entryShort(TradeBot _bot, int _leverage = na, string _leverageType = "cross", float _sizePercent = na, float _sizeCurrency = na) =>
	string cmdEntryShort = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => cancelAll(_bot) + "\n" + leverage(_bot, _leverage, _leverageType) + "\n" + entry(_bot, BOT.DIRECTION_SHORT, _sizePercent, _sizeCurrency)
		GLOBAL_SERVER_ZIGNALY   => ""

// @function               Generates a complete close position command string for a bot
// @param    _bot          (TradeBot) Previously instancied bot type variable
// @param    _sizePercent  (float)    Position size in percent value. Optional. Default = na. Mandatory if _sizeCurrency is not given.
// @param    _sizeCurrency (float)    Position size in currency value. Optional. Default = na. Mandatory if _sizePercent is not given.
// @param    _reduce       (bool)     Flag to use Ruce Only option on Binance positions. Optional. Default = true
// @returns                (string)   A string of a comlete close position command
export exitPosition(TradeBot _bot, float _sizePercent = 100.0, float _sizeCurrency = na, bool _reduce = true) =>
	string cmdEntryLong = switch _bot.server
		GLOBAL_SERVER_FROSTYBOT => cancelAll(_bot) + "\n" + exit(_bot, _sizePercent, _sizeCurrency, _reduce)
		GLOBAL_SERVER_ZIGNALY   => ""

// @function Print bot's information for debug purposes
// @param    _bot     (TradeBot) Previously instancied bot type variable
// @param    _command (string)   A command string to be debugged
// @returns  Nothing.        
export printBot(TradeBot _bot, string _command = "") => 
    if barstate.islastconfirmedhistory
        label.new(x     = bar_index + 2,
                  y     = hl2, 
                  style = label.style_label_upper_left,
                  color = color.silver,
                  size  = size.large,
                  textalign =  text.align_left,
                  text  = _bot.server + ":" + _bot.id + ":" + _bot.symbol + "\n\n" + _command
                 )

//#endregion Functions





