Stack Exchange股票交易所-V3


42

注意:此挑战现已结束:我将不再更新排行榜,也不会更改已接受的答案。但是,您可以随意运行控制器并自行更新排行榜。

加入聊天!

介绍

晚上好,交易员!你们都是高尔夫公司PPCG的商人。您的任务是赚尽可能多的钱。

挑战

编写一个在Stack Exchange Stock Exchange上买卖股票的程序,目的是尽可能赚钱。

游戏玩法

所有玩家将以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

您出售的股票数量可能不会超过您拥有的股票数量。如果您尝试这样做,则您的请求将被拒绝,并且您将跳过该回合。

如果您想跳过该回合而不执行任何操作,请输出b0s0

如果您尝试买卖负数股和/或非整数股,您的请求将被拒绝。

经过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

最后,它将打印一个排行榜并显示股价在整个游戏中如何变化的图表。

例如,当两个随机机器人在玩

获奖

在最后一场游戏结束时,其余额中金额最高的玩家将获胜。

排行榜

第四局:16:14 10/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也太少了,但我喜欢玩很多游戏。为了使之成为可能,您需要更改挑战的格式,该格式现已超出范围。
内森·美林

Answers:


11

经验丰富的贪婪白痴

经PHP> = 7测试的PHP也应适用于以前的版本。

<?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并附加到末尾。因此,请与在脚本路径上具有适当写许可权的用户一起运行。
  • 一个简单的如何在Windows上安装PHP 7.2的方法:http : //www.dorusomcutean.com/how-to-install-php-7-2-on-windows/
  • 要处理超大数字,我必须使用GMP,因此php.ini应取消对这两行的注释(如果尚未删除,则应删除行首的分号):
    • ; extension_dir = "ext"
    • ;extension=gmp

1
哇,谢谢你的链接!我想知道:D
Beta衰变'18

1
@BetaDecay:没问题,顺便说一句,您只需要执行步骤2(已安装Test PHP),即可使用来检查安装php -v。其余的不需要这样做。我相信您会为挑战设置这么多不同的语言而遇到很多麻烦!我永远都不敢做这样的事情:D
Night2

@BetaDecay将TryItOnline作为Docker容器安装会更容易吗?
NieDzejkob

@NieDzejkob可能,但是安装这些语言可能会派上用场
Beta Decay

1
恭喜,您始终击败其他所有参赛者!
Beta Decay

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
Night2

10

奥亚布

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!
Beta Decay

谢谢!第一次发布,所以让我知道是否有任何异常。
just_browsing

您可能需要添加一个额外条件,即在最后一轮中,您卖出了所有股票(investments不计入分数)。
凌晨

2
这就是OYAIB的优点,它会自动执行。target_cash是total_assets的百分比,具体取决于它位于“生命”中的哪一点。在生命周期尽头,target_cash是total_assets的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在每两回合后股价将保持相同()(假设机器人是一个人,因此是Lone Accountant),该机器人的余额也会增加,因为售价高于买入价,而更多的余额导致购买更多股票的能力。这是一个恶性循环,但对我而言是一个好方法。

最大的漏洞在于邪恶的机器人在旁边玩耍,为了降低股价而进行出售(不确定是否对他们也有好处)。在这种情况下,如果有足够多的恶意机器人,则该机器人可能会保持$ -890的余额。这名会计师真的很想让他们省心。;-)


我不确定一对一的打法是否可行;即使您完全了解会计师事务所LA并尝试反制它,也不容易。在人数众多的大众游戏中,您可能会表现出色。
Yakk

@Yakk其他人已经在我的测试运行中击败了它。
暴民埃里克(Erik the Outgolfer)'18年

1对1?我很困惑;我无法弄清楚对手如何变得足够富有以扭转价格波动,甚至阻止它们随着时间的推移而增长而又不消耗大量资源(同时洛杉矶没有做出牺牲,因此变得更难了)停)。您可以链接到洛杉矶一对一输掉的游戏吗?
Yakk

@Yakk我尚未进行一对一的测试。此外,如果您愿意,我们还设有一个聊天室供我们讨论。
暴民埃里克(Erik the Outgolfer)'18年

如果您有股票并且价格低于上一轮,或者您有钱并且价格更高,那么什么都不做会更强大吗?它将防止与其他类似的机器人不同步。另外,我看不出如何一对一地击败它。
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运行价格#股份余额回合#

这个怎么运作

  • 该机器人会在第一轮购买尽可能多的股票。
  • 如果价格上涨,则机器人会出售等于价格上涨百分比的股份百分比(根据新价值计算)
  • 如果价格下跌,则漫游器会购买其可以购买的最大份额的百分比,该百分比等于价格减少的百分比(根据之前的价格计算)
  • 在第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进行了测试)

首先在codegolf中发消息,告诉我是否做错了什么。

基本思想是,如果可能的话,每轮购买一股股票,最后出售所有股票。

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))
Beta Decay

1
因为我很懒
Skidsdev'18年

1
为什么不只是import lazy
Woohoojin

整个事情可以简化为from random import randint, choice;print("{}{}".format(choice(["b", "s"]), randint(0, 1e6)))--P
Aaron 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 shell中。

因此,要在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,粘贴上面的代码然后执行来获得该工作区文件)save <path>。如果这样会更容易,我也可以提供此工作区文件。

-script 只是使dyalog执行给定代码并打印到stdout而无需实际打开REPL的参数。

不幸的是,我还没有找到使其与Windows CMD或Powershell一起工作的方法,因此我使用Git Bash运行了它。我不确定将这个机器人放到竞赛中是否可行,但是我非常喜欢这个代码,不要发布它。


抱歉,我只有Dyalog APL的未注册版本,所以我不确定这会成为比赛的参赛者
Beta Decay

@BetaDecay我了解,那里没有问题。我还发现您可以使用Pynapl库运行此代码。详细信息在“从Python访问APL”下,尤其是“使用Python定义tradfn”下,它看起来非常简单。
J.Sallé18年

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轮中经历另一个卖/买周期。


从控制者的角度来看,股息在第四轮之后每轮支付,而不仅仅是每五轮一次。您的周期应该仍然有效,但可能未达到您的预期。
维斯卡

如果您是在别人购买之后购买的,那么最终您会在购买时变得更昂贵。
fəˈnɛtɪk

谢谢@Veskah。还必须添加一些r1 / r1000逻辑。
brian_t

@ fəˈnɛtɪk-假设人们在分红后买入该轮,您也想购买该轮然后再卖出,不是吗?
brian_t

股息之后也没有回合,因为您在第4轮之后每轮都会获得股息。
fəˈnɛtɪk

3

尽可能购买/再投资!

类似于我的Dollar-Cost Averager(平均平均费用),令人惊讶的是,它相当平均,它每轮购买尽可能多的可负担股票,并且仅在最后一轮出售。

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:还是不缩进?
Beta Decay '18

是。我的次要编辑似乎破坏了我的格式。只要我在电脑上恢复就可以解决
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 '18

4
@BetaDecay:可惜作者的中间名不是以“ A”开头。
3D1T0R

3
@NieDzejkob:如果它是'A':“ Ann A. Logue” 类似于Analog ”。
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
Beta衰减,

@BetaDecay我更新了可以解决此问题的代码。让我知道。
罗伯特S.18年

1

贪婪B ***** d

# 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,

带有三个参数的typo到sell()...现在,您对返回打印语句有何担忧?
Arek S

只是,他们是不必要的
β衰变

有人认为它们有助于提高可读性
Arek S '18

您没有因为打印而将其包括在结果中?sale()定义中的afaik错字不会停止它的工作...顺便解决一下
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
Beta Decay,

1
@BetaDecay haha​​ yeah:],但您会想知道大多数人是如何随机地将他们的钱花在股市(或比特币)上的:D
Solenya,

1

幸运数字6

编辑:哦,老兄,我认为我不将销售数量转换为整数是我的问题之一,在这里我们再次进行。

可能是我的最后一个贡献,除非我对工作感到无聊并且做些更复杂的事情,但是我倒是因为复杂的机器人已经占据了优势。

这个家伙基本上每6轮就卖出一部分股票,因为嘿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")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.