[Question]
  [
The stock market is all about the speed of knowledge. Unlike previous challenges, **the current stock price is not random: it is determined by those playing the game.** If you can identify an under-priced stock before anybody else, then you've written yourself a money-making program.
***Price* refers to the how much people are trading the stock for, while *Value* refers to the amount the stock is worth at the end of the game.**
Each player starts with 1000 of each stock, and 0 relative net worth. **Each stock has a secret value, and your score at the end of the game is `(stockValue for each ownedStock) + netWorth`**. Your net worth can be negative. In an N-player game, there are N stocks.
# Steps:
The game follows the following steps:
1. You are given the secret value of a single stock.
2. You make an offer to sell X of Y stock for $Z
3. All players are given the offers, and each may choose one to accept
4. All players are informed of accepted offers
5. Go back to step 2
Each of the steps are given in detail below:
1. `void secretValue(int stockType, int value)`:
	* The value you learn is not revealed to any other player.
	* The value is between `0` and `1000`
	* Low values are more like to occur than high values (squared uniform distribution)
2. `Offer makeOffer(List<Stock> currentStock)`
	* You can return `null` to make no offer.
3. `Offer acceptOffer(List<Offer> offers)`
	* You can return `null` to accept none of them
	* If there are no available offers, this will not be called
	* If you accept, your net worth goes down by $Z (can go negative) and receive X of Y stock. The opposite occurs with the seller.
	* If you accept an offer, the exchange will occur immediately, and the offer will be removed so additional players cannot accept it.
4. `void acceptedOffers(List<Offer> offers)`
	* Includes your accepted offers as well
Static variables or writing to files is not allowed. (No persistent data from game to game) Non-serious contenders are allowed.
Interfaces:
```
public final class Stock {
    public Stock(int stockType, int amount);
    public int getType();
    public int getAmount();
    public Stock minus(Stock other);
    public Stock plus(Stock other);
    public Stock minus(int amount);
    public Stock plus(int amount);
    public Stock setAmount(int amount);
}
public class Offer {
    public Offer(Stock offer, int payment);
    public Stock getOffer();
    public int getPayment();
}
```
**Non-Java submissions:**
* All calls consist of two lines: The first line is the function being called: `SecretValue`, `MakeOffer`, `AcceptOffer`, `AcceptedOffers`, `SetRandom`, and the second line containing the actual data.
* Stocks are formatted with a `:` delimiter: `stockType:stockAmount`.
* Offers are formatted with a `@` delimiter: `offer@price`
* Lists are formatted with a `;` delimiter
* `SecretValue` is formatted with a `:` delimiter: `stockType:value`
* `RandomSeed` is used to make your submission deterministic. If your submission uses randomness, please use the integer value passed as the seed!
* All function calls *need* a response. If the response is `null` or `void`, return an empty string.
* Please include a `command.txt` that gives the command line arguments to run your submission
# Scoring
Games consisting of 1000 turns will be run multiple times. Players will be scored according to the [ELO system](https://en.wikipedia.org/wiki/Elo_rating_system), and paired with players of similar skill levels. The player with the highest final ELO score wins! (I've modified the system so that each game, ELO scores are updated for each player pairing)
The controller includes an autodownloader, so please start your submission with a header: `Name, Language`. If your submission is not in Java, each code block should start with the name of the file. (excluding the command file, which should be the first block in your post)
# Running
There are 2 ways to run this project:
1. Download the source code, compile and run. You can find the source on [Github](https://github.com/nathanmerrill/StockExchange). Run `git clone --recursive https://github.com/nathanmerrill/StockExchange.git`
2. Download the JAR executable. Submissions should be placed in your current working directory in the `/submissions` folder. You can download just the [JAR](https://github.com/nathanmerrill/StockExchange/blob/archives/StockExchange.jar), just the [submissions](https://github.com/nathanmerrill/StockExchange/blob/archives/StockExchangePlayers.zip), or [both](https://github.com/nathanmerrill/StockExchange/blob/archives/StockExchange.zip)
Pass in `run` to run the project (default option), or pass in `download` to download all submissions so far from this question.
# Scoreboard
```
1.  1308.1220497323848  Cheater
2.  1242.0333695640356  InsideTrader
3.  1158.3662658295411  UncleScrooge
4.  1113.8344000358493  BlackMarket
5.  1051.8370015258993  DartMonkey
6.  983.0545446731494   WarGamer
7.  939.457423938002    Spammer
8.  901.4372529538886   DumbBot
9.  859.0519326039137   ShutUpAndTakeMyMoney
10. 852.9448222849587   VincentKasuga
11. 718.2112067329083   Profiteer
```
  
[Answer]
# Cheater, Java
Tries to sell nothing for money.
```
import java.util.List;
import java.util.Random;
import com.ppcg.stockexchange.*;
public class Cheater extends Player {
    private Random random = new Random();
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        Stock stock = randomStock();
        int price = random.nextInt(100) + 1;
        return new Offer(stock.setAmount(0), price);
    }
}
```
[Answer]
# WarGamer, Java
Upon a perfunctory examination of the rules I have decided that the primary winning move is not to play. Anyone offering to sell stock likely knows the price and will profit from the sale. It can be toggled so it will make "joke" offers to sell a stock for Integer.MAX\_VALUE dollars hoping shut up and take my money will bite.
```
import java.util.List;
import com.ppcg.stockexchange.*;
import com.ppcg.kothcomm.game.AbstractPlayer;
import com.ppcg.kothcomm.utils.Tools;
import java.util.List;
public class WarGamer extends Player {
static final boolean FRAUD = false;
    /**
     * @param offers All available offers
     * @return An offer you want to accept, or null if you want to accept neither.
     */
    public Offer acceptOffer(List<Offer> offers){
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
    if(FRAUD)
    return new Offer(new Stock(0,1),Integer.MAX_VALUE);
        //defraud shut up and take my money            
    return null;
    }
}
```
[Answer]
# ShutUpAndTakeMyMoney, Java
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class ShutUpAndTakeMyMoney extends Player {
    public ShutUpAndTakeMyMoney() {}
    public Offer acceptOffer(List<Offer> offers) {
        try {
            return offers.get(0);
        } catch (Exception ex) {
            return null;
        }
    }
    public Offer makeOffer(List<Stock> stock) {
        return null;
    }
}
```
It accepts any offer.
[Answer]
# DumbBot, Java
Use this bot when creating your own. Offers its secret stock at a discounted price.
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class DumbBot extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        return new Offer(currentStock.get(secretStockType).setAmount(1), Math.max(1, secretStockValue - 5));
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}
```
[Answer]
# python\_starter, Python 3
Use this as a starting point for any python (or other language) programs
Accepts a random offer.
Command file:
```
python3 starter.py
```
Program:
```
starter.py
import random
from functools import total_ordering
LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'
@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))
    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)
    def __str__(self):
        return str(self.type)+STOCK_DELIMITER+str(self.amount)
    def __eq__(self, other):
        return self.amount == other.type
    def __lt__(self, other):
        return self.amount < other.amount
    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)
    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)
    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)
    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)
    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)
class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            offer, payment = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(offer), int(payment.strip()))
    def __init__(self, offer: Stock, payment: int):
        self.offer = offer
        self.payment = payment
    def __str__(self):
        return str(self.offer)+OFFER_DELIMITER+str(self.payment)
def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)
def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(str(output))
    else:
        print()
def read_seed(seed: str):
    random.seed(int(seed))
def start():
    while True:
        process_input()
hidden_stock = None
hidden_price = None
def make_offer(current_stock: str):
    current_stock = map(Stock.parse, current_stock.split(LIST_DELIMITER))
    pass
def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    return random.sample(available_offers, 1)[0]
def accepted_offers(offers: str):
    offers = map(Offer.parse, offers.split(LIST_DELIMITER))
    pass
if __name__ == "__main__":
    start()
```
[Answer]
# VincentKasuga, Java
Not sure if my Java is valid. Please review. 
## How it works
~~- if you own all the stocks, you can set the price of the stock. You are the only seller.
 1. Buy all the stocks.
 2. Set the price of all the stocks to be super high on the last tick.
 3. **PROFIT!**
 - This isn't normally possible because...~~
* The price would usually skyrocket to infinity... but there's a limit!
* ... (more reasons to come)
## How it works, v2
* The price is artificially set at a maximum by some anarchist state
* This is bad economically
* **The bot doesn't predict - it exploits an inherent flaw in the structure of the market!**
## Todo
* Corner the market multiple times! Muahaha!
## FAQ
**Q:** Who's Vincent Kasuga?
**A:** He bought all the onions and onion futures in the United States. (put them all in a secret warehouse) Held the industry at ransom - give me X million or I'll set the price sky-low and you'll all go bankrupt.
But he didn't stop there.
Then, he secretly shorted the onion ETF (bet that it would go down). He sold all the onions at one time, physically delivering them in thousands of trucks to the stock exchange. The onion bag cost less than the onions. He made millions AGAIN. In short, the Hudson river overflowed with onions. 
He's a real person.
## The code
```
import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;
import java.util.List;
public class VincentKasuga extends Player {
    private int knownStock;
    private int knownPrice;
    private int corneredStockType = -1;
    private int corneredLikelehood = 0;
    private boolean marketCornered;
    private int ticks;
    public Offer acceptOffer(List<Offer> offers) {
        if (!marketCornered) {
            Offer maxOffer = null;
            int maxAmount = 0;
            if (corneredStockType == -1) {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            } else {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount && offer.getOffer().getType() == corneredStockType) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            }
            if (maxOffer == null) {
                // may have cornered the market
                corneredLikelehood++;
                if (corneredLikelehood == 5) {
                    // probably cornered the market
                    marketCornered = true;
                }
            }
            return maxOffer;
        } else {
            // who needs offers when the market is cornered!?
            return null;
        }
    }
    public Offer makeOffer(List<Stock> currentStock) {
        ticks++;
        if (ticks >= 999) {
            // SELL SELL SELL!
            return new Offer(new Stock(corneredStockType, 1000), 1000);
        } else {
            return null;
        }
    }
    public void secretValue(int stockType, int value) {
        knownStock = stockType;
        knownPrice = value;
        if (stockType == corneredStockType) {
            if (knownPrice == 1000) {
                corneredLikelehood += 3;
            } else if (knownPrice < 900){
                // didn't corner the market.
                corneredLikelehood = 0;
            }
        }
    }
}
```
---
*"I've cornered the Gold Market, Mr. Bond!"*
[Answer]
# Spammer, Java
```
import java.util.List;
import java.util.ArrayList;
import com.ppcg.stockexchange.*;
public class Spammer extends Player {
    private boolean panic = false;
    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.panic || offer.getPayment() < 20)
                return offer;
        }
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock) {
        if (currentStock.size() > 1) { // Don't sell all the stock
            this.panic = false;
            return new Offer(currentStock.get(secretStockType).setAmount(1), 1);
        }
        this.panic = true; // BUY
        return null;
    }
}
```
Spam the market with really cheap stock, and only buy stock when the price is lesser than 20. When the stock count fall to 1, it will try to buy anything.
[Answer]
# DartMonkey, Java
(non-competing: It won't win and I already have another answer)
Dart monkey likes throwing things... and there's a big pile of pointy sticks next to him. He sees some paper on the wall. Bam! Bam! Bam! In no time at all, Dart Monkey's thrown 80 darts! Half the darts are red, and the other half are blue, and there's random numbers on them! Dart monkey sees a computer... dart monkey types in the numbers. Dart monkey likes numbers. Dart monkey makes some money from his darts...
---
In all seriousness, DartMonkey initializes an integer array that has a length that is twice the number of stocks. He stores one number for the amount of stock he wants to buy/sell, and one number for the price of the stock. He then alternates selling stock from the array, and accepting offers according to the array. If he has no stock from the array, he won't offer anything, and if he has no offers given to him from the array, he won't accept anything.
---
[Answer]
# InsideTrader, Java
InsideTrader just looked around and saw that everybody was trying to be creative. But he did something creative: do what is expected.
This bot buys when it's "worth it" because it "borrowed" some "internal documents" to "guide" "investing decisions".
To-Do and how it works in the code. ;)
## The "code"
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class InsideTrader extends Player {
    public String coverStory = "I can tell the good companies from the bad ones.";
    private String theTruth = "I'm cheating. (but so is everyone else)";
    private String ambitions = "Learn to \"follow the market\"";  // don't steal this idea
    private int secretStock = -1;
    private int secretStockValue = -1;
    private int appraiseOffer(Offer offer) {
        /* get how much the offer is worth, 0 if it's not the secret stock */
        if (offer.getOffer().getType() != secretStock ||offer.getOffer().getAmount() == 0) {
            return 0;
        }
        return (offer.getPayment()/offer.getOffer().getAmount())  // price per stock...
                - secretStockValue  // minus value of stock.
                ;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer bestOffer = null;
        int bestOfferValue = -1;
        for (Offer offer :
                offers) {
            int value = appraiseOffer(offer);
            if (value > bestOfferValue && value > 0) {
                bestOfferValue = value;
                bestOffer = offer;
            }
        }
        return bestOffer;
    }
    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1), Integer.MAX_VALUE);
    }
    public void secretValue(int stockType, int value) {
        secretStock = stockType;
        secretStockValue = value;
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}
```
[Answer]
# WallStreet, Kotlin
Starts by selling high and buying low and gradually shifts to what it thinks the price really is. Also, you can use this as a template for making your own in kotlin.
**Note:** There is a bug in here that I can't seem to reliably reproduce. If my program crashes or has problems, please ping me in [chat](http://chat.stackexchange.com/rooms/44660/stock-exchange) and link a pastebin of the contents of `submissions/other/WallStreet/log.txt`
```
kotlinc WallStreet.kt
kotlin WallStreetKt
```
```
WallStreet.kt
import java.io.FileOutputStream
import java.io.PrintStream
import java.util.*
val LOGGER = PrintStream(FileOutputStream("log.txt", true))
const val DEBUG = false
const val LOG_GAME_HEADER = """
###############
#STARTING GAME#
###############"""
data class Stock(val type : Int, val amount : Int) {
    operator fun minus(amount : Int) = copy(amount = this.amount - amount)
    operator fun plus(amount: Int) = copy(amount = this.amount + amount)
    fun setAmount(amount: Int) = copy(amount = amount)
    operator fun minus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount - other.amount)
    }
    operator fun plus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount + other.amount)
    }
    override fun toString() = "$type:$amount"
}
data class Offer(val offer: Stock, val payment: Int) {
    override fun toString() = "$offer@$payment"
}
fun parseStock(repr : String) : Stock {
    val data = repr.split(":").map { it.toInt() }
    return Stock(data[0], data[1])
}
fun parseOffer(repr: String) : Offer {
    val data = repr.split("@")
    return Offer(parseStock(data[0]), data[1].toInt())
}
fun parseOffers(repr: String) = if (repr == "") emptyList<Offer>() else repr.split(";").map { parseOffer(it) }
interface Player {
    fun secretValue(stockType: Int, value: Int)
    fun makeOffer(currentStock: List<Stock>) : Offer?
    fun acceptOffer(offers: List<Offer>) : Offer?
    fun acceptedOffers(offers: List<Offer>)
    var random : Random
}
fun main(args : Array<String>) {
    try {
        if (DEBUG) {
            LOGGER.println(LOG_GAME_HEADER)
        }
        //Change bot name here
        val player = WallStreet()
        while (true) {
            val function = readLine()
            function ?: return
            val line = readLine()!!
            if (DEBUG) {
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
            }
            var result : Any
            try {
                result = when (function) {
                    "SecretValue" -> {
                        val data = line.split(":").map { it.toInt() }
                        player.secretValue(data[0], data[1])
                    }
                    "MakeOffer" -> player.makeOffer(line.split(";").map { parseStock(it) }) ?: ""
                    "AcceptOffer" -> player.acceptOffer(parseOffers(line)) ?: ""
                    "AcceptedOffers" -> player.acceptedOffers(parseOffers(line))
                    "RandomSeed" -> player.random = Random(line.toLong())
                    else -> return        //Exit program
                }
                if (function == "AcceptOffer" && result.toString() !in line) {
                    throw Exception("Offer not among available offers!!!!\nResult: $result\nParsed Available Offers: ${parseOffers(line)}")
                }
            } catch (e : Exception) {
                LOGGER.println("Turn #${player.turn}")
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
                throw e
            }
            if (result == Unit) {
                result = ""
            }
            if (DEBUG) {
                LOGGER.println("Output:")
                LOGGER.println(result)
            }
            println(if (result == Unit) "" else result)
        }
    } catch (e : Exception) {
        e.printStackTrace(LOGGER)
        throw e
    } finally {
        LOGGER.close()
    }
}
// ###################################################
// #          Put program logic below here.          #
// ###################################################
const val DEFAULT_STOCK_VALUE = 333
const val MAX_TURNS = 1000
const val MAX_STOCK_VALUE = 1000
class WallStreet : Player {
    var secretStockType = 0
    var secretStockValue = 0
    override var random = Random()
    var turn = 0
    val stockPriceStatistics = mutableMapOf<Int, DoubleSummaryStatistics>()
    override fun secretValue(stockType: Int, value: Int) {
        secretStockType = stockType
        secretStockValue = value
    }
    override fun makeOffer(currentStock: List<Stock>): Offer {
        val stock = currentStock[random.nextInt(currentStock.size)]
        val type = stock.type
        val amount = random.nextInt(stock.amount)
        val price = getSellPrice(type) * amount
        return Offer(Stock(type, amount), Math.ceil(price).toInt())
    }
    override fun acceptOffer(offers: List<Offer>): Offer? {
        var bestOffer : Offer? = null
        var mostProfit = 0.0
        for (offer in offers) {
            val offerProfit = profitOfOffer(offer)
            if (offerProfit > mostProfit) {
                bestOffer = offer
                mostProfit = offerProfit
            }
        }
        if (bestOffer != null && bestOffer !in offers) {
            throw IllegalStateException("Tried to accept non-existent offer.\nOffer:  $bestOffer\nAvailable Offers: ${offers.joinToString(";")}")
        }
        return bestOffer
    }
    override fun acceptedOffers(offers: List<Offer>) {
        turn++
        for ((stock, payment) in offers) {
            val stats = stockPriceStatistics.getOrPut(stock.type) { DoubleSummaryStatistics() }
            for (i in 1..stock.amount) {
                stats.accept(payment.toDouble() / stock.amount)
            }
        }
    }
    private fun getSellPrice(type: Int): Double {
        var price = getPrice(type)
        if (price < 1000) {
            price += (1000 - price) * (MAX_TURNS - turn) / MAX_TURNS
        }
        return if (type == secretStockType) Math.max(secretStockValue.toDouble(), price) else price
    }
    private fun getPrice(type: Int): Double {
        return stockPriceStatistics[type]?.average ?: DEFAULT_STOCK_VALUE.toDouble()
    }
    private fun profitOfOffer(offer: Offer): Double {
        return getBuyPrice(offer.offer.type) * offer.offer.amount - offer.payment
    }
    private fun getBuyPrice(type: Int): Double {
        var price = getPrice(type)
        price = price * turn / MAX_TURNS
        return if (type == secretStockType) Math.min(secretStockValue.toDouble(), price) else Math.min(price, MAX_STOCK_VALUE.toDouble())
    }
}
```
[Answer]
# UncleScrooge, Java
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class UncleScrooge extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        Offer offer;
        try {
            offer = offers.get(0);
        } catch (Exception ex) {
            return null;
        }
        if (offer.getPayment() < 100)
            return offer;
        else
            return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if (this.getRandom().nextDouble() < 0.6)
            return new Offer(currentStock.get(secretStockType).setAmount(1), Integer.MAX_VALUE);
        else
            return null;
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) { }
}
```
Sell stock at a really high price, and only buy if the price is less than 100.
[Answer]
# Profiteer, Java
Profiteer is in it for the money, and he's always counting coins. He makes a conservative estimate of how much money he's got. He'll then buy the secret stock, if it's less than the value, or buy cheap stock. He also remembers how much he's paid for everything, and always makes offers above the stock price. Furthermore, he'll make higher offers if he has less money.
*Note: I think I've done this correctly, but if @NathanMerrill wouldn't mind skimming my code for bugs, that'd be great*
```
import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Profiteer extends Player {
    private List<StockInfo> onMarket;
    private List<StockInfo> stocks;
    private int money;
    private boolean first = true;
    @Override
    public Offer acceptOffer(List<Offer> offers) {
        Offer finalOffer;
        Optional<Offer> offer = offers.stream().filter(o -> o.getOffer().getType() == this.secretStockType && o.getPayment() < this.secretStockValue * o.getOffer().getAmount()).sorted((a, b) -> Integer.compare((this.secretStockValue * a.getOffer().getAmount()) - b.getPayment(), (this.secretStockValue * b.getOffer().getAmount()) - b.getPayment())).findFirst();
        if (offer.isPresent()) {
            finalOffer = offer.get();
        } else {
            finalOffer = offers.stream().sorted((a, b) -> Integer.compare(a.getPayment(), b.getPayment())).findFirst().orElse(null);
        }
        if (finalOffer == null || this.money <= finalOffer.getPayment()) {
            return null;
        } else {
            this.stocks.add(new StockInfo(finalOffer.getOffer(), finalOffer.getPayment()));
            this.refreshMoney();
            return finalOffer;
        }
    }
    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if (this.first) {
            this.init(stocks);
        } else {
            this.refreshMarketList(stocks);
        }
        Optional<StockInfo> least = this.stocks.stream().sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();
        Optional<StockInfo> secret = this.stocks.stream().filter(stockInfo -> stockInfo.getStock().getType() == this.secretStockType).sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();
        StockInfo finalOffer;
        int price;
        if (secret.isPresent()) {
            finalOffer = secret.get();
        } else if (least.isPresent()) {
            finalOffer = least.get();
        } else {
            return null;
        }
        this.onMarket.add(finalOffer);
        this.stocks.remove(finalOffer);
        price = this.calculatePrice(finalOffer.boughtPrice);
        return new Offer(new Stock(finalOffer.getStock().getType(), finalOffer.getStock().getAmount()), price);
    }
    private int calculatePrice(int boughtPrice) {
        return (int) (boughtPrice + ((boughtPrice / (double) this.money) * this.money)) + 1;
    }
    private void refreshMarketList(List<Stock> stocks) {
        this.stocks.addAll(this.onMarket.stream().filter(stockInfo -> stocks.contains(stockInfo.getStock())).collect(Collectors.toList()));
        this.onMarket.clear();
    }
    private void refreshMoney() {
        this.money = this.stocks.stream().mapToInt(info -> this.secretStockType == info.getStock().getType() ? this.secretStockValue : 5).reduce((a, b) -> a + b).orElseGet(() -> 0) - this.stocks.stream().mapToInt(StockInfo::getBoughtPrice).reduce((a, b) -> a + b).orElseGet(() -> 0);
    }
    private void init(List<Stock> stocks) {
        this.stocks = stocks.stream().map(stock -> new StockInfo(stock, 0)).collect(Collectors.toList());
        this.onMarket = new ArrayList<>();
        this.money = 0;
        this.first = false;
        this.refreshMoney();
    }
    private static class StockInfo {
        private Stock stock;
        private int boughtPrice;
        public StockInfo(Stock stock, int boughtPrice) {
            this.stock = stock;
            this.boughtPrice = boughtPrice;
        }
        public Stock getStock() {
            return this.stock;
        }
        public int getBoughtPrice() {
            return this.boughtPrice;
        }
    }
}
```
[Answer]
# MaxBot, Java
This bot tries to make the most profit out of each transaction. While selling, puts the price of an unknown stock at $300, when buying $250.
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class MaxBot extends Player {
    int toSell;
    int sellPrice;
    
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
        toSell = stockType;
        sellPrice = (value + 1000)/2;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer max = null;
        int maxDif = 0;
        for(Offer o: offers){
            int price = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int val = price * o.getOffer().getAmount();
            int dif = val - o.getPayment();
            if(maxDif < dif){
                max = o;
                maxDif = dif;
            }
        }
        return max;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if(toSell == -1){
            return null;
        }
        int sum = 0;
        for (Stock s: currentStock){
            if(s.getType() == toSell){
                sum += s.getAmount;
            }
        }
        int n = sum - sum/2;
        return new Offer(new Stock(toSell, n), n * sellPrice);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
        int highStock = -1;
        int highPrice = 0;
        int markup = 0;
        for(Offer o: offers){
            int trueVal = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int marketVal = o.getPayment()/o.getOffer().getAmount();
            if(marketVal - trueVal > markup){
                highStock = o.getOffer().getType();
                highPrice = marketVal;
                markup = marketVal - trueVal;
            }
        }
        toSell = highStock;
    }
}
```
[Answer]
# BlackMarket, Java
Not much to say about this one, seeing as these transactions will be... off the charts, you might say.
```
import java.util.List;
import com.ppcg.stockexchange.*;
public class BlackMarket extends Player {
    private boolean approvedBySEC = false;
    private int ammoLeft = 30;
    public String taxView = "We want higher tax rates";
    public String excuse = "I never saw that in my life";
    public void secretValue(int drugType, int warrantForMyArrest) {
        super.secretValue(drugType, warrantForMyArrest);
        if (warrantForMyArrest != 0 || drugType == 420) {
            ammoLeft += 10;
        }
    }
    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.approvedBySEC || offer.getPayment() < 9)
                return offer;
        }
        return null;
    }
    
    
    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1),420);
    }
}
```
[Answer]
## NotQuiteABanksBestFriend, Python 3
Command.txt:
```
python3 NotQuiteABanksBestFriend.py
```
```
NotQuiteABanksBestFriend.py
import random
from functools import total_ordering
from io import StringIO
log = StringIO()
log.write("\n\n~~~NEW GAME~~~\n\n")
LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'
JAVA_MAX_INT = 2147483647
@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))
    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)
    def __str__(self):
        return "T%sx%s"%(self.type, self.amount)
    def __repr__(self):
        return str(self.type)+STOCK_DELIMITER+str(int(self.amount))
    def __bool__(self):
        return bool(self.amount)
    def __eq__(self, other):
        return self.amount == other.amount
    def __lt__(self, other):
        return self.amount < other.amount
    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)
    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)
    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)
    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)
    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)
class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            stock, price = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(stock), int(price.strip()))
    def __init__(self, stock: Stock, price: int):
        self.stock = stock
        self.price = price
        try:
            self.price_per_unit = self.price/self.stock.amount
        except ZeroDivisionError:
            self.price_per_unit = float('inf')
    def __str__(self):
        return "%s$%s"%(self.stock, self.price)
    def __repr__(self):
        return repr(self.stock)+OFFER_DELIMITER+str(int(self.price))
def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)
    log.write("Hidden StockID: %s\nHidden Price: %s\n"%(hidden_stock, hidden_price))
def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(repr(output))
    else:
        print()
def read_seed(seed: str):
    random.seed(int(seed))
def start():
    while True:
        process_input()
hidden_stock = None
hidden_price = None
def filter_offers(offer):
    if offer.stock.amount == 0:
        return False
    if offer.price_per_unit > 1000:
        return False
    return True
def certain_profit(offer):
    stock = offer.stock
    if stock.type == hidden_stock and offer.price_per_unit < hidden_price:
        log.write("Offer, %s is certainly profitable.\n"%offer)
        return True
    return False
def make_offer(current_stock: str):
    current_stock = list(map(Stock.parse, current_stock.split(LIST_DELIMITER)))
    own_stock = [stock for stock in current_stock if stock.type == hidden_stock]
    if own_stock and own_stock[0]:
        own_stock = own_stock[0]
        amount_sold = min(random.randrange(1,50), own_stock.amount)
        price = hidden_price+random.randrange(10,50)
        return Offer(Stock(hidden_stock, amount_sold), price*amount_sold)
    sell_stock = random.choice(current_stock)
    amount_sold = min(random.randrange(1,50), sell_stock.amount)
    price = random.randrange(1000, JAVA_MAX_INT//(amount_sold or 1))
    return Offer(Stock(sell_stock.type, amount_sold), price*(amount_sold or 1))
def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    filtered_offers = list(filter(filter_offers, available_offers))
    profitable = list(filter(certain_profit, filtered_offers))
    rtn_list = filtered_offers
    if profitable:
        log.write("Profitable: %s\n"%profitable)
        rtn_list = profitable
    if not rtn_list:
        return None
    accepted_offer = min(rtn_list, key=lambda offer: offer.price_per_unit)
    log.write("Bidded for %s\n"%accepted_offer)
    return accepted_offer
def accepted_offers(offers: str):
    pass
if __name__ == "__main__":
    try:
        start()
    finally:
        log.close()
```
Always tries to sell hidden stock for more than it's worth.
]