Advertisement
Guest User

Bitburner investment broker script

a guest
Dec 3rd, 2017
1,033
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //--------------------------------------------------------------------------------------------------------------------------
  2. //---------------------------InvestmentBroker.script------------------------------------------------------------------------
  3. //--------------------------------------------------------------------------------------------------------------------------
  4.  
  5. // Clear database
  6. write("_Investment_DB.txt","","w");
  7.  
  8. // Clean ports
  9. for (portId = 1; portId <= 10; portId++)
  10. {
  11.     inputCommand = ""
  12.     while (inputCommand !== 'NULL PORT DATA')
  13.     {
  14.         print(inputCommand);
  15.         inputCommand = read(portId);
  16.     }
  17. }
  18.  
  19. run("_InvestmentBroker.script", 1);
  20.  
  21. //--------------------------------------------------------------------------------------------------------------------------
  22. //---------------------------_InvestmentBroker.script-----------------------------------------------------------------------
  23. //--------------------------------------------------------------------------------------------------------------------------
  24.  
  25. // kill any scripts from previous run
  26. localHost = getHostname();
  27. scriptKill("_InvestmentBroker_Data.script", localHost);
  28. scriptKill("_InvestmentBroker_Manager.script", localHost);
  29.  
  30. COMMISION_FEE = 100000;
  31.  
  32. INPUT_PORT = 10;
  33.  
  34. // Stock ID (add entries here to handle more stocks)
  35. function GetStockParamId(stockSymbol)
  36. {
  37.     if (stockSymbol === "APHE") return 0;
  38.     if (stockSymbol === "CTYS") return 1;
  39.     if (stockSymbol === "JGN") return 2;
  40.     if (stockSymbol === "SGC") return 3;
  41.     return -1;
  42. }
  43.  
  44. // Stock paramaters, according to id returned by GetStockParamId
  45. // Moving Average size, History buffer size, buy/sell threshold (0.01 - 1%)
  46. STOCK_PARAMS = [];
  47. STOCK_PARAMS[0] = [9, 5, 0.01];
  48. STOCK_PARAMS[1] = [5, 10, 0.01];
  49. STOCK_PARAMS[2] = [7, 7, 0.01];
  50. STOCK_PARAMS[3] = [5, 6, 0.01];
  51.  
  52. // Port assignment per stock
  53. StockPort = [-1, -1, -1, -1];
  54.  
  55. freePort = 1;
  56.  
  57. // Managed stock data, each managed stock will have an entry here (with the stock port as index) containing an array with the following data:
  58. // 0 : StockSymbol
  59. // 1 : available cash
  60. // 2 : starting cash
  61. // 3 : starting price
  62. // 4 : total worth
  63. ManagerData = [];
  64.  
  65. function SaveManagerDataInDB()
  66. {
  67.     // Write current managed stock data to file, will be used to restart the script after a reload
  68.     write("_Investment_DB.txt","","w");
  69.     for (i = 1; i < freePort; i++)
  70.     {
  71.         if (ManagerData[i][0] !== "")
  72.         {
  73.             write("_Investment_DB.txt", i + "," + ManagerData[i][0] + "," + ManagerData[i][1] + "," + ManagerData[i][2] + "," + ManagerData[i][3] + "," + ManagerData[i][4] + "|");
  74.         }
  75.     }  
  76. }
  77.  
  78. previousData = read("_Investment_DB.txt");
  79. if (previousData !== "")
  80. {
  81.     // load previous run data
  82.     previousData = previousData.split("|");
  83.     for (i = 0; i < previousData.length - 1; i++)
  84.     {
  85.         data = previousData[i].split(",");
  86.         stockId = 1 * data[0];
  87.         ManagerData[stockId] = [];
  88.         ManagerData[stockId][0] = data[1];
  89.         ManagerData[stockId][1] = 1 * data[2];
  90.         ManagerData[stockId][2] = 1 * data[3];
  91.         ManagerData[stockId][3] = 1 * data[4];
  92.         ManagerData[stockId][4] = 1 * data[5];
  93.         if (stockId >= freePort)
  94.         {
  95.             freePort = stockId + 1;
  96.         }
  97.         StockPort[GetStockParamId(data[1])] = stockId;
  98.     }
  99.    
  100.     // re-run previous managers with new cash argument
  101.     for (i = 1; i < freePort; i++)
  102.     {
  103.         stockSymbol = ManagerData[i][0];
  104.         stockParamId = GetStockParamId(stockSymbol);
  105.         run("_InvestmentBroker_Data.script", 1, stockSymbol, i, STOCK_PARAMS[stockParamId][0]);
  106.         run("_InvestmentBroker_Manager.script", 1, stockSymbol, i, STOCK_PARAMS[stockParamId][1], STOCK_PARAMS[stockParamId][2], ManagerData[stockId][1]);
  107.     }
  108. }
  109.  
  110. doLoop = true;
  111.  
  112. while (doLoop)
  113. {
  114.     inputCommand = read(INPUT_PORT);
  115.     if (inputCommand !== 'NULL PORT DATA')
  116.     {
  117.         inputCommand = inputCommand.split(" ");
  118.         if (inputCommand[0] == "A" && freePort < INPUT_PORT)
  119.         {
  120.             // Add a new managed stock
  121.             stockSymbol = inputCommand[1];
  122.             stockParamId = GetStockParamId(stockSymbol);
  123.             run("_InvestmentBroker_Data.script", 1, inputCommand[1], freePort, STOCK_PARAMS[stockParamId][0]);
  124.             run("_InvestmentBroker_Manager.script", 1, inputCommand[1], freePort, STOCK_PARAMS[stockParamId][1], STOCK_PARAMS[stockParamId][2], 1 * inputCommand[2]);
  125.             print("Adding managed stock " + inputCommand[1] + ", cash: " + inputCommand[2] + "$");
  126.             stockPrice = getStockPrice(stockSymbol);
  127.             cash = 1 * inputCommand[2];
  128.             ManagerData[freePort] = [];
  129.             ManagerData[freePort][0] = stockSymbol;
  130.             ManagerData[freePort][1] = cash;
  131.             ManagerData[freePort][2] = cash;
  132.             ManagerData[freePort][3] = stockPrice;
  133.             ManagerData[freePort][4] = cash;
  134.             SaveManagerDataInDB();
  135.             StockPort[stockParamId] = freePort;
  136.             freePort++;
  137.         }
  138.  
  139.         if (inputCommand[0] == "L")
  140.         {
  141.             // Liquidate stock
  142.             stockSymbol = inputCommand[1];
  143.             stockParamId = GetStockParamId(stockSymbol);
  144.             stockId = StockPort[stockParamId];
  145.             if (stockId != -1)
  146.             {
  147.                 // Kill Data gathering script
  148.                 kill("_InvestmentBroker_Data.script", localHost, stockSymbol, stockId, STOCK_PARAMS[stockParamId][0]);
  149.                 // Send liquidation command to manage script (it is not killed immediatly to ensure any queued stock transactions will be handled before selling a stock to avoid selling with the wrong price)
  150.                 write(stockId, "_L");
  151.             }
  152.         }
  153.  
  154.         if (inputCommand[0] == "__L")
  155.         {
  156.             // Liquidation response from manage script, script has terminated and any outstanding transactions has been processed
  157.             stockId = 1 * inputCommand[1];
  158.             stockSymbol = ManagerData[stockId][0];
  159.             stockPrice = getStockPrice(stockSymbol);
  160.             stockData = getStockPosition(stockSymbol);
  161.             profit = stockData[0] * (stockPrice - stockData[1]);
  162.             if (profit > COMMISION_FEE * 2)
  163.             {
  164.                 sellStock(stockSymbol, stockData[0]);
  165.                 print("Sold " + stockSymbol + " shares for " + profit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$");
  166.                 ManagerData[stockId][4] = ManagerData[stockId][4] + profit;
  167.  
  168.             }
  169.             else
  170.             {
  171.                 sellPrice = stockData[1] + (COMMISION_FEE * 2 / stockData[0]);
  172.                 placeOrder(stockSymbol, stockData[0], sellPrice, "limitsell", "long");
  173.                 tprint("placed limit sell order on " + stockSymbol + " for " + stockData[0] + " shares at " + sellPrice.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$");
  174.             }
  175.             holdProfit = ((ManagerData[stockId][2] - COMMISION_FEE) / ManagerData[stockId][3]) * (stockPrice - ManagerData[stockId][3]);
  176.             profit = ManagerData[stockId][4] - ManagerData[stockId][2];
  177.             tprint("Final profit for " + stockSymbol + ": " + profit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$ (" +
  178.                     holdProfit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$)");
  179.            
  180.             // End managment for stock
  181.             ManagerData[stockId][0] = "";
  182.             SaveManagerDataInDB();
  183.         }
  184.  
  185.         if (inputCommand[0] == "_Sb")
  186.         {
  187.             // Process stock purchase transaction
  188.             stockId = 1 * inputCommand[1];
  189.             cost = 1 * inputCommand[2];
  190.             print("Bought " + ManagerData[stockId][0] + " shares for " + cost.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$");
  191.            
  192.             // Update available cash reserve
  193.             ManagerData[stockId][1] = ManagerData[stockId][1] - cost;
  194.             SaveManagerDataInDB();
  195.         }
  196.        
  197.         if (inputCommand[0] == "_Ss")
  198.         {
  199.             // Process stock sale transaction
  200.             stockId = 1 * inputCommand[1];
  201.             income = 1 * inputCommand[2];
  202.             print("Sold " + ManagerData[stockId][0] + " shares for " + income.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$");
  203.            
  204.             // Update available cash reserve and total worth
  205.             ManagerData[stockId][1] = ManagerData[stockId][1] + income;
  206.             ManagerData[stockId][4] = ManagerData[stockId][1];
  207.             SaveManagerDataInDB();
  208.         }
  209.        
  210.         if (inputCommand[0] == "S")
  211.         {
  212.             // Print stock status
  213.             totalProfit = 0;
  214.             totalHoldProfit = 0;
  215.             for (i = 1; i < freePort; i++)
  216.             {
  217.                 if (ManagerData[i][0] !== "")
  218.                 {
  219.                     profit = ManagerData[i][4] - ManagerData[i][2];
  220.                     totalProfit += profit;
  221.                     stockData = getStockPosition(ManagerData[i][0]);
  222.                     stockPrice = getStockPrice(ManagerData[i][0]);
  223.                     holdProfit = ((ManagerData[i][2] - COMMISION_FEE) / ManagerData[i][3]) * (stockPrice - ManagerData[i][3]);
  224.                     totalHoldProfit += holdProfit;
  225.                     tprint(ManagerData[i][0] + ": " + stockData[0] + " Shares, Profit: " + profit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$ (" +
  226.                             holdProfit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$)");
  227.                 }
  228.             }
  229.             tprint("Total profit: " + totalProfit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$ (" +
  230.                         totalHoldProfit.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + "$)");
  231.         }
  232.     }  
  233. }
  234.  
  235. //--------------------------------------------------------------------------------------------------------------------------
  236. //---------------------------_InvestmentBroker_Data.script------------------------------------------------------------------
  237. //--------------------------------------------------------------------------------------------------------------------------
  238.  
  239. StockSymbol = args[0];
  240. DATA_PORT = args[1];
  241. MovingAverageSize = args[1];
  242.  
  243. prices = [];
  244. sum = 0;
  245. lastPrice = -1;
  246.  
  247. while(true)
  248. {
  249.     price = getStockPrice(StockSymbol);
  250.     if (price != lastPrice)
  251.     {
  252.         prices.push(price);
  253.         sum += price;
  254.         if (prices.length > MovingAverageSize)
  255.         {
  256.             sum -= prices.shift();
  257.             avg = sum/MovingAverageSize;
  258.             write(DATA_PORT, avg);
  259.         }
  260.         lastPrice = price;
  261.     }
  262. }
  263.  
  264. //--------------------------------------------------------------------------------------------------------------------------
  265. //---------------------------_InvestmentBroker_Manager.script---------------------------------------------------------------
  266. //--------------------------------------------------------------------------------------------------------------------------
  267.  
  268. COMMISION_FEE = 100000;
  269. INPUT_PORT = 10;
  270.  
  271. localHost = getHostname();
  272.  
  273. StockSymbol = args[0];
  274. DATA_PORT = args[1];
  275. HistorySize = args[2];
  276.  
  277. BuyThreshold = 1 + args[3];
  278. SellThreshold = 1 - args[3];
  279.  
  280. cash = args[4];
  281.  
  282. movingAverageHistory = [];
  283.  
  284. doLoop = true;
  285.  
  286. while (doLoop)
  287. {
  288.     movingAverage = read(DATA_PORT);
  289.     if (movingAverage === "_L")
  290.     {
  291.         // Liquidate command given, terminate script
  292.         doLoop = false;
  293.         write(INPUT_PORT, "__L " + DATA_PORT);
  294.     }
  295.     else if (movingAverage !== 'NULL PORT DATA')
  296.     {
  297.         movingAverageHistory.push(movingAverage);
  298.         if (movingAverageHistory.length > HistorySize)
  299.         {
  300.             previousMovingAverage = movingAverageHistory.shift();
  301.             if (movingAverage > (previousMovingAverage * BuyThreshold))
  302.             {
  303.                 // MA is trending up, buy stocks if cash is available
  304.                 additionalCost = 0;
  305.                 prevStockData = getStockPosition(StockSymbol);
  306.                 stockPrice = getStockPrice(StockSymbol);
  307.                 if (cash > stockPrice + COMMISION_FEE)
  308.                 {
  309.                     // Calculate amount of stocks to purchase
  310.                     newShares = Math.floor((cash - additionalCost - COMMISION_FEE) / stockPrice);
  311.                     while (!buyStock(StockSymbol, newShares) && newShares > 0)
  312.                     {
  313.                         // We failed to buy stocks, adjust cash and retry
  314.                         availableCash = getServerMoneyAvailable("home");
  315.                         if (availableCash < cash)
  316.                         {
  317.                             // Less cash is available then should be (can happen due to purchase/sell orders happening at a different price then we measured or simply because the user spent the money on something)
  318.                             // Adjust cost to account for discrepency (I'm adjusting the cose instead of the available cash to reflect the missing cash in the broker script)
  319.                             additionalCost += (cash - availableCash);
  320.                         }
  321.                         // Recalculate amount of stocks to purchase
  322.                         newShares = Math.floor((cash - additionalCost - COMMISION_FEE) / getStockPrice(StockSymbol));
  323.                     }
  324.                     if (newShares > 0)
  325.                     {
  326.                         stockData = getStockPosition(StockSymbol);
  327.                         if (prevStockData[0] === 0)
  328.                         {
  329.                             cost = (COMMISION_FEE + (newShares * stockData[1]));
  330.                         }
  331.                         else
  332.                         {
  333.                             cost = COMMISION_FEE + ((stockData[1] * stockData[0]) - (prevStockData[1] * prevStockData[0]));
  334.                         }
  335.                         cost += additionalCost;
  336.                         cash -= cost;
  337.                         // Send transaction data to broker
  338.                         write(INPUT_PORT, "_Sb " + DATA_PORT + " " + cost);
  339.                     }
  340.                 }
  341.             }
  342.             if (movingAverage < (previousMovingAverage * SellThreshold))
  343.             {
  344.                 // MA is trending down, sell stocks if it's profitable
  345.                 stockData = getStockPosition(StockSymbol);
  346.                 stockPrice = getStockPrice(StockSymbol);
  347.                 profit = stockData[0] * (stockPrice - stockData[1]);
  348.                 if (profit > COMMISION_FEE * 2)
  349.                 {
  350.                     sellStock(StockSymbol, stockData[0]);
  351.                     stockPrice = getStockPrice(StockSymbol);
  352.                     income = (stockData[0] * stockPrice) - COMMISION_FEE;
  353.                     cash += income;
  354.                     // Send transaction data to broker
  355.                     write(INPUT_PORT, "_Ss " + DATA_PORT + " " + income);
  356.                 }
  357.             }
  358.         }
  359.     }
  360. }
  361.  
  362. //--------------------------------------------------------------------------------------------------------------------------
  363. //---------------------------_InvestmentBroker_Msg.script-------------------------------------------------------------------
  364. //--------------------------------------------------------------------------------------------------------------------------
  365.  
  366. INPUT_PORT = 10;
  367. msg = "";
  368. for (i = 0; i < args.length; i++)
  369. {
  370.     msg = msg + args[i] + " ";
  371. }
  372. write(INPUT_PORT, msg);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement