1. 概要

トレーディングボットは、人間の介入を必要とせずに、市場または取引所に自動的に注文を出すことができるコンピュータプログラムです。

このチュートリアルでは、 Cassandre を使用して、最高の瞬間と思われるときにポジションを生成する単純な暗号取引ボットを作成します。

2. ボットの概要

取引とは、「あるアイテムを別のアイテムに交換する」ことを意味します。

金融市場では、株式、先物、オプション、スワップ、債券など、私たちの場合はある量の暗号通貨を購入しています。 ここでの考え方は、特定の価格で暗号通貨を購入し、それをより高い価格で販売して利益を上げることです(たとえ価格がショートポジションで下がっても利益を得ることができるとしても)。

サンドボックス交換を使用します。 サンドボックスは、「偽の」資産があり、注文してティッカーを受け取ることができる仮想システムです。

まず、私たちが何をするか見てみましょう:

  • Cassandreスプリングブートスターターをプロジェクトに追加します
  • 取引所に接続するために必要な構成を追加します
  • 戦略を作成します。
    • 取引所からティッカーを受け取る
    • いつ購入するかを選択してください
    • 購入するときは、十分な資産があり、ポジションを作成しているかどうかを確認してください
    • ログを表示して、ポジションがいつオープン/クローズされたか、およびどのくらいの利益が得られたかを確認します
  • 履歴データに対してテストを実行して、利益を上げることができるかどうかを確認します

3. Mavenの依存関係

pom.xml に必要な依存関係を追加することから始めましょう。最初に、Cassandrespring bootスターターです。

<dependency>
    <groupId>tech.cassandre.trading.bot</groupId>
    <artifactId>cassandre-trading-bot-spring-boot-starter</artifactId>
    <version>4.2.1</version>
</dependency>

CassandreはXChangeに依存して暗号交換に接続します。 このチュートリアルでは、KucoinXChangeライブラリを使用します。

<dependency>
    <groupId>org.knowm.xchange</groupId>
    <artifactId>xchange-kucoin</artifactId>
    <version>5.0.8</version>
</dependency>

また、hsqldを使用してデータを保存しています。

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.5.2</version>
</dependency>

履歴データに対してトレーディングボットをテストするために、テスト用のCassandreスプリングブートスターターも追加します。

<dependency>
    <groupId>tech.cassandre.trading.bot</groupId>
    <artifactId>cassandre-trading-bot-spring-boot-starter-test</artifactId>
    <version>4.2.1</version>
    <scope>test</scope>
</dependency>

4. 構成

create application.properties を編集して、構成を設定しましょう。

# Exchange configuration
cassandre.trading.bot.exchange.name=kucoin
cassandre.trading.bot.exchange.username=kucoin.cassandre.test@gmail.com
cassandre.trading.bot.exchange.passphrase=cassandre
cassandre.trading.bot.exchange.key=6054ad25365ac6000689a998
cassandre.trading.bot.exchange.secret=af080d55-afe3-47c9-8ec1-4b479fbcc5e7

# Modes
cassandre.trading.bot.exchange.modes.sandbox=true
cassandre.trading.bot.exchange.modes.dry=false

# Exchange API calls rates (ms or standard ISO 8601 duration like 'PT5S')
cassandre.trading.bot.exchange.rates.account=2000
cassandre.trading.bot.exchange.rates.ticker=2000
cassandre.trading.bot.exchange.rates.trade=2000

# Database configuration
cassandre.trading.bot.database.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
cassandre.trading.bot.database.datasource.url=jdbc:hsqldb:mem:cassandre
cassandre.trading.bot.database.datasource.username=sa
cassandre.trading.bot.database.datasource.password=

構成には4つのカテゴリがあります。

  • 交換構成:Kucoinの既存のサンドボックスアカウントへの接続用に設定した交換資格情報
  • モード:使用するモード。 この例では、Cassandreにサンドボックスデータを使用するように依頼しています
  • Exchange API呼び出しレート:取引所からデータ(アカウント、注文、取引、ティッカー)を取得するペースを示します。 気をつけて; すべての取引所には、私たちがそれらを呼び出すことができる最大レートがあります
  • データベース構成 :Cassandreはデータベースを使用して、ポジション、注文、取引を保存します。 このチュートリアルでは、単純なhsqldインメモリデータベースを使用します。 もちろん、本番環境では、永続データベースを使用する必要があります

次に、テストディレクトリの application.properties に同じファイルを作成しますが、cassandre.trading.bot.exchange.modes.drytrueに変更します。 、テスト中、実際の注文をサンドボックスに送信したくありません。 それらをシミュレートしたいだけです。

5. 戦略

取引戦略は、収益性の高い利益を達成するために設計された固定計画です。 注釈付きのJavaクラスを追加することで作成できます @CassandreStrategy と拡張 BasicCassandreStrategy.

で戦略クラスを作成しましょう MyFirstStrategy.java:

@CassandreStrategy
public class MyFirstStrategy extends BasicCassandreStrategy {

    @Override
    public Set<CurrencyPairDTO> getRequestedCurrencyPairs() {
        return Set.of(new CurrencyPairDTO(BTC, USDT));
    }

    @Override
    public Optional<AccountDTO> getTradeAccount(Set<AccountDTO> accounts) {
        return accounts.stream()
          .filter(a -> "trade".equals(a.getName()))
          .findFirst();
    }
}

実装 BasicCassandreStrategy 2つのメソッドを実装するように強制します getRequestedCurrencyPairs() getTradeAccount()

getRequestedCurrencyPairs()では、取引所から受け取りたい通貨ペアの更新のリストを返す必要があります。 通貨ペアは、2つの異なる通貨の見積もりであり、一方の通貨の値がもう一方の通貨に対して見積もられます。 この例では、BTC/USDTを使用します。

より明確にするために、次のcurlコマンドを使用して手動でティッカーを取得できます。

curl -s https://api.kucoin.com/api/v1/market/orderbook/level1?symbol=BTC-USDT

次のようなものが得られます。

{
  "time": 1620227845003,
  "sequence": "1615922903162",
  "price": "57263.3",
  "size": "0.00306338",
  "bestBid": "57259.4",
  "bestBidSize": "0.00250335",
  "bestAsk": "57260.4",
  "bestAskSize": "0.01"
}

価格値は、1BTCのコストが57263.3USDTであることを示しています。

実装する必要があるもう1つのメソッドは、 getTradeAccount()です。 交換では、通常、複数のアカウントがあり、Cassandreは、どのアカウントが取引アカウントであるかを知る必要があります。 そのためには、 getTradeAccount()メソッドを実装する必要があります。このメソッドは、所有するアカウントのリストをパラメーターとしてuswに提供し、そのリストから、取引に使用するアカウントを返す必要があります。 。

この例では、取引所の取引口座の名前は「trade」であるため、単に返品します。

6. ポジションの作成

新しいデータの通知を受け取るには、BasicCassandreStrategyの次のメソッドをオーバーライドできます。

  • onAccountUpdate()は、アカウントに関する更新を受け取ります
  • onTickerUpdate()は、新しいティッカーを受け取ります
  • onOrderUpdate()は、注文に関する最新情報を受け取ります
  • onTradeUpdate())取引に関する最新情報を受け取る
  • onPositionUpdate()は、位置に関する更新を受信します
  • onPositionStatusUpdate()は、位置ステータスの変更に関する更新を受信します

このチュートリアルでは、ダムアルゴリズムを実装します。 受け取ったすべての新しいティッカーをチェックします。 1BTCの価格が56000USDTを下回る場合は、購入する時期だと思います 。

ゲインの計算、注文、取引、および閉鎖について物事を簡単にするために、Cassandreはポジションを自動的に管理するクラスを提供します。

これを使用するには、最初のステップは、 PositionRulesDTO クラスのおかげで、位置のルールを作成することです。次に例を示します。

PositionRulesDTO rules = PositionRulesDTO.builder()
  .stopGainPercentage(4f)
  .stopLossPercentage(25f)
  .create();

次に、そのルールでポジションを作成しましょう。

createLongPosition(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0.01"), rules);

この時点で、Cassandreは0.01BTCの購入注文を作成します。 ポジションステータスはOPENINGになり、対応するすべての取引が到着すると、ステータスはOPENEDに移動します。 今後、Cassandreは、受け取ったティッカーごとに、新しい価格でポジションをクローズすると2つのルール(4% sトップゲインまたは25% sトップロス)のいずれかがトリガーされるかどうかを自動的に計算します。

1つのルールがトリガーされると、Cassandreは0.01BTCの販売注文を自動的に作成します。 ポジションステータスはCLOSINGに移動し、対応するすべての取引が到着すると、ステータスはCLOSEDに移動します。

これが私たちが持っているコードです:

@Override
public void onTickerUpdate(TickerDTO ticker) {
    if (new BigDecimal("56000").compareTo(ticker.getLast()) == -1) {

        if (canBuy(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0.01"))) {
            PositionRulesDTO rules = PositionRulesDTO.builder()
              .stopGainPercentage(4f)
              .stopLossPercentage(25f)
              .build();
            createLongPosition(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0.01"), rules);
        }
    }
}

総括する:

  • 新しいティッカーごとに、価格が56000未満であるかどうかを確認します。
  • トレードアカウントに十分なUSDTがある場合、0.01BTCのポジションを開きます。
  • 今後、すべてのティッカーについて:
    • 新しい価格で計算されたゲインが4% gainまたは25% lossを超える場合、Cassandreは購入した0.01BTCを販売することで作成したポジションをクローズします。

7. ログで位置の進化を追跡する

最後に、 onPositionStatusUpdate()を実装して、ポジションがいつ開閉されるかを確認します。

@Override
public void onPositionStatusUpdate(PositionDTO position) {
    if (position.getStatus() == OPENED) {
        logger.info("> New position opened : {}", position.getPositionId());
    }
    if (position.getStatus() == CLOSED) {
        logger.info("> Position closed : {}", position.getDescription());
    }
}

8. バックテスト

簡単に言えば、戦略のバックテストは、前の期間の取引戦略をテストするプロセスです。 Cassandreトレーディングボットを使用すると、履歴データに対するボットの反応をシミュレートできます。

最初のステップは、履歴データ(CSVまたはTSVファイル)を src / test /resourcesフォルダーに配置することです。

Linuxを使用している場合、それらを生成するための簡単なスクリプトを次に示します。

startDate=`date --date="3 months ago" +"%s"`
endDate=`date +"%s"`
curl -s "https://api.kucoin.com/api/v1/market/candles?type=1day&symbol=BTC-USDT&startAt=${startDate}&endAt=${endDate}" \
| jq -r -c ".data[] | @tsv" \
| tac $1 > tickers-btc-usdt.tsv

startDate (3か月前)からendDateまでのBTC-USDTの履歴レートを含むtickers-btc-usdt.tsvという名前のファイルを作成します。 (今)。

2番目のステップは、仮想アカウントの残高を作成して、投資する資産の正確な量をシミュレートすることです。

これらのファイルでは、アカウントごとに、各暗号通貨の残高を設定します。 たとえば、これは、トレードアカウントのアセットをシミュレートするuser-trade.csvのコンテンツです。

このファイルは、 src / test /resourcesフォルダーにもある必要があります。

BTC 1
USDT 10000
ETH 10

これで、テストを追加できます。

@SpringBootTest
@Import(TickerFluxMock.class)
@DisplayName("Simple strategy test")
public class MyFirstStrategyLiveTest {
    @Autowired
    private MyFirstStrategy strategy;

    private final Logger logger = LoggerFactory.getLogger(MyFirstStrategyLiveTest.class);

    @Autowired
    private TickerFluxMock tickerFluxMock;

    @Test
    @DisplayName("Check gains")
    public void whenTickersArrives_thenCheckGains() {
        await().forever().until(() -> tickerFluxMock.isFluxDone());

        HashMap<CurrencyDTO, GainDTO> gains = strategy.getGains();

        logger.info("Cumulated gains:");
        gains.forEach((currency, gain) -> logger.info(currency + " : " + gain.getAmount()));

        logger.info("Position still opened :");
        strategy.getPositions()
          .values()
          .stream()
          .filter(p -> p.getStatus().equals(OPENED))
          .forEach(p -> logger.info(" - {} " + p.getDescription()));

        assertTrue(gains.get(USDT).getPercentage() > 0);
    }
    
}

@Import from TickerFluxMock は、 src / test / resources フォルダーから履歴データをロードし、それらを戦略に送信します。 次に、 await()メソッドを使用して、ファイルからロードされたすべてのティッカーがストラテジーに送信されたことを確認します。 最後に、閉じた位置、開いたままの位置、およびグローバルゲインを表示します。

9. 結論

このチュートリアルでは、暗号交換と相互作用する戦略を作成し、履歴データに対してテストする方法を説明しました。

もちろん、私たちのアルゴリズムは単純でした。 実生活では、目標は、有望なテクノロジー、優れたアルゴリズム、およびポジションを作成できる時期を知るための優れたデータを見つけることです。 たとえば、Cassandreがta4j。を統合するときにテクニカル分析を使用できます。

この記事のすべてのコードは、GitHubから入手できます。