/**
 * https://www.forexfactory.com/thread/1270740-which-trade-setup-has-the-highest-probability
 *
 *  $ javac ExpectedReturn.java
 *  $ java ExpectedReturn
 */
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class ExpectedReturn {

   private static double STOP_LOSS = 0.00500;
   private static double TAKE_PROFIT = 0.01000;
   private static double BE_LEVEL = 0.00000;
   private static boolean TRAILING_SL = false;
   private static double RISK_PERCENT = 1.0;
   private static double COST = 0.00050;

   private static int NR_TICKS = 10_000_000;
   private static int NR_RUNS = 200_000;
   private static double START_BALANCE = 10_000.0;
   private static String FILENAME = "return-50-100.csv";

   /**
    * @param args the command line arguments
    * @throws java.io.IOException
    */
   public static void main(String[] args) throws IOException {
      Locale.setDefault(Locale.US);
      FileWriter writer = new FileWriter(FILENAME);

      Random random = ThreadLocalRandom.current();

      for (int run = 0; run < NR_RUNS; run++) {
         double price = 1.00000;
         double equity = START_BALANCE;
         int sign = 0;
         double volume = 0.0;
         double takeProfit = 0.0;
         double beLevel = 0.0;
         double stopLoss = 0.0;
         double entry = 0.0;
         int nrTrades = 0;

         for (int tick = 0; tick < NR_TICKS; tick++) {
            // update price
            if (random.nextBoolean()) {
               price *= 1.00001;
            } else {
               price /= 1.00001;
            }

            if (sign != 0) {
               // check stops
               if (sign * price >= sign * takeProfit || sign * price <= sign * stopLoss) {
                  equity += sign * volume * (price - entry) - volume * COST;
                  sign = 0;
                  nrTrades++;
               } else {
                  // check BE
                  if (beLevel != 0.0 && sign * price >= sign * beLevel) {
                     stopLoss = entry;
                  }
                  // check trailing SL
                  if (TRAILING_SL) {
                     double newSL = price - sign * STOP_LOSS;
                     if (sign * newSL > sign * stopLoss) {
                        stopLoss = newSL;
                     }
                  }
               }
            } else {
               // make entry
               sign = random.nextBoolean() ? -1 : +1;
               takeProfit = price + sign * TAKE_PROFIT;
               stopLoss = price - sign * STOP_LOSS;
               beLevel = (BE_LEVEL == 0.0 ? 0.0 : price + sign * BE_LEVEL);
               double amountRisked = equity * RISK_PERCENT / 100.0;
               volume = amountRisked / STOP_LOSS;
               entry = price;
            }
         }

         writer.write(String.format("%.5f, %d\n", equity / START_BALANCE, nrTrades));
      }

      writer.close();
      System.out.printf("Written \"%s\"\n", FILENAME);
   }
}
