Фондова біржа стеків - V3


42

ПОВІДОМЛЕННЯ: Ця проблема зараз закрита: я більше не оновлюватимуть таблицю лідерів і не зміню прийняту відповідь. Однак ви можете запустити контролер і оновити таблицю лідерів самостійно, якщо бажаєте.

Приєднуйтесь до чату!

Вступ

Доброго вечора, торговці! Ви всі торговці компанії для гольфу PPCG. Ваше завдання - заробити якомога більше грошей.

Виклик

Напишіть програму, яка купує та продає акції на фондовій біржі стеків з метою заробити якомога більше грошей.

Ігровий процес

Усі гравці розпочнуть з 5 акцій та 100 доларів у своєму банку. Гра завжди починається з ціни акцій 10 доларів.

Кожна гра матиме 1000 раундів, де перший раунд є круглим 1. У кожному раунді вашій програмі будуть представлені чотири аргументи як вхідні дані: поточна ціна акцій, кількість акцій, якими ви володієте, кількість грошей, якими ви володієте, та кругле число (1-індексований).

Наприклад, якщо в моїй програмі є test1.pyціна акцій 100, кількість акцій, якими я володію 3, кількість грошей у мене є 1200, і кругле число - 576моя програма буде працювати так:

python test1.py 100 3 1200 576

У турі ціна акцій, надана кожному гравцеві, буде однаковою. Це не змінюється до кінця раунду.

У відповідь гравець повинен надрукувати свою команду. Є два варіанти:

  • Купуйте акції: Ця команда задається тим, bnде nє кількість акцій, які ви бажаєте придбати. Наприклад, якщо ви хочете придбати 100 акцій, ви отримаєте:
b100

Купуючи акції, вам дозволяється овердрафт до 1000 доларів. Якщо ви спробуєте придбати достатню кількість акцій, що перевищують цей овердрафт (баланс вашого банку нижче ніж -1000 доларів), вас визнають банкрутами. Це означає, що ви втратите всі свої акції, а баланс буде встановлено на рівні 50 доларів.

Ваша команда не вплине на ціну акцій, якщо ви збанкрутуєте.

(Якщо ваш баланс становить -1000 доларів, ви не є банкрутом. Однак якщо ваш баланс становить -1001, ви банкрутуєте)

  • Продайте акції: Ця команда задається як snде nкількість акцій, які ви хочете продати. Наприклад, якщо ви хочете продати 100 акцій, ви отримаєте:
s100

Ви не можете продавати більше акцій, ніж у вас є. Якщо ви спробуєте це зробити, ваш запит буде відхилено, і ви пропустите раунд.

Якщо ви хочете пропустити раунд і нічого не робити, виведіть b0або s0.

У вашому запиті буде відхилено, якщо ви спробуєте придбати або продати негативну кількість акцій та / або нецілу кількість акцій.

Після 5 раундів, в кінці кожного раунду всім гравцям буде виплачено дивіденд, вартість якого становить 5% від середньої середньої ціни акцій за останні 5 раундів.

Як це працює?

Спочатку ціна акцій складе 10 доларів. В кінці кожного раунду він буде перерахований за формулою:

New Share Price=Old Share Price+(Number of shares boughtNumber of shares sold)

Ціна акцій буде обмежена, щоб вона ніколи не опускалася нижче 1 долара.

Щоб запобігти надмірно швидким змінам, зміна ціни акцій обмежена максимумом .±$200

Правила

  • У вашій програмі повинно бути назва


  • У вашій програмі дозволений єдиний текстовий файл для зберігання даних. Він повинен зберігатися в тій же папці, що і ваша програма


  • Включіть у свою інформацію відповіді про те, як запустити свою програму


  • Цей KotH відкритий для всіх мов програмування, які є безкоштовними у використанні та можуть працювати в Windows 10


  • Ваш рахунок базується виключно на вмісті балансу. Будь-які гроші, зафіксовані в акціях, не зараховуються


  • Ви можете будь-коли редагувати свою програму. Перед кожною грою останній код буде збережений та складений


  • Не слід писати код, який конкретно націлений на іншого бота.

Контролер

Контролер написаний на Python і його можна знайти тут: https://gist.github.com/beta-decay/a6abe40fc9f4ff6cac443395377ec31f

Наприкінці він надрукує таблицю лідерів та відобразить графік того, як змінювалася ціна акцій протягом гри.

Наприклад, коли грали два випадкових бота

Перемога

Гравець з найбільшою сумою грошей у своєму балансі в кінці останньої гри виграє.

Таблиця лідерів

Гра 4: 16:14 08.08.2018

Name                                Balance

Experienced Greedy Idiot            $14802860126910608746226775271608441476740220190868405578697473058787503167301288688412912141064764060957801420415934984247914753474481204843420999117641289792179203440895025689047561483400211597324662824868794009792985857917296068788434607950379253177065699908166901854516163240207641611196996217004494096517064741782361827125867827455285639964058498121173062045074772914323311612234964464095317202678432969866099864014974786854889944224928268964434751475446606732939913688961295787813863551384458839364617299883106342420461998689419913505735314365685264187374513996061826694192786379011458348988554845036604940421113739997490412464158065355335378462589602228039730
Equalizer                           $763185511031294813246284506179317396432985772155750823910419030867990447973211564091988995290789610193513321528772412563772470011147066425321453744308521967943712734185479563642323459564466177543928912648398244481744861744565800383179966018254551412512770699653538211331184147038781605464336206279313836606330
Percentage Trader                   $448397954167281544772103458977846133762031629256561243713673243996259286459758487106045850187688160858986472490834559645508673466589151486119551222357206708156491069820990603783876340193236064700332082781080188011584263709364962735827741094223755467455209136453381715027369221484319039100339776026752813930
OYAIB                               $8935960891618546760585096898089377896156886097652629690033599419878768424984255852521421137695754769495085398921618469764914237729576710889307470954692315601571866328742408488796145771039574397444873926883379666840494456194839899502761180282430561362538663182006432392949099112239702124912922930
Chimps on a Typewriter              $176504338999287847159247017725770908273849738720252130115528568718490320252556133502528055177870
Greedy B*****d                      $17689013777381240
Illiterate Dividend Investor        $2367418699671980
Lucky Number 6                      $4382725536910
Lone Accountant                     $90954970320
Buy/Reinvest                        $127330
Technical Analysis Robot            $126930
Dollar Cost Averager                $106130
Fibonacci                           $69930
Novice Broker                       $28130
Buy Low                             $6130
Naive Statistician                  $6130
Fallacious Gambler                  $6130
Passive Trader                      $4980
Half More or Nothing                $4920
Monkeys on a Typewriter             $66

Перегляньте графіки кожного учасника


Пов’язаний, але критерій ігрового процесу та виграшів дуже відрізняються від цієї проблеми.


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
Денніс

Для мене формула відображається як [Помилка обробки математики] червоним кольором. Це те ж саме і для інших? Якщо так, можливо, це питання з питанням.
Капітан Людина

2
Можливо, варто буде усереднювати результати, скажімо, 10-100 ігор, щоб зменшити вплив удачі. А може, це занадто сильно змінить виклик.
mbrig

1
Чи можливо, щоб оцінки були log2 / log10? Це значно полегшило б порівняння балів. (Я переглядаю свій телефон, і експоненти зникли з екрану)

1
Я думаю, що навіть 10-100 - це занадто мало, але мені подобається проводити багато ігор. Щоб зробити це можливим, вам потрібно буде змінити формат виклику, який зараз виходить за рамки.
Натан Меррілл

Відповіді:


11

Досвідчений жадібний ідіот

PHP, протестований на PHP> = 7, також повинен працювати на попередніх.

<?php

class StickExchange
{
    private $dbFile;
    private $sharePrice;
    private $shares;
    private $balance;
    private $overdraft;

    public function __construct($sharePrice, $shares, $balance, $round)
    {
        $this->dbFile = __FILE__ . '.txt';
        $this->sharePrice = gmp_init($sharePrice);
        $this->shares = gmp_init($shares);
        $this->balance = gmp_init($this->parseScientificNotationToInt($balance));
        $this->overdraft = gmp_init(1000);

        $action = 'b';

        if ($round == 1) {
            $this->buy();
        } elseif ($round == 1000) {
            $this->sell();
        } else {
            $content = $this->getDbContent();
            $lastPrice = gmp_init($content['price']);
            $secondLastPrice = gmp_init($content['last_price']);
            $lastAction = $content['action'];

            $shareAndLastCmp = gmp_cmp($this->sharePrice, $lastPrice);
            $lastAndSecondLastCmp = gmp_cmp($lastPrice, $secondLastPrice);

            if ($shareAndLastCmp > 0 && $lastAndSecondLastCmp > 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->buy();
                }
            } elseif ($shareAndLastCmp < 0 && $lastAndSecondLastCmp < 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->skip();
                }
            } elseif ($shareAndLastCmp > 0) {
                $this->sell();
                $action = 's';
            } elseif ($shareAndLastCmp < 0) {
                $this->buy();
            } else {
                $this->skip();
            }
        }

        $this->setDbContent([
            'action' => $action,
            'price' => gmp_strval($this->sharePrice),
            'last_price' => isset($lastPrice) ? gmp_strval($lastPrice) : '0',
        ]);
    }

    private function parseScientificNotationToInt($number)
    {
        if (strpos($number, 'e+') !== false) {
            $sParts = explode('e', $number);
            $parts = explode('.', $sParts[0]);
            $exp = (int)$sParts[1];

            if (count($parts) > 1) {
                $number = $parts[0] . $parts[1];
                $exp -= strlen($parts[1]);
            } else {
                $number = $parts[0];
            }

            $number = gmp_init($number);
            $pow = gmp_pow(gmp_init(10), $exp);
            return gmp_strval(gmp_mul($number, $pow));
        } elseif (strpos($number, 'e-') !== false) {
            return sprintf('%d', $number);
        } else {
            $parts = explode('.', $number);
            return $parts[0];
        }
    }

    private function getDbContent()
    {
        return unserialize(file_get_contents($this->dbFile));
    }

    private function setDbContent($content)
    {
        file_put_contents($this->dbFile, serialize($content));
    }

    private function buy()
    {
        $realBalance = gmp_add($this->balance, $this->overdraft);
        $sharesToBuy = gmp_div($realBalance, $this->sharePrice);
        $this->stdout('b' . gmp_strval($sharesToBuy));
    }

    private function sell()
    {
        $this->stdout('s' . gmp_strval($this->shares));
    }

    private function skip()
    {
        $this->stdout('b0');
    }

    private function stdout($string)
    {
        $stdout = fopen('php://stdout', 'w');
        fputs($stdout, $string);
        fclose($stdout);
    }
}

new StickExchange($argv[1], $argv[2], $argv[3], $argv[4]);

Оновлена ​​версія «Жадібного ідіота» з переструктурованою поведінкою та виправленнями помилок, пов’язаних із роботою з величезною кількістю.

Примітки:

  • Збережіть у файлі та запустіть його так: php C:\path\path\stack_exchange.php 10 5 100 1
  • Цей скрипт створює текстовий файл з такою ж назвою, що і файл сценарію, і .txtдодається до кінця. Тому, будь ласка, запустіть із користувачем відповідний дозвіл на запис сценарію.
  • Простий спосіб встановлення PHP 7.2 на windows: http://www.dorusomcutean.com/how-to-install-php-7-2-on-windows/
  • Для роботи з надзвичайно величезними числами мені довелося використовувати GMP , тому ці два рядки php.iniслід не коментувати (напівкрапка на початку рядка повинна бути видалена, якщо її ще немає):
    • ; extension_dir = "ext"
    • ;extension=gmp

1
Нічого, дякую за це посилання! Мені було цікаво: D
бета-розпад

1
@BetaDecay: Немає проблем, btw вам потрібно лише пройти до кроку 2 (встановлений тест PHP), де ви перевіряєте встановлення php -v. Решта для цього не потрібні. Я вірю, що у вас виникнуть багато проблем зі створенням такої кількості різних мов для цього завдання! Я б ніколи не наважувався зробити щось подібне: D
Ніч2,

@BetaDecay чи не було б простіше просто встановити TryItOnline як контейнер Docker?
NieDzejkob

@NieDzejkob Можливо, але, ймовірно, стане в нагоді встановлення цих мов
Beta Decay

1
З повагою, ви послідовно перемагаєте кожного іншого учасника!
Бета-розпад

19

Шимпанзе на машинці

import random
from sys import argv

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])

x = random.random()
if x < 0.5:
    max_buy = balance / share_price
    buy_count = int(max_buy * random.random())
    print('b' + str(buy_count))
else:
    sell_count = int(share_count * random.random())
    print('s' + str(sell_count))

Шимпанзе розумніші за мавп, вони не купуватимуть акції, які не можуть собі дозволити, або продають акції, яких у них немає.

Все ще досить випадковий, інакше.

Запустити з python3, але також (?) Також працювати з python2


1
Вони можуть бути розумнішими, але чи вони щасливіші?
Woohoojin

У всіх моїх тестах цей вийшов на перше місце, тому так
Skidsdev

26
Мені надзвичайно цікаво, як це виграло перший тур більш ніж на 20 порядків
mbrig

Мені подобається ставити це до мистецтва простоти. Всі інші надмірно розробляють своїх ботів.
Skidsdev

1
Це отримало стільки кохання помилково: P
Ніч2

10

OYAIB

from sys import argv

share_price = float(argv[1])
shares      = int(argv[2])
cash        = float(argv[3])
cur_round   = int(argv[4])
tot_rounds  = 1000.0

investments = shares * share_price
total_assets = investments + cash

target_cash = round(cur_round / tot_rounds * total_assets)

if target_cash > cash:
  shares_to_sell = min(shares, round((target_cash - cash) / share_price))
  print('s%d' % shares_to_sell)
else:
  shares_to_buy = round((cash - target_cash) / share_price)
  print('b%d' % shares_to_buy)

Дотримуючись старої приказки "володій своїм віком у облігаціях", ця програма намагається зробити те саме. Таким чином, ми не піддаємося волатильності ринку в кінці гри.

Редагувати: дивлячись на контролер, це показує, що ми можемо купувати / продавати лише повні акції, але можемо мати частковий баланс рахунку.


Ласкаво просимо до PPCG!
Бета-розпад

Дякую! Перший раз розміщую повідомлення, тож дайте мені знати, якщо щось не на місці
just_browsing

Ви можете додати додаткову умову, що в останньому турі ви продаєте всі свої акції (як investmentsце не враховується у вашому рахунку).
Рікінг

2
Це краса OYAIB, вона робить це автоматично. Target_cash - це відсоток від загального_набору, залежно від того, в якій точці "життя" знаходиться. Наприкінці життя target_cash становить 100% від загальної кількості активів, тому він продаватиме будь-які акції, якими володіє.
just_browsing

9

Одинокий бухгалтер

buy-sell.py:

from sys import argv

Price = int(argv[1])
Shares = int(argv[2])
Balance = float(argv[3])
Round = int(argv[4])

if Round % 2 == 0: print('s' + str(Shares))
if Round % 2 == 1: print('b' + str(int((Balance + 1000) / Price)))

Нічого не зберігається в buy-sell.txt.

У непарних раундах він купує стільки акцій, скільки може. У рівних раундах він продає всі свої акції.

Метою є спочатку підняти ціну акцій, купивши якомога більше акцій, а потім продати ці акції, щоб отримати більше грошей. Це працює, тому що фінальний раунд є рівним (круглий 1000).

Навіть незважаючи на те, що ціна акцій залишатиметься однаковою ( 5) після кожної пари раундів (якщо вважати, що бот один, отже, Одинокий бухгалтер ), баланс бота збільшується, оскільки ціна продажу вища, ніж ціна покупки, і більший баланс призводить до можливість придбання більшої кількості акцій. Це порочний цикл, але хорошим способом (для мене).

Основна вразливість полягає в тому, що злі боти грають поряд, продаючи, щоб знизити ціну акцій (не впевнений, чи добре це для них). У цьому випадку бот може залишитися із залишком -890 доларів, за умови наявності достатньої кількості злих ботів. Цей бухгалтер дуже хоче їх спокою. ;-)


1 на 1 Я не впевнений, чи можливо це побиття; це непросто, навіть якщо ти повністю розумієш бухгалтера LA і намагаєшся протидіяти йому. У масовій грі, де ви перелічилися, ви могли бути перевиконані.
Якк

@Yakk Інші вже побили це в моїх тестових запусках.
Ерік Аутгольфер

1 на 1? Я спантеличений; Я не в змозі розібратися, як противником ви можете розбагатіти, щоб перевернути цінові коливання або навіть запобігти зростанню з часом, не спалюючи купу ресурсів (тим часом, ЛА не приносить жертви, тому стає важче Стоп). Чи можете ви зв’язатись із геймплеєм, що Лос-Анджелес програв один на один?
Якк

@Yakk Я ще не тестував його один на один. Крім того, є чат для нас, щоб обговорити це, якщо ви хочете.
Erik the Outgolfer

Чи було б більш надійним нічого не робити, якщо у вас є акції і ціна нижча, ніж попередній раунд, або у вас є гроші, а ціна вища? Це захищатиме від синхронізації з іншими, подібними ботами. Крім того, я не бачу, як це можна було бити один на один.
JollyJoker

5

Пасивний торговець

from sys import argv

share_price = int(argv[1])
balance = float(argv[3])
round_num = int(argv[4])

if round_num == 1:
    print('b%s' % str(int(balance / share_price)))
else:
    print('b0')

Цей хлопець не є великим на всю цю "акцію", але він чув, що якщо він зараз просто витратить трохи грошей, він з часом отримає невеликі шматочки грошей, які збільшать більше, ніж витратили.

Він купить достатню кількість акцій, щоб перейти на $ 0 (жодного овердрафту для цього хлопця, він не є гарною, щоб заборгувати за невеликий прибуток), а потім сидіти, дозволяючи дивідендам нарощувати

Запустити з python3, але також (?) Також працювати з python2.


1
Я думаю, ви повинні продати свої 15 акцій принаймні в останньому раунді.
Калдо

14
@Kaldo nah, він давно забув про те, коли одного разу він купував акції до цього моменту
Skidsdev

5

Процентний трейдер Python3

(можливо, працює в python2)

import sys
args=sys.argv

price=int(args[1])
held=int(args[2])
money=int(args[3])
roundNum=int(args[4])
prevPrice=0

if roundNum==1:
    print("b"+str((money+1000)//price))
else:
    if roundNum==1000:
        print("s"+str(held))
    else:
        with open("percentageTrader.dat","r") as f:
            prevPrice=int(f.read())
        if(price>prevPrice):
            toSell=int(held*int(1000000*(price-prevPrice))/(price))//1000000
            print("s"+str(toSell))
        if(price<prevPrice):
            toBuy=int(((money+1000)//price)*int(1000000*(prevPrice-price))//(prevPrice))//1000000
            print("b"+str(toBuy))
        if(price==prevPrice):
            print("b0")

with open("percentageTrader.dat","w") as f:
    f.write(str(price))

Інструкції з бігу

  • Зберегти як filename.py
  • Виконати з python filename.py ціна #shares баланс круглий #

Як це працює

  • Перший раунд бот купує стільки акцій, скільки може собі дозволити.
  • Якщо ціна зростає, бот продає відсоток акцій, рівний відсотковому збільшенню ціни (обчисленому з нової вартості)
  • Якщо ціна знижується, бот купує відсоток від максимальних акцій, які він міг би придбати, рівних відсотковому зменшенню ціни (обчисленому з попереднього значення)
  • Продає все в 1000 раунді

Зміни повинні сподіватися, щоб усунути проблеми, викликані поділом з плаваючою комою


4

Наївний статистик

Створений для Python 3, може працювати в Python 2

from sys import argv
from math import floor

# Save an entry to the stock history
def save_history(price):
    with open('stockhistory.txt', 'a') as f:
        f.write(str(price) + '\n')

# Load the stock history
def load_history():
    with open('stockhistory.txt', 'r') as f:
        return [float(line.strip()) for line in f]

# Calculate average price rise/fall streak length
def average_streak(history, condition):
    streaks = []
    current_streak = 0
    last_price = history[0]
    for price in history[1:]:
        if condition(last_price, price):
            current_streak += 1
        elif current_streak:
            streaks += [current_streak]
            current_streak = 0
        last_price = price
    if current_streak:
        streaks += [current_streak]
    return sum(streaks) / len(streaks) if streaks else None

# Calculate the current streak length
def current_streak(history, condition):
    streak = 0
    while streak < len(history) - 1 and condition(history[-streak - 2], history[-streak - 1]):
        streak += 1
    return streak

def run(share_price, share_count, balance, round_number):
    save_history(share_price)

    # Sell all shares if it is the last round
    if round_number == 1000:
        print('s' + str(int(share_count)))
        return

    # Buy as many shares as possible if the price is down to one, as there's
    # nothing to lose
    if share_price == 1:
        buy_count = int(balance + 1000)
        print('b' + str(buy_count))
        return

    history = load_history()

    # Calculate the average and current rise/fall streaks
    average_rise = average_streak(history, lambda a, b: a <= b)
    current_rise = current_streak(history, lambda a, b: a <= b)
    average_fall = average_streak(history, lambda a, b: a >= b)
    current_fall = current_streak(history, lambda a, b: a >= b)

    # Do nothing if there's no analyzed data
    if not average_fall or not average_rise:
        print('b0')
        return

    # Buy shares if the current rise streak is as long as or longer than average
    if current_rise > current_fall and current_rise >= average_rise:
        buy_count = (balance + 1000) / share_price
        print('b' + str(int(buy_count)))
        return

    # Sell shares if the current fall streak is as long as or longer than average
    if current_fall > current_rise and current_fall >= average_fall:
        print('s' + str(int(share_count)))
        return

    # Otherwise, do nothing    
    print('b0')

run(*map(float, argv[1:]))

Це наївний статистик, який намагається передбачити ціни на акції, лише купуючи / продаючи, якщо ціна зросла / впала довше, ніж зазвичай, а також купуючи акції, якщо ціна знизилася до однієї, і продаючи всі акції в останньому раунді.


4

Середня вартість долара

(тестовано на Python 3.7)

Перша публікація в кодегольфі, тому скажіть мені, чи зробив я щось не так.

Основна ідея - купувати одну акцію на кожен раунд, якщо це можливо, та продавати всі акції наприкінці.

from sys import argv
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])

if round < 1000:
    if balance > share_price-1000:
        print("b1")
    else:
        print("b0")
else:
    print("s" + str(share_count))

4

Еквалайзер

from sys import argv
p, n, b, r = map(int, argv[1:])
c = p*n
print "bs"[(c+b)/2>b] + str(int(abs(((c-b)/2)/p))) if r < 999.5 else "s" + str(int(n))

Розподіляє свої фінансові ресурси порівну між готівкою та запасами на кожному раунді, крім останнього. Я вважаю, що ця стратегія є математично обґрунтованим способом заробити хоч якісь гроші, але я можу бути доведеною неправильною.

Можуть бути чи ні помилки, яких я не спіймав. Також гольф дещо.


У вашій програмі виникають труднощі з великою кількістю залучених тут, тому я б запропонував змінити рядок p, n, b, r = map(float, argv[1:])наp, n, b, r = map(int, argv[1:])
Beta Decay

@BetaDecay виконано
Айдан Ф. Пірс

4

Мавпи на машинці

import random

cmd = ['b', 's'][int(random.random() * 2)]
num = str(int(random.random() * 1000000))
print("%s%s" % (cmd, num))

Це купа мавп на машинках. Випадково продає або купує акції X, де:
0 <= X <= 1,000,000

Запустити з python3, але також (?) Також працювати з python2


4
Чому б не використовувати cmd=random.choose(['b','s'])і num = str(random.randint(0, 1000000))?
Бета-розпад

1
Тому що я лінивий
Skidsdev

1
чому б не простоimport lazy
Woohoojin

все це можна було б звести до from random import randint, choice;print("{}{}".format(choice(["b", "s"]), randint(0, 1e6)));-P
Аарон F

6
так, але це не проблема для гольфу
Skidsdev

4

Купуйте низьку

(Python 2 або 3)

import random

def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return

    # If the price is low enough, buy everything we can.
    if price <= 20 + round_ * 60:
        print('b' + str((balance + 1000) // price))
        return

    # If we have no shares, wait for the price to drop.
    if shares == 0:
        print('b0')
        return

    # Sometimes sell shares so we can buy if the price gets low again.
    if random.random() < 0.4:
        print('s1')
        return

    # Otherwise, just wait for a better price.
    print('b0')


if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

3

Помилковий азартний гравець

(Python 2 або 3)

import random

def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return

    # For the first round, just watch.
    if round_ == 1:
        with open('fg.txt', 'w') as f:
            f.write('1 0 10')
        print('b0')
        return

    # Get the state.
    with open('fg.txt') as f:
        direction, streak, previous = map(int, f.read().strip().split())
    change = price - previous

    # If the market isn't moving, wait for it to get hot again.
    if change == 0:
        print('b0')
        return

    # Keep track of the market direction.
    if (change > 0) == (direction > 0):
        streak += 1
    else:
        streak = 0
        direction *= -1

    # If the market's been going one way for too long, it has to switch, right?
    if streak > 5:
        if direction > 0:
            print('s' + str(shares // 2))
        else:
            print('b' + str((balance + 1000) // price // 2))
    # Otherwise, the market's too volatile.
    else:
        print('b0')

    # Save the state.
    with open('fg.txt', 'w') as f:
        f.write('%d %d %d' % (direction, streak, price))


if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

3

Фермер (Dyalog) APL

r←apl_stock_farmer args
 round←¯1↑args
 :If 1=round
     (buyPrice sellPrice)←10 0
     bought←1
     (currPrice shares balance)←3↑args
     r←'b10'
 :ElseIf 1000=round
     r←'s',⍕shares
 :Else
     (currPrice shares balance)←3↑args
     :If (currPrice>buyPrice)∧bought
         bought←0
         sellPrice←currPrice
         r←'s',⍕shares
     :ElseIf (currPrice<sellPrice)∧~bought
         bought←1
         buyPrice←currPrice
         r←'b',⍕⌊(1000+balance)÷currPrice
     :Else
         r←'b0'
     :End
 :End

TradFn, який купує всі можливі акції в першому раунді, і продає лише тоді, коли поточна ціна акцій вища за ціну, за яку вони були куплені. Після продажу бот купуватиме лише ті акції, які дешевші за ціну, яку він продав останній рік.

Це тому, що бухгалтер фермера сказав йому, що саме так ви займаєтеся торгівлею акціями. "Купуйте низько, продайте високо" і все таке.

Відмова від відповідальності

Це моя перша спроба виклику KotH, і оскільки я в основному тут займаюся лише APL, я вирішив продовжувати це.

При цьому я не зовсім впевнений, чи вдасться це запустити поряд з іншими ботами, оскільки це Tradfn і його не можна подавати безпосередньо в оболонку CMD / Bash.

Отже, щоб запустити це в Bash, вам потрібна наступна команда:

$ echo apl_stock_farmer args | dyalog 'stock_exchange.dws' -script

Де:

apl_stock_farmer - це назва функції, яка знаходиться в першому рядку коду.

args- вектор аргументів, розділених простором (у першому раунді це було б 10 5 100 1).

dyalog - шлях до виконуваного файлу Dyalog

'stock_exchange.dws'- це ім'я (або шлях, якщо файл знаходиться не в одному каталозі, в якому відкрита оболонка) робочої області, яка містить функцію. Цей файл робочої області можна отримати, відкривши чисту робочу область, набравши )ed apl_stock_farmer, вставивши код вище, а потім виконавши команду a )save <path>. Я також можу надати цей файл робочої області, якщо це буде простіше.

-script це лише аргумент, який змушує dyalog виконувати даний код і друкувати в stdout, не відкриваючи фактично REPL.

На жаль, я не знайшов способу змусити його працювати з Windows CMD або Powershell, тому я запустив його за допомогою Git Bash. Я не впевнений, наскільки можливо поставити цього бота на змагання, але мені дуже подобається цей код, щоб не публікувати його.


Вибачте, у мене є лише незареєстрована версія програми Dyalog APL, тому я не впевнений, що це буде працювати як учасник змагань
бета-версія занепаду

@BetaDecay Я розумію, проблем там немає. Я також дізнався, що ви можете використовувати бібліотеку Pynapl для запуску цього коду. Деталі містяться в розділі "Доступ до APL з Python", зокрема "Визначення tradfn за допомогою Python", і це виглядає досить просто.
Дж. Салле

3

Неграмотний інвестор з дивідендів

import random
from sys import argv

price = float(argv[1])
shares = int(argv[2])
cash = float(argv[3])
round = int(argv[4])

# buy 1st round, sell last round
if round == 1:
    print('b' + str(int((cash + 1000) / price)))
elif round == 1000:
    print('s' + str(shares))

# round right before dividend: sell
elif round % 5 == 4:
    print('s' + str(shares))

# 1 round after dividend: buy
elif round % 5 == 0:
    print('b' + str(int((cash + 1000) / price)))

# 2 rounds after dividend: 50/50 sell/try to buy
elif round % 5 == 1:
    if random.random() < 0.5:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))

# 3 rounds after dividend: sell if own shares (didn't sell last round), else buy
elif round % 5 == 2:
    if shares > 0:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))

# otherwise, 4 rounds after dividend, buy
else:
    print('b' + str(int((cash + 1000) / price)))

Припускає, що після дивідендів люди мають більше грошових коштів, тому вони будуть частіше купувати. Продає прямо перед дивідендами, купує відразу після. Проходить один інший цикл продажу / купівлі в інших 3 раунди.


Дивлячись на контролера, дивіденди виплачуються кожен раунд після 4-го, а не кожен 5-й раунд. Ваш цикл все ще повинен працювати, але, ймовірно, не так, як ви задумали.
Веська

Якщо ви купуєте після того, як купуєте інші, ви закінчуєте купувати, коли дорожчі.
fəˈnɛtɪk

Дякую @Veskah. Довелося також додати деякі логіки r1 / r1000.
brian_t

@ fəˈnɛtɪk - якщо припустити, що люди купують раунд після дивідендів, ви теж хотіли б придбати цей раунд, а потім продати згодом, ні?
brian_t

Після дивідендів також немає раунду, оскільки ви отримуєте дивіденди кожен раунд після 4-го.
fəˈnɛtɪk

3

Купуйте / реінвестуйте якомога більше!

Подібно до мого середньостатистичного долара, який, на диво, досить середній, він купує кожен раунд стільки акцій, скільки доступних, і продає їх лише в останньому раунді.

from sys import argv

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])


if round < 1000:
    if balance > share_price-1000:
        buy_count = int((balance+1000)/share_price)
        print("b"+str(buy_count))
    else:
        print("b0")
else:
    print("s" + str(share_count))

Гей, у вас тут помилка з відступом. Ви мали на увазі відступити if balance > share_price-1000:блок чи ні?
Бета-розпад

Так. Моя незначна редакція, схоже, порушила моє форматування. Виправимо, як тільки я повернусь до ПК
Barbarian772

2

Новачок-брокер (але отримує основну думку)

se_stock_exchange.rb:

DATA_FILE = $0.sub /\.rb$/, ".data"
NUM_ROUNDS = 1000

share_price, num_shares, money, round = ARGV.map &:to_i

order = "s0"

if round == NUM_ROUNDS
  puts "s#{num_shares}"
  exit
end

if File.exists? DATA_FILE
  last_price, trend, bought_price = File.read(DATA_FILE).lines.map &:to_i
else
  last_price = 0
  trend = -1
  bought_price = 0
end

if (new_trend = share_price <=> last_price) != trend
  case trend
  when -1
    order = "b#{(money + 1000) / share_price}"
    bought_price = [bought_price, share_price].max
  when 1
    if share_price > bought_price
      order = "s#{num_shares}"
      bought_price = 0
    end
  end
  trend = new_trend
end

File.open(DATA_FILE, "w") { |f| f.puts share_price, trend, bought_price }

puts order

Чекає, поки ціна обернеться, потім купує / продає все. Я маю на увазі, саме так сказано в Денній торгівлі манекенами Примітка: це, мабуть, справжня книга, і це, мабуть, щось, хтось може отримати з неї .

Зберігає дані в se_stock_exchange.data. Виконати з ruby se_stock_exchange.rb ${SHARE_PRICE} ${SHARES} ${MONEY} ${ROUND}(замінивши відповідні значення).


Це мій перший удар у KotH, тому дайте мені знати, чи я все роблю неправильно.
iamnotmaynard


Я отримую цю помилку:se_stock_exchange.rb:24:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)
Erik the Outgolfer

4
@BetaDecay: Шкода, що прізвище автора не починається з "A".
3D1T0R

3
@NieDzejkob: Якби це було "A": "Енн А. Лог" є аналогом " Аналогу ".
3D1T0R

2

Половина більше або нічого

def run(price, shares, balance, cur_round):
    if cur_round==1000:
        print('s'+str(int(shares)))
        return

    if cur_round==1:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return

    if shares==0:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return

    with open('HalfMoreOrNothing.dat', 'r') as f:
        bought_price=int(f.read())
    if price>=bought_price*1.5:
        print('s'+str(int(shares)))
        return

    print('b0')

if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

Я рідко використовую Python, повідомте мене, якщо це десь створює помилку.

Стратегія полягає в тому, щоб чекати, поки ціна акцій буде щонайменше на 50% більшою, ніж ціна в момент їх оббивання, потім продати їх, а потім негайно придбати нові акції, щоб можна було чекати на підвищення нової ціни акцій.

Сподіваємось, люди шимпанзе не почнуть продавати акції наприкінці ... (здається, більшість ботів просто чекають потрібного моменту, що б це не було)


2

Фібоначчі

Я переписав це в Python 3, щоб полегшити все. Сподіваємось!

import math
from sys import argv

price = float(argv[1])
shares = int(argv[2])
balance = float(argv[3])
roundNum = int(argv[4])

fibonacci = [2,3,5,8,13,21,34,55,89,144,233,377,610,987]
if (roundNum == 1):
    buy = int((balance+1000)/price)
    print('b' + str(buy))
elif (roundNum in fibonacci) and roundNum % 2 == 1 and balance > 0:
    buy = int((balance/price)/2)
    print('b' + str(buy))
elif ((roundNum in fibonacci) and roundNum % 2 == 0) or roundNum % 100 == 0:
    if (roundNum == 1000):
        sell = shares
        print('s' + str(sell))
    else:
        sell = math.ceil(shares/2)
        print('s' + str(sell))
else:
    print('b0')

Він купує половину максимальної кількості акцій, доступної, коли раунд дорівнює непарному числу Фібоначчі, і продає половину наявних акцій, коли раунд дорівнює парному числу Фібоначчі, а також кожні 100 раундів. Продає всі акції в круглому 1000. Інакше це просто чекає. Купує акції лише тоді, коли баланс позитивний.


Гей, я отримую помилкуError in roundNum%%2 : non-numeric argument to binary operator Execution halted
бета-розпад

@BetaDecay Я оновив код, який може вирішити проблему. Дай мені знати.
Роберт С.

1

Жадібний Б ***** д

# Gready one...
from sys import argv

SMA_PERIOD = 5
LAST_BUY_DAY = 985
LAST_SELL_DAY = 993

# Save an entry to the stock history
def save_history(price):
    with open('db.txt', 'a') as f:
        f.write(str(price) + '\n')

# Load the stock history
def load_history():
    with open('db.txt', 'r') as f:
        return [float(line.strip()) for line in f]

def get_sma(d, n):
    l = d[-n:]
    return int(sum(l) / len(l))


def buy(price, account):
    if account + 1000 > 0:
        print 'b' + str(int((account + 1000) / price))
        return
    print 'b0'

def sell(holdings):
    print 's'+ str(int(holdings))


def run(price, holdings, account, day):

    save_history(price)
    d = load_history()

    if price <= get_sma(d, SMA_PERIOD) and day < LAST_BUY_DAY:
        return buy(price, account)

    if price > get_sma(d, SMA_PERIOD):
        return sell(holdings)

    if day >= LAST_SELL_DAY:
        return sell(holdings)

    # Otherwise, do nothing    
    print 'b0'


run(*map(float, argv[1:]))  

Він піде все, коли його дешево, і продасть все, як тільки ціна підніметься ...


Ваш код повсюдно. По-перше, ви повертаєте друковані висловлювання, але також sell()передаєте три аргументи, до яких береться лише одне
Beta Decay

Друкарські помилки з трьома аргументами, щоб продати () ... тепер, що ти хвилюєшся поверненням друкованих заяв?
Arek S

Тільки те, що вони непотрібні
бета-розпад

дехто стверджує, що вони допомагають у читанні
Arek S

ви не включили його до результатів через відбитки? afaik typo у продажу () визначення не буде припиняти його працювати ... Я це поправляю, до речі
Arek S

1

Технічний робот-аналіз

Я вивчаю економіку бізнесу, тому спробував реалізувати найпростіший метод аналізу фондового ринку (технічний аналіз). Згідно з теорією, ви просто повинні проаналізувати всі мінімуми графіка, щоб побачити, чи є тенденція (вгору та вниз). Під час тенденції зростання вам доведеться купувати, а під час тенденції до зниження ви повинні продавати.

Я не думаю, що цей метод спрацює надто добре, але спробуємо спробувати :)

import sys
from sys import argv

share_price = int(argv[1])
share_number = int(argv[2])
bank_account = float(argv[3])
round_number = int(argv[4])

max_buy_greedily = (1000 + bank_account) / share_price
minima = []

def log():
    f = open("log_technical_analysis.txt","a+")
    f.write("%d;" % share_price)

def analyze():
    f = open("log_technical_analysis.txt","r+")
    line = f.readline()
    values = line.split(";")
    values.pop()
    for i in range(len(values) - 1):
        if i > 0 and int(values[i-1]) > int(values[i]) and int(values[i+1]) > int(values[i]):
            minima.append(int(values[i]))
    if len(minima) >= 3 and minima[len(minima) - 1] > minima[len(minima) - 2] and minima[len(minima) - 2] > minima[len(minima) - 3]:
        print('b' + str(int(max_buy_greedily)))
    elif len(minima) >= 3 and minima[len(minima) - 1] < minima[len(minima) - 2] and minima[len(minima) - 2] < minima[len(minima) - 3]:
        print('s' + str(share_number))
    else:
        print('b0')

if round_number >= 994:
    print('s' + str(share_number))
    sys.exit(0)

if share_price <= 15:
    print('b' + str(int(max_buy_greedily)))
    log()
    sys.exit(0)

log()
analyze()
sys.exit(0)

Тестований з python3


2
Удачі! Це далеко не нормальний ринок: D
бета-розпад

1
@BetaDecay, так:], але вам буде цікаво, як випадково більшість людей витрачають свої гроші на фондовому ринку (або біткойн): D
Соленя,

1

Вдалий номер 6

EDIT: О, ffs, я думаю, що не перетворення кількості продажів на int було однією з моїх проблем, і ось ми знову.

Можливо, мій останній внесок, якщо я не нудьгую на роботі і не роблю щось трішки складніше, але я впав, як витончені боти вже заповнюють ніші.

Цей хлопець, в основному, продає кілька своїх акцій кожні 6 раундів, тому що hey 6 - це його щасливе число.

from sys import argv
import random

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])
x = random.uniform(1,2)

if round == 1 or round == 1000:
    print("s"+str(share_count))
elif round % 6 == 0 and share_price >= 10:
    sell = int(share_count/x)
    print("s"+str(sell))
elif balance > share_price-1000:
    buy_count = int((balance+1000)/share_price)
    print("b"+str(buy_count))
else:
    print("b0")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.