This board has been archived, no new registrations are allowed. Please come join us on our discord!

[Readme] General information

General discussion about the script-bots
User avatar
stephan
Administrator
Posts: 1047
Joined: Fri Sep 12, 2014 9:37 am
Contact:

[Readme] General information

Postby stephan » Fri Feb 09, 2018 10:11 am

Re-introducing the Script bot...

Back in version 2.0 of the Haasbot we had scripted bots supported. For the development of version 3 we decided to add the script-bots as one of the last bots and this time has come. Just to be clear, this does not mean we will not add in other new bots. But this will close the 3.0 generation and we will continue into the 3.1 generation very soon. We are reaching a milestone.

The new script-bot will be availible into 2 languages, C# and HaasScript. But we are putting the most weight into C# first because its a proven technology already. HaasScript is more intended for future goals.

The re-introduction will be happening into stages because of the complexity of the the script-bot introduces. First we will kick off by just adding support for scripted bots. This will directly enable a lot of options. But not everything. For example you will be able to call the command PlaceBuyOrder(price,amount) and a order will be send then. But you can not control the market just yet. We created a basic model where the end-user must select a Account, Price market and Trade-amount. Same goes for a coin position.

At the second stage of the implementation we will make it possible so you can place orders at different Accounts and Price markets. We will also make it possible to do charting at this stage.

If it all works as designed then we will switch over to adding in new abilities. For example, we like to make it possible that you can send a Telegram message from the bot.


The following documentation is created in combination with C# scripting. The documentation for the HaasScript version wil be very simulair but that will be listed inside our wiki.


Lets gets started on how to make a script-bot. The interface of a scripted bot looks like this.

Code: Select all

namespace TradeServer.ScriptingDriver.Interfaces
{
    public interface IScriptBot
    {
        string Name { get; }

        void Init();
        void DoUpdate(ScriptBotContext context);

        List<ScriptParameter> GetParameters();
        void SetParameters(Dictionary<string, object> parameters);
    }
}


Its pretty straight forward. We got a Init() call which get executed if a script get started/loaded at the first time. If you are using some kind of local variable then that will be the place to reset those. Next we got the DoUpdate() call and this is the place where the magic really happens. This is what we call during a backtest and/or during runtime.


The context is a object which is given each time the update function is called.

Code: Select all

namespace TradeServer.ScriptingDriver.DataObjects
{
    public class ScriptBotContext
    {
        public string PriceSourceName { get; set; }
        public string PrimairyCoin { get; set; }
        public string SecondairyCoin { get; set; }
        public string ContractName { get; set; }

        public int Interval { get; set; }
        public int TicksBack { get; set; }

        public int Offset { get; set; }

        public decimal TradeAmount { get; set; }

        public decimal Fee { get; set; }

        public decimal LastBuyPrice { get; set; }
        public decimal LastSellPrice { get; set; }

        public decimal LastEnterLongPrice { get; set; }
        public decimal LastExitLongPrice { get; set; }
        public decimal LastEnterShortPrice { get; set; }
        public decimal LastExitShortPrice { get; set; }

        public BotsPosition BotPosition { get; set; }

        public IPriceInstrument PriceInstrument { get; set; }
        public PriceTick PriceTick { get; set; }

        public IndicatorLog Logger { get; set; }
        public IScriptBotAPI API { get; set; }

        public List<string> OpenOrders { get; set; } = new List<string>();
        public List<string> FinishedOrders { get; set; } = new List<string>();

        public Dictionary<string, decimal> Wallet { get; set; } = new Dictionary<string, decimal>();
    }
}



The context object comes with the API property and inside this you can find the methods to get information or to trade.

Code: Select all

namespace TradeServer.ScriptingDriver.Interfaces
{
    public interface IScriptBotAPI
    {
        List<string> GetAllPriceSources();
        List<string> GetEnabledPriceSources();
        List<string> GetPriceMarkets(string pricesourceName);

        IPriceInstrument GetPriceInstrument(string pricesourceName, string primairyCoin, string secondairyCoin, string contractName, int interval, int ticksBack);
        PriceTick GetPriceTick(string pricesourceName, string primairyCoin, string secondairyCoin, string contractName);
        PriceTick GetMinutePriceTick(string pricesourceName, string primairyCoin, string secondairyCoin, string contractName);

        bool CancelOrder(string orderid);

        string PlaceBuyOrder(decimal amount, decimal price);
        string PlaceSellOrder(decimal amount, decimal price);

        string PlaceGoLongOrder(decimal amount, decimal price);
        string PlaceExitLongOrder(decimal amount, decimal price);
        string PlaceGoShortOrder(decimal amount, decimal price);
        string PlaceExitShortOrder(decimal amount, decimal price);
    }
}



Coding Instructions
One of the most basic rules of the scripted bots is to log everything you want to see. So its highly recommand to use the context.Logger method.

The scripted bot works only supports limit orders. We did not have created support for market orders. So the basic principle will be to send a order and then you get back a order ID which you can trace. If you get no ID back then you may assume the order has failed for whatever reason.

OpenOrders - Has a list of all open Order IDs created by the scripted bot.
FinishedOrders - Has a list of all open Order IDs created by the scripted bot.

Keep in mind, aldo the scripted bot provides a coin position. You are still into control of this. You must control the position of where the coins are at and what to do, buy or sell.

To keep coding easy we did not make use of events, instead by design its 1 point of entry for all kind of events. So be sure to check everything.


Test and Runtime Instructions
For the moment he advice is to check, check and check again if everything is running as you intent to be happening with your script. Do not take a shortcut!


Runtime Warning
Despite the fact that C# coding is OOP by nature, its not behaving like this. We have noticed that objects liek the class you write for a script bot are not being re-crreated with a run-time compiler.
Join the telegram group too: https://t.me/haasonlineofficial

User avatar
stephan
Administrator
Posts: 1047
Joined: Fri Sep 12, 2014 9:37 am
Contact:

Re: [Readme] General information

Postby stephan » Fri Feb 09, 2018 10:12 am

Example: Spot Scalper-Bot

The spot scalper bot is desinged to be running on stop trading markets. The bot itself is designed to be very simple. It aims for trading just above the fee levels and it comes with a stop-loss.

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TradeServer.ScriptingDriver.DataObjects;
using TradeServer.ScriptingDriver.Interfaces;

namespace BotScripts
{
    public class ScalperBot : IScriptBot
    {
        private bool _openOrder = false;
        private decimal _stoploss = 5.0M;
       
        public string Name
        {
            get { return "Spot Scalper-bot"; }
        }

        public ScriptBotType BotType
        {
            get { return ScriptBotType.SpotBot; }
        }

        public List<ScriptParameter> GetParameters()
        {
            List<ScriptParameter> res = new List<ScriptParameter>();
            res.Add(new ScriptParameter("Stop-loss", ScriptParameterType.Double, _stoploss.ToString()));
            return res;
        }

        public void SetParameters(Dictionary<string, object> parameters)
        {
            foreach (var item in parameters) // lets just loop them all
            {
                if (item.Key == "Stop-loss") { _stoploss = Convert.ToDecimal(item.Value); }
            }
        }

        public void Init()
        {

        }

        public void DoUpdate(ScriptBotContext context)
        {
            // Check for open orders
            if (context.OpenOrders.Count > 0)
            {
                context.Logger.Log("Open orders detected, update skipped.");
                return;
            }

            context.Logger.Log("Last buy: " + context.LastBuyPrice.ToString());
            context.Logger.Log("Last sell: " + context.LastSellPrice.ToString());
            context.Logger.Log("Fee: " + context.Fee.ToString());
            context.Logger.Log("Stop-loss: " + _stoploss.ToString());
           

            // Based on the position, lets see what we can do...
            if (context.BotPosition == BotsPosition.BuyLong)
            {
                context.Logger.Log("The bot its position is: Bought");

                // Wallet checkup
                if (context.Wallet.ContainsKey(context.PrimairyCoin) == false ||
                    context.Wallet[context.PrimairyCoin] < context.TradeAmount)
                {
                    context.API.SignalWalletAlert();
                    return;
                }

                if (context.LastBuyPrice == 0)
                {
                    context.Logger.Log("No last prices are known, approving first selling order.");
                    context.API.PlaceSellOrder(context.TradeAmount, (decimal)context.PriceTick.Bid);
                }
                else
                {
                    var targetPrice = context.LastBuyPrice;

                    if (context.Fee > 0.0M)
                        targetPrice = context.LastBuyPrice + (context.LastBuyPrice / 100.0M * (context.Fee * 2.0M));

                    context.Logger.Log("Last buying price was " + context.LastBuyPrice.ToString() + " the target sell price is: " +
                        targetPrice.ToString() + " (now: " + context.PriceTick.Ask.ToString() + ")");

                    // Normal trading procedure
                    if (targetPrice < (decimal)context.PriceTick.Ask)
                    {
                        context.Logger.Log("Approving selling order.");
                        context.API.PlaceSellOrder(context.TradeAmount, (decimal)context.PriceTick.Bid);
                    }
                }
            }
            else if (context.BotPosition == BotsPosition.SellShort)
            {
                context.Logger.Log("The bot its position is: Sold");

                // Wallet checkup
                if (context.Wallet.ContainsKey(context.SecondairyCoin) == false ||
                    (context.Wallet[context.SecondairyCoin] * (decimal)context.PriceTick.Ask) < context.TradeAmount)
                {
                    context.API.SignalWalletAlert();
                    return;
                }

                if (context.LastSellPrice == 0)
                {
                    context.Logger.Log("No last prices are known, approving first buying order.");
                    context.API.PlaceBuyOrder(context.TradeAmount, (decimal)context.PriceTick.Ask);
                }
                else
                {
                    var targetPrice = context.LastSellPrice;

                    if (context.Fee > 0.0M)
                        targetPrice = context.LastSellPrice - (context.LastSellPrice / 100.0M * (context.Fee * 2.0M));

                    context.Logger.Log("Last selling price was " + context.LastSellPrice.ToString() + " the target buy price is: " +
                        targetPrice.ToString() + " (now: " + context.PriceTick.Ask.ToString() + ")");

                    // Normal trading procedure
                    if (targetPrice > (decimal)context.PriceTick.Bid)
                    {
                        context.Logger.Log("Approving buying order.");
                        var res = context.API.PlaceBuyOrder(context.TradeAmount, (decimal)context.PriceTick.Ask);
                    }
                }
            }
        }
    }
}
Join the telegram group too: https://t.me/haasonlineofficial

User avatar
stephan
Administrator
Posts: 1047
Joined: Fri Sep 12, 2014 9:37 am
Contact:

Re: [Readme] General information

Postby stephan » Fri Feb 09, 2018 10:12 am

Example: Simplefied FCB bot

With the script-bots we can create bots which can trade 1 time and switch positions. Bu we also created support for having more open orders. The following example is a very simplefied version of the FCB, its a example on how to deal with more then 1 open order at the same time.

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TradeServer.ScriptingDriver.DataObjects;
using TradeServer.ScriptingDriver.Interfaces;

namespace BotScripts
{
    public class SimpleFCBBot : IScriptBot
    {
      public string slot_buy_1 = "";
      public string slot_buy_2 = "";
      public string slot_buy_3 = "";

      public string slot_sell_1 = "";
      public string slot_sell_2 = "";
      public string slot_sell_3 = "";
      
        public string Name
        {
            get { return "Simple FCB-bot"; }
        }

      private decimal _spread = 10.0M;
      
        public List<ScriptParameter> GetParameters()
        {
            List<ScriptParameter> res = new List<ScriptParameter>();
            res.Add(new ScriptParameter("Spread", ScriptParameterType.Double, _spread.ToString()));
            return res;
        }

        public void SetParameters(Dictionary<string, object> parameters)
        {
            foreach (var item in parameters) // lets just loop them all
            {
                if (item.Key == "Spread") { _spread = Convert.ToDecimal(item.Value); }
            }
        }

        public void Init()
        {

        }

        public void DoUpdate(ScriptBotContext context)
        {
            // Check for open orders
            if (context.OpenOrders.Count == 6)
            {
                context.Logger.Log("Perfect, all orders are set.");
                return;
            }

         if (slot_buy_1 == "" || !context.OpenOrders.Contains(slot_buy_1))
         {
            context.Logger.Log("Filling buy slot 1");
            var price = (decimal)context.PriceTick.Ask - _spread;
            slot_buy_1 = context.API.PlaceBuyOrder(context.TradeAmount, price);
         }
         
         if (slot_buy_2 == "" || !context.OpenOrders.Contains(slot_buy_2))
         {
            context.Logger.Log("Filling buy slot 2");
            var price = (decimal)context.PriceTick.Ask - (_spread * 2.0M);
            slot_buy_2 = context.API.PlaceBuyOrder(context.TradeAmount, price);
         }

         if (slot_buy_3 == "" || !context.OpenOrders.Contains(slot_buy_3))
         {
            context.Logger.Log("Filling buy slot 3");
            var price = (decimal)context.PriceTick.Ask - (_spread * 3.0M);
            slot_buy_3 = context.API.PlaceBuyOrder(context.TradeAmount, price);
         }      

         if (slot_sell_1 == "" || !context.OpenOrders.Contains(slot_sell_1))
         {
            context.Logger.Log("Filling sell slot 1");
            var price = (decimal)context.PriceTick.Bid + _spread;
            slot_sell_1 = context.API.PlaceSellOrder(context.TradeAmount, price);
         }
         
         if (slot_sell_2 == "" || !context.OpenOrders.Contains(slot_sell_2))
         {
            context.Logger.Log("Filling sell slot 2");
            var price = (decimal)context.PriceTick.Bid + (_spread * 2.0M);
            slot_sell_2 = context.API.PlaceSellOrder(context.TradeAmount, price);
         }

         if (slot_sell_3 == "" || !context.OpenOrders.Contains(slot_sell_3))
         {
            context.Logger.Log("Filling sell slot 3");
            var price = (decimal)context.PriceTick.Bid + (_spread * 3.0M);
            slot_sell_3 = context.API.PlaceSellOrder(context.TradeAmount, price);
         }   
        }
    }
}
Join the telegram group too: https://t.me/haasonlineofficial

mjmokhtari.tehran
Registered User
Posts: 10
Joined: Sat Feb 17, 2018 2:10 pm

Re: [Readme] General information

Postby mjmokhtari.tehran » Tue Feb 27, 2018 6:16 am

stephan wrote:Re-introducing the Script bot...

Back in version 2.0 of the Haasbot we had scripted bots supported. For the development of version 3 we decided to add the script-bots as one of the last bots and this time has come ...


Hi Dear Stephan.
I have an advance License of the product and want to know when I can use this feature?
Thanks A lot.


Return to “Script-bots”

Who is online

Users browsing this forum: No registered users and 2 guests