Mike Fishy and Automation System Programming (Bots)


#222

Screenshot after adjusting the formatting for the latest version of the bot.

After 99 minutes the bot is down 6.2% and this is confirmed from the 14 trades in the log file. It’s noticeable that every trade is a “loss” so it could be that there is an issue with some of the logic.


#223

During the 99 minutes BTC dropped about 2.2% and it probably took most alts down by at least this much. 14 trades at 0.2% per trade is 2.8% so in total, market fall and costs, come to about a 5% loss. So the 6.2% observed loss in the bot could be about right.

In the 36 minutes following the initial 99 minutes it has only lost 0.5% (including fees) so it looks to be getting better. Will review it again later today.


#224

Losses, including fees, grew to over 15% but a few wins has brought that down to 11% after 286 minutes.


#225

yup, I can confirm…similar results for me…

image

I’m trying to see where the logic error might be, but so far, I don’t see any and assuming its market dynamics we must begin handling with better rules to get to profitable territory.

I’m going to experiment a little with the sell trigger. Right now, it sells as soon as both short and mid term averages are no longer “UP” - that is, when they go FLAT or DOWN, but it doesn’t seem soon enough.

I noticed that when we’re holding a position, the bot doesn’t take advantages of short term pumps in prices…so we can see gains of +2% and even +4%, but end up exiting around 1% or less, presumably because the moving averages were adversely affected by the impulse spikes. So my idea here is to introduce a virtual trailing stop loss and sell when price falls below that after achieving +2% gains.


#226

Awesome idea @mwlang.

I have got a lot of homework to do to understand all of this. Making lots of notes.

@Mike_Fishy thanks as always. Have a good weekend and have a few beers on me :beer::beer::beer::beer::beer::beer::beer::beer::beer::beer::beers::beers::beers::beers::beers:


#227

Wow, you are at a 28% loss.


#228

New version with stop/loss protection is running. I set it at 0.5% trailing current price, but y’all can mess with it. So far, 30 minutes in, no trades made, so no idea if any bugs in the buy/sell cycle, yet, but what the heck, somebody’s out there wanting to play with this like right now, right? :slight_smile:

<?php
require 'vendor/autoload.php';

// This bot will trade USDT to the other pairs and back to make more USDT
// It shall use all the trading pairs to make more UDST except the ones we tell it not to use

$strend = 100;            // Short Term Trend - must be less than $mtrend
$mtrend = 180;            // Medium Term Trend - must be less than $ltrend
$ltrend = 280;            // Long Term Trend
$tradefile = "USDT.txt";  // The Trade Logging file name
$minspread = 0.6;         // The minimum spread percentage needed for a trade
$minrsi = 46;             // Relative Strength must be below this number to buy

// Do not change any of the flags, we use this to signal the bot what to do and when
$buyready = 0;            // This flag signals the bot that the pair meets rules to buy
$buyprep = 1;             // This flag signals the bot to prepare to buy
$buyord = 2;              // This flag signals the bot to place an order
$sellok = 3;              // This flag signals the bot that the order was completed
$sellready = 4;           // This flag signals the bot to sell
$selldone = 5;            // This flag signals the bot the trade completed
$dontbuy = 6;             // This flag signals the bot we dont want to trade BCASH :P

// Standard variables and arrays we use
$i = 0;
$binance_prices = array();
$time_start = time();
$time_end = 0;
$run_time = 0;
$rpc = 0;
$tpc = 0;
$q = 0;

// API call to fetch pricing data from Binance
function getprices()
{
  $api = new Binance\API("<api key>","<secret>");
  $mp = $api->prices();
  return $mp;
}

// Start of the Loop - can run for months - press CTRL-C to stop
for($i = 0; $i <= 2000000; $i++)
{
  $time_end = time();
  $run_time = round((($time_end - $time_start)/60),2);
  print "====================================\n";
  print "Iteration = $i \n";
  print "Running Time: $run_time mins \n";
  print "Current running percentage = $rpc \n";
  print "====================================\n";

// Fetch current prices from Binance
  $binance_prices = getprices();

// Loop through the price data as key and value pairs
  foreach($binance_prices as $key => $value)
  {

// Only process pairs with USDT
    if(strpos($key, "USDT"))
    {

// Convert the pair name to lower case in varibale $tick
// for example the name "BTCUSDT" will become "btcusdt"

      $tick = strtolower($key);

// For the first iteration, create arrays and varibales for the bot
      if($i == 0)
      {

// Use the lower case name to form the leading part of varibales and arrays
// for exmaple, using "btcusdt" and adding "st" for the short term array
// will initialise an array called "btcusdtst"
// as we loop thorugh the pairs, each one gets created for each pair
// for exmaple "NEOUSDT" will become "neousdtst"

        ${$tick . "st"} = array();         // Short Term Array
        ${$tick . "mt"} = array();         // Medium Term Array
        ${$tick . "lt"} = array();         // Long Term Array
        ${$tick . "stavg"} = 0;            // Short Term Moving Average
        ${$tick . "mtavg"} = 0;            // Medium Term Moving Average
        ${$tick . "ltavg"} = 0;            // Long Term Moving Average
        ${$tick . "strend"} = 0;           // Short Term Moving Trend
        ${$tick . "mtrend"} = 0;           // Medium Term Moving Trend
        ${$tick . "ltrend"} = 0;           // Long Term Moving Trend
        ${$tick . "mspread"} = 0;          // Medium Term Spread
        ${$tick . "rsi"} = 0;              // Relative Strength Indicator for this pair
        ${$tick . "buyflag"} = $buyready;  // Set this pair to buyready
        ${$tick . "buyvalue"} = 0;         // record what we buy for on this pair
        ${$tick . "sellvalue"} = 0;        // record what we sell for on this pair
        ${$tick . "isset"} = 1;            // used to signal we are initialised for this pair
        ${$tick . "stoploss"} = 0; // MWLANG
      }

// We are not on the first loop anymore, we proceed with processing the data
      else
      {

// Exclude List - these ones we do not trade

        if($key == "BCHABCUSDT") ${$tick . "buyflag"} = $dontbuy;
        if($key == "BCHSVUSDT") ${$tick . "buyflag"} = $dontbuy;
        if($key == "BCCUSDT") ${$tick . "buyflag"} = $dontbuy;
        if($key == "TUSDUSDT") ${$tick . "buyflag"} = $dontbuy;
        if($key == "VENUSDT") ${$tick . "buyflag"} = $dontbuy;
        if($key == "PAXUSDT") ${$tick . "buyflag"} = $dontbuy;

// Check if the trading pair has been initialised
// this covers if Binance add a new trading pair on USDT while we are running
// if Binance adds new trading pairs while bot is running, we shall
// ignore them and only use the ones since the bot was started and initialised

        if(isset(${$tick . "isset"}))
        {

// Push data into arrays and shift arrays once we have enough data
          array_push(${$tick . "st"}, $value);
          array_push(${$tick . "mt"}, $value);
          array_push(${$tick . "lt"}, $value);
          if($i > $strend) array_shift(${$tick . "st"});
          if($i > $mtrend) array_shift(${$tick . "mt"});
          if($i > $ltrend) array_shift(${$tick . "lt"});

// Wait until we have all the arrays populated with data
          if($i <= $ltrend)
          {
            printf("%-9s",$key);
            print "\t:Loading Arrays with data\n";
          }

// Arrays are populated, so on with the processing
          else
          {

// Calculate the Moving Average for the 3 arrays
            ${$tick . "stavg"} = round((array_sum(${$tick . "st"})/$strend),8);
            ${$tick . "mtavg"} = round((array_sum(${$tick . "mt"})/$mtrend),8);
            ${$tick . "ltavg"} = round((array_sum(${$tick . "lt"})/$ltrend),8);

// Check if the Short Term Trend is trending down, flat or up
// We use the current price to see if it is above or below the short term moving average
// We use "1" to signal it is trending down, "2" for flat, "3" for trending up
            if($value < ${$tick . "stavg"}) ${$tick . "strend"} = 1;
            if($value == ${$tick . "stavg"}) ${$tick . "strend"} = 2;
            if($value > ${$tick . "stavg"}) ${$tick . "strend"} = 3;

// Check if the Medium Term Trend is trending down, flat or up
// We use the short term moving average to see if it is above or below the medium term moving average
// We use "1" to signal it is trending down, "2" for flat, "3" for trending up
            if(${$tick . "stavg"} < ${$tick . "mtavg"}) ${$tick . "mtrend"} = 1;
            if(${$tick . "stavg"} == ${$tick . "mtavg"}) ${$tick . "mtrend"} = 2;
            if(${$tick . "stavg"} > ${$tick . "mtavg"}) ${$tick . "mtrend"} = 3;

// Check if the Long Term Trend is trending down, flat or up
// We use the medium term moving average to see if it is above or below the long term moving average
// We use "1" to signal it is trending down, "2" for flat, "3" for trending up
            if(${$tick . "mtavg"} < ${$tick . "ltavg"}) ${$tick . "ltrend"} = 1;
            if(${$tick . "mtavg"} == ${$tick . "ltavg"}) ${$tick . "ltrend"} = 2;
            if(${$tick . "mtavg"} > ${$tick . "ltavg"}) ${$tick . "ltrend"} = 3;

// Calculate the Medium Term spread, which is the percentage difference between
// the highest recorded price and the lowest recorded price in the Medium Term Array
            $mlow = min(${$tick . "mt"});
            $mhigh = max(${$tick . "mt"});
            ${$tick . "mspread"} = round(((1-($mlow/$mhigh))*100),3);
      
// Calculate the Relative Strength Indicator on the Long Term Array
// A Low RSI indicates a buy opportunity
            $rsitck = 0;
            ${$tick . "gain"} = array();
            ${$tick . "loss"} = array();
            foreach(${$tick . "lt"} as $cdaval)
            {
              if($rsitck == 0)
              {
                $cdagain = 0;
                $cdaloss = 0;
              }
              else
              {
                if($cdaval == $cdaprev)
                {
                  $cdagain = 0;
                  $cdaloss = 0;
                }
                elseif($cdaval > $cdaprev)
                {
                  $cdacalc = $cdaval - $cdaprev;
                  $cdagain = number_format($cdacalc,8);
                  $cdaloss = 0;
                }
                else
                {
                  $cdacalc = $cdaprev - $cdaval;
                  $cdaloss = number_format($cdacalc,8);
                  $cdagain = 0;
                }
              }
              array_push(${$tick . "gain"}, $cdagain);
              array_push(${$tick . "loss"}, $cdaloss);
              $cdaprev = $cdaval;
              $rsitck++;
            }
            $cdarsgain = (array_sum(${$tick . "gain"})) / $ltrend;
            $cdarsloss = (array_sum(${$tick . "loss"})) / $ltrend;
            if($cdarsloss > 0)
            {
              ${$tick . "rsi"} = round(100-(100/(1+($cdarsgain/$cdarsloss))),3);
              if(${$tick . "rsi"} == 0) ${$tick . "rsi"} = 0;
            }
            else
            {
              ${$tick . "rsi"} = 100;
            }

// Print out what we have so far so we can see what is going on
            printf("%-9s",$key);
            print "\tV:";
            printf("%-14.8F",$value);
            print "\t  ST:";
            printf("%-14.8F",${$tick . "stavg"});
            if(${$tick . "strend"} == 1) printf("%-5s",":DOWN");
            if(${$tick . "strend"} == 2) printf("%-5s",":FLAT");
            if(${$tick . "strend"} == 3) printf("%-5s",":UP");
            print "\t  MT:";
            printf("%-14.8F",${$tick . "mtavg"});
            if(${$tick . "mtrend"} == 1) printf("%-5s",":DOWN");
            if(${$tick . "mtrend"} == 2) printf("%-5s",":FLAT");
            if(${$tick . "mtrend"} == 3) printf("%-5s",":UP");
            print "\t  LT:";
            printf("%-14.8F",${$tick . "ltavg"});
            if(${$tick . "ltrend"} == 1) printf("%-5s",":DOWN");
            if(${$tick . "ltrend"} == 2) printf("%-5s",":FLAT");
            if(${$tick . "ltrend"} == 3) printf("%-5s",":UP");
            print "\t  SPREAD:";
            printf("%-03.3F",${$tick . "mspread"}); 
            print "%\t  RSI:";
            printf("%-06.3F",${$tick . "rsi"});
            if(${$tick . "buyflag"} == $buyready) $cdastatus = "Buy Ready";
            if(${$tick . "buyflag"} == $buyprep) $cdastatus = "Buy Prep";
            if(${$tick . "buyflag"} == $buyord) $cdastatus = "Buy Order";
            if(${$tick . "buyflag"} == $sellok) $cdastatus = "Sell OK";
            if(${$tick . "buyflag"} == $sellready) $cdastatus = "Sell Ready";
            if(${$tick . "buyflag"} == $selldone) $cdastatus = "Sell Done";
            if(${$tick . "buyflag"} == $dontbuy) $cdastatus = "Dont Trade";
            print "\tS:$cdastatus \n";

// Trading rules start here
// ========================

// CDA is trending up so set to buyprep
            if(${$tick . "buyflag"} == $buyready AND ${$tick . "strend"}==3 AND ${$tick . "mtrend"}==3 AND ${$tick . "ltrend"}==3)
            {
              printf("%-9s",$key);
              print "Was Buyready, now Buyprep V:$value\n";
              ${$tick . "buyflag"} = $buyprep;
            }

// CDA was buyprep, now trending down, set to buyord if reasonable spread
            if(${$tick . "buyflag"} == $buyprep AND ${$tick . "strend"}==1 AND ${$tick . "mtrend"}==1 AND ${$tick . "ltrend"}==1 AND ${$tick . "mspread"} >= $minspread)
            {
              printf("%-9s",$key);
              print "Was Buyprep, now Buyord V:$value\n";
              ${$tick . "buyflag"} = $buyord;
            }

// CDA stopped trending down and is ready to buy
            if(${$tick . "buyflag"} == $buyord AND ${$tick . "strend"}!=1 AND ${$tick . "rsi"} <= $minrsi)
            {
              printf("%-9s",$key);
              print "Was Buyord, now Buy V:$value\n";
// Assume we buy at the current value
              ${$tick . "buyvalue"} = $value;
              ${$tick . "buyflag"} = $sellok;
              $fh = fopen($tradefile, "a") or die("Cannot open file");
              fwrite($fh, "========================== \n");
              fwrite($fh, "Runtime $run_time \n");
              fwrite($fh, "Buy on $key BV:${$tick . "buyvalue"} \n");
              fwrite($fh, "========================== \n");
              fclose($fh);
            }

// Buy Order on CDA placed, do order tracking here to make sure order completes
            if(${$tick . "buyflag"} == $sellok)
            {
// Since we are not placing an order, we just assume it completed
              ${$tick . "buyflag"} = $sellready;
            }

// **********************            
// **** START CHANGES ***
// **********************            

// Track Selling Stop Loss
// $pl is unrealized profit/loss of current holding
// $new_sl is current value trailing by 0.5% half a percent (1 - 0.005, thus 0.995)
            $pl = round(((($value - ${$tick . "buyvalue"})/${$tick . "buyvalue"})*100),3);
            $new_sl = round($value * 0.995, 6)
            if(${$tick . "buyflag"} == $sellready AND $pl > 2.0 AND ${$tick . "stoploss"} < $new_sl)
            {
              ${$tick . "stoploss"} = ($value * 0.9985);
            }

            if (${$tick . "buyflag"} == $sellready && $value <= ${$tick . "stoploss"})
            {
              ${$tick . "sellvalue"} = $value;
              ${$tick . "buyflag"} = $selldone;
              ${$tick . "stoploss"} = 0;
            }

// **********************            
// ***** END CHANGES ****
// **********************            

// CDA is sellready and is no longer trending upwards - time to sell
            if(${$tick . "buyflag"} == $sellready AND ${$tick . "strend"}!=3 AND ${$tick . "mtrend"}!=3)
            {
// Assume we sell at the current value
              ${$tick . "sellvalue"} = $value;
              ${$tick . "buyflag"} = $selldone;
              ${$tick . "stoploss"} = 0; // MWLANG
            }

// CDA is selldone
            if(${$tick . "buyflag"} == $selldone)
            {
// Sell Order on CDA placed, do order tracking here to make sure order completes
// Since we are not placing an order, we just assume it completed
              $q = round((((${$tick . "sellvalue"} - ${$tick . "buyvalue"})/${$tick . "buyvalue"})*100),3);
              $tpc = $q - 0.2;
              $rpc = $rpc + $tpc;
              ${$tick . "buyflag"} = $buyready;
              printf("%-9s",$key);
              print "Sell Done BV:${$tick . "buyvalue"} SV:${$tick . "sellvalue"} TPC:$tpc \n";
              $fh = fopen($tradefile, "a") or die("Cannot open file");
              fwrite($fh, "========================== \n");
              fwrite($fh, "Runtime $run_time \n");
              fwrite($fh, "Sell Done on $key BV:${$tick . "buyvalue"} SV:${$tick . "sellvalue"} TPC:$tpc \n");
              fwrite($fh, "========================== \n");
              fclose($fh);
            }
          }
        }
      }
    }
  }
  sleep(5);
}
?>

There are two or three lines I added within original script with a comment, “// MWLANG” So find those and add to your current script. Then there’s a big section within the trading rules section for setting and acting on stop/loss trigger, sectioned off with “START CHANGES” / “END CHANGES”

P.S. PHP is not my usual language, so extra scrutiny should be exercised on anything I add to the code to confirm it does what I intended it to do!


#229

Can you please add a semi-colon at the end of line 299 in your script:
$new_sl = round($value * 0.995, 6);


#230

@mwlang

What editor are you using? Like the coloured code. Makes it easier to read.


#231
<?php
require 'vendor/autoload.php';

// This bot will trade USDT to the other pairs and back to make more USDT
// It shall use all the trading pairs to make more UDST except the ones we tell it not to use

$strend = 100;            // Short Term Trend - must be less than $mtrend
$mtrend = 180;            // Medium Term Trend - must be less than $ltrend
$ltrend = 280;            // Long Term Trend

It’s not the editor that gives the colours it’s the forum formatting with backticks.

I would recommend notepad++ rather than notepad.


#232

@mwlang you need to check if $buyvalue > 0 at line 298 as it’s giving a lot of division by zero warnings.

After 92 minutes I’m at a 4.5% loss (including fees).


#233

As @Blynker pointed out…I posted with backticks and specifying “php” as the language.

For editor, try the open source Sublime Text editor: https://www.sublimetext.com/ Works great on Windows, Mac, and Linux. I found Sublime to be much more stable and consistently performing over the Atom editor for editors that can work across many OS’s. And of course, before you emacs folks start chiming in – you’ll have absolutely no luck prying vi from my hands. :stuck_out_tongue_winking_eye:

Michael


#234

Good catch on the division by zero, @Blynker

Wrap the whole block in a check for zero guard:

// **********************            
// **** START CHANGES ***
// **********************            

// Track Selling Stop Loss
// $pl is unrealized profit/loss of current holding
// $new_sl is current value trailing by 0.5% half a percent (1 - 0.005, thus 0.995)
            if(${$tick . "buyvalue"} > 0) {
              $pl = round(((($value - ${$tick . "buyvalue"})/${$tick . "buyvalue"})*100),3);
              $new_sl = round($value * 0.995, 6);
              if(${$tick . "buyflag"} == $sellready AND $pl > 2.0 AND ${$tick . "stoploss"} < $new_sl)
              {
                ${$tick . "stoploss"} = ($value * 0.9985);
              }

              if (${$tick . "buyflag"} == $sellready && $value <= ${$tick . "stoploss"})
              {
                ${$tick . "sellvalue"} = $value;
                ${$tick . "buyflag"} = $selldone;
                ${$tick . "stoploss"} = 0;
              }
            }

// **********************            
// ***** END CHANGES ****
// **********************            

I’m at around 8% running loss, so not really sure where the faulty decision is happening at the moment. Truth be told, I haven’t really had a chance to dig in since implementing a stop/loss trigger.

image

  • EDIT: fixed typo (missing semi-colon on line 301)

#235

Try changing strend to mtrend :wink:

Though, dont trust me right now, I’m pretty hungover lol

Stay Fishy


#236

With Mike’s latest revision I’m at 5.5 % gain, after fees, at 340 minutes.


#238

You can extract the zip into the directory with 7zip if you can’t use the command line. The “tasks” will be more complex so if it is problem for you to unzip things in Windows then you need some other, more basic skills to pick up first. No offense,


#239

Hey guys I created a github repo so we can all enjoy the ride without having to go back in multiples comments and not knowing were we saw the thing we want.

Of course, I encourage every one of you to contribute to the repo !! :smiley:
And also to ask questions if something is unclear !

(I can transfer the repo ownership to you @Mike_Fishy if you want?)


#240

@Mike_Fishy I think it would be great to keep your thread clean. Before this one becomes a mess I would separate your materials from others and the comments. We should create another thread to discuss the things you contribute into this thread. What do you think?

update: kudos for @BTL creating repo on github.


#241

Thanks bud and no offense taken. I actually used 7zip originally to unzip the file, but encountered another error on step 3, which is why I thought I did something wrong on step 2. But yeh I guess this might be too much more me at this stage. Might just spectate you guys.


#242

What version of Windows are you using?