Stream Analytics ile yüksek frekanslı alım-satım simülasyonu

Azure Stream Analytics SQL dili, JavaScript kullanıcı tanımlı işlevler (UDF) ve kullanıcı tanımlı toplamalar (UDA) birleşimi aracılığıyla gelişmiş analizi destekler. Gelişmiş analizler, çevrimiçi makine öğrenmesi eğitimi ve puanlama ile durum bilgisi olan işlem simülasyonlarını içerir. Bu makalede, yüksek frekanslı bir alım satım senaryosunda sürekli eğitim ve puanlama yapan bir Azure Stream Analytics işinde doğrusal regresyon gerçekleştirme işlemi açıklanmaktadır.

Prerequisites

Yüksek frekanslı ticaret iş akışı

Yüksek frekanslı ticaretin mantıksal akışı:

  1. Bir menkul kıymetler borsasından gerçek zamanlı kotasyonlar alma.
  2. Kotasyonları temel alarak fiyat hareketini öngörmek için tahmine dayalı bir model oluşturma.
  3. Fiyat hareketlerinin başarılı tahmininden para kazanmak için satın alma veya satış siparişleri verme.

Bu senaryo şunları gerektirir:

  • Gerçek zamanlı teklif akışı.
  • Gerçek zamanlı fiyat teklifileriyle çalışabilen tahmine dayalı bir model.
  • Ticaret algoritmasının kar veya zararını gösteren bir ticaret simülasyonu.

Gerçek zamanlı teklif akışı

Important

Bu bölümde başvurulan IEX ticaret WebSocket API'si (iextrading.com) kullanımdan kaldırılmıştır. IEX Cloud artık farklı kimlik doğrulaması ve uç noktalarla IEX Cloud aracılığıyla pazar verileri sağlıyor. Uygulamanızdaki URL'yi ve kimlik doğrulamasını uygun şekilde güncelleştirin.

Important

SocketIoClientDotNet Bu örnekte kullanılan ve WindowsAzure.ServiceBus NuGet paketleri kullanım dışıdır. Yeni projeler için, eski Azure.Messaging.EventHubs yerine geçerli bir Socket.IO istemci kitaplığını ve EventHubProducerClient ile EventHubClient paketini kullanın.

Investors Exchange (IEX), daha önce socket.io kullanarak ücretsiz gerçek zamanlı alış ve satış kotasyonları sunuyordu. Gerçek zamanlı teklifler almak ve bunları veri kaynağı olarak Azure Event Hubs göndermek için basit bir konsol programı yazabilirsiniz. Aşağıdaki kod, programın bir iskeletidir. Kod, kısa süre için hata işlemeyi atlar. Ayrıca projenize SocketIoClientDotNet NuGet paketlerini WindowsAzure.ServiceBus de eklemeniz gerekir.

using Quobject.SocketIoClientDotNet.Client;
using Microsoft.ServiceBus.Messaging;
var symbols = "msft,fb,amzn,goog";
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName);
var socket = IO.Socket("https://ws-api.iextrading.com/1.0/tops");
socket.On(Socket.EVENT_MESSAGE, (message) =>
{
    eventHubClient.Send(new EventData(Encoding.UTF8.GetBytes((string)message)));
});
socket.On(Socket.EVENT_CONNECT, () =>
{
    socket.Emit("subscribe", symbols);
});

Caution

Bu kod örneği yalnızca çizim içindir. IEX WebSocket API uç noktası ve burada kullanılan NuGet paketleri artık kullanılamaz. Bu kodu üretimde kullanmayın. Geçerli alternatifler için bu bölümün önceki bölümlerinde yer alan ÖNEMLİ notlara bakın.

Oluşturulan bazı örnek olaylar şunlardır:

{"symbol":"MSFT","marketPercent":0.03246,"bidSize":100,"bidPrice":74.8,"askSize":300,"askPrice":74.83,"volume":70572,"lastSalePrice":74.825,"lastSaleSize":100,"lastSaleTime":1506953355123,"lastUpdated":1506953357170,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"GOOG","marketPercent":0.04825,"bidSize":114,"bidPrice":870,"askSize":0,"askPrice":0,"volume":11240,"lastSalePrice":959.47,"lastSaleSize":60,"lastSaleTime":1506953317571,"lastUpdated":1506953357633,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"MSFT","marketPercent":0.03244,"bidSize":100,"bidPrice":74.8,"askSize":100,"askPrice":74.83,"volume":70572,"lastSalePrice":74.825,"lastSaleSize":100,"lastSaleTime":1506953355123,"lastUpdated":1506953359118,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"FB","marketPercent":0.01211,"bidSize":100,"bidPrice":169.9,"askSize":100,"askPrice":170.67,"volume":39042,"lastSalePrice":170.67,"lastSaleSize":100,"lastSaleTime":1506953351912,"lastUpdated":1506953359641,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"GOOG","marketPercent":0.04795,"bidSize":100,"bidPrice":959.19,"askSize":0,"askPrice":0,"volume":11240,"lastSalePrice":959.47,"lastSaleSize":60,"lastSaleTime":1506953317571,"lastUpdated":1506953360949,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"FB","marketPercent":0.0121,"bidSize":100,"bidPrice":169.9,"askSize":100,"askPrice":170.7,"volume":39042,"lastSalePrice":170.67,"lastSaleSize":100,"lastSaleTime":1506953351912,"lastUpdated":1506953362205,"sector":"softwareservices","securityType":"commonstock"}
{"symbol":"GOOG","marketPercent":0.04795,"bidSize":114,"bidPrice":870,"askSize":0,"askPrice":0,"volume":11240,"lastSalePrice":959.47,"lastSaleSize":60,"lastSaleTime":1506953317571,"lastUpdated":1506953362629,"sector":"softwareservices","securityType":"commonstock"}

Note

Olayın zaman damgası lastUpdated(son güncelleştirme) zaman dilimindedir.

Yüksek frekanslı ticaret için tahmine dayalı model

Bu gösterim için örnek, Yüksek Frekanslı Algoritmik Ticarette Sipariş Dengesizliği Tabanlı Strateji'de açıklanan doğrusal bir model kullanır.

Hacim emir dengesizliği (VOI), mevcut alış/satış fiyatı ve hacmi ile son tikteki alış/satış fiyatı ve hacminin bir fonksiyonudur. Kağıt, VOI ile gelecekteki fiyat hareketi arasındaki bağıntıyı tanımlar. Son beş VOI değeri ile sonraki 10 değerdeki fiyat değişikliği arasında doğrusal bir model oluşturur. Model, doğrusal regresyon kullanarak önceki günün verileriyle eğitilir.

Daha sonra eğitilen model, geçerli işlem günündeki tekliflerde gerçek zamanlı olarak fiyat değişikliği tahminleri yapar. Model yeterince büyük bir fiyat değişikliği tahmin ettiğinde bir işlem yürütür. Eşik ayarına bağlı olarak, tek bir hisse senedi bir işlem günü boyunca binlerce işlem üretebilir.

Yüksek frekanslı alım satımda kullanılan birim sırası dengesizliği tanım formülünü gösteren diyagram.

Aşağıdaki bölümlerde, Azure Stream Analytics bir işte eğitim ve tahmin işlemlerinin nasıl ifade edildiği gösterilmektedir. Sorgunun tamamı, işlem hattı oluşturan ortak tablo ifadelerinden (CTE) oluşan tek WITH bir deyimdir:

CTE aşaması Purpose
typeconvertedquotes Ham giriş alanlarını uygun SQL türlerine dönüştürme
timefilteredquotes Fiyat tekliflerini işlem saatlerine göre filtreleme ve geçersiz verileri kaldırma
shiftedquotes Önceki tick'in bid/ask değerlerini almak için LAG kullanın
currentPriceAndVOI Geçerli ve önceki değerden birim sipariş dengesizliği (VOI) hesaplama
shiftedPriceAndShiftedVOI Ardışık 10 orta fiyat ve ardışık 2 VOI değerinden oluşan diziler oluşturma
modelInput Verileri özellik vektörlerine göre yeniden şekillendirin (VOI x, fiyat değişim değeri y)
modelagg / modelparambs / model SUM ve AVG toplama işlevlerini kullanarak iki değişkenli doğrusal regresyon modeli eğitin
shiftedVOI / VOIAndModel / VOIANDModelJoined Mevcut VOI değerlerini önceki günün eğitilen modeliyle birleştirme
prediction Modelden beklenen gelecekteki fiyat değişikliğini (efpc) hesaplama
tradeSignal Efpc ±0.02 eşiğini aştığında alış/satış sinyalleri oluşturma

Note

Bu sorgu, UDA'larla öngörülebilir davranış sağlamak için alan adlarının büyük/küçük harf kullanımını koruyan Azure Stream Analytics uyumluluk düzeyi 1.1 veya üzeri bir düzey gerektirir.

Teklif giriş alanlarını temizleme ve dönüştürme

Azure Stream Analytics sorgusundaki ilk CTE, Event Hubs’taki ham teklif verilerini uygun veri türlerine sahip SQL sütunlarına dönüştürür. DATEADD , dönem süresini (Unix milisaniye) tarih saatine dönüştürür. TRY_CAST, sorgunun başarısız olmasına neden olmadan veri türlerini dönüştürür. Alanların düzenlenmesinde veya karşılaştırılmasında beklenmeyen davranışlardan kaçınmak için giriş alanlarını beklenen veri türlerine dönüştürebilirsiniz.

WITH
typeconvertedquotes AS (
    /* convert all input fields to proper types */
    SELECT
        System.Timestamp AS lastUpdated,
        symbol,
        DATEADD(millisecond, CAST(lastSaleTime as bigint), '1970-01-01T00:00:00Z') AS lastSaleTime,
        TRY_CAST(bidSize as bigint) AS bidSize,
        TRY_CAST(bidPrice as float) AS bidPrice,
        TRY_CAST(askSize as bigint) AS askSize,
        TRY_CAST(askPrice as float) AS askPrice,
        TRY_CAST(volume as bigint) AS volume,
        TRY_CAST(lastSaleSize as bigint) AS lastSaleSize,
        TRY_CAST(lastSalePrice as float) AS lastSalePrice
    FROM quotes TIMESTAMP BY DATEADD(millisecond, CAST(lastUpdated as bigint), '1970-01-01T00:00:00Z')
),
timefilteredquotes AS (
    /* filter between 7am and 1pm PST, 14:00 to 20:00 UTC */
    /* clean up invalid data points */
	SELECT * FROM typeconvertedquotes
	WHERE DATEPART(hour, lastUpdated) >= 14 AND DATEPART(hour, lastUpdated) < 20 AND bidSize > 0 AND askSize > 0 AND bidPrice > 0 AND askPrice > 0
),

LAG ile önceki tick değerlerini alma

Azure Stream Analytics sorgusundaki bir sonraki CTE, her hisse senedi simgesi için bir önceki tick’ten alış/satış fiyatı ve miktarını almak üzere LAG işlevini kullanır. Bir saatlik LIMIT DURATION değeri rastgele seçilir. Teklif sıklığı göz önünde bulundurulduğunda, bir saat geriye bakarak önceki onay işaretini bulabilirsiniz.

shiftedquotes AS (
    /* get previous bid/ask price and size in order to calculate VOI */
	SELECT
		symbol,
		(bidPrice + askPrice)/2 AS midPrice,
		bidPrice,
		bidSize,
		askPrice,
		askSize,
		LAG(bidPrice) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS bidPricePrev,
		LAG(bidSize) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS bidSizePrev,
		LAG(askPrice) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS askPricePrev,
		LAG(askSize) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS askSizePrev
	FROM timefilteredquotes
),

Birim sipariş dengesizliği (VOI) hesaplama

Sonraki CTE, mevcut ve önceki tikin alış/satış verilerinden VOI değerini hesaplar. Sorgu, önceki tick’in bulunmadığı durumlarda null değerleri hariç tutar.

currentPriceAndVOI AS (
    /* calculate VOI */
	SELECT
		symbol,
		midPrice,
		(CASE WHEN (bidPrice < bidPricePrev) THEN 0
            ELSE (CASE WHEN (bidPrice = bidPricePrev) THEN (bidSize - bidSizePrev) ELSE bidSize END)
         END) -
        (CASE WHEN (askPrice < askPricePrev) THEN askSize
            ELSE (CASE WHEN (askPrice = askPricePrev) THEN (askSize - askSizePrev) ELSE 0 END)
         END) AS VOI
	FROM shiftedquotes
	WHERE
		bidPrice IS NOT NULL AND
		bidSize IS NOT NULL AND
		askPrice IS NOT NULL AND
		askSize IS NOT NULL AND
		bidPricePrev IS NOT NULL AND
		bidSizePrev IS NOT NULL AND
		askPricePrev IS NOT NULL AND
		askSizePrev IS NOT NULL
),

Model eğitimi için özellik dizileri oluşturma

Sonraki CTE, ardışık 2 VOI değeri ve ardından ardışık 10 orta fiyat değeri içeren bir dizi oluşturmak için LAG'yi yeniden kullanır. Bu diziler doğrusal regresyon modeli için eğitim verilerini oluşturur.

shiftedPriceAndShiftedVOI AS (
    /* get 10 future prices and 2 previous VOIs */
    SELECT
		symbol,
		midPrice AS midPrice10,
		LAG(midPrice, 1) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice9,
		LAG(midPrice, 2) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice8,
		LAG(midPrice, 3) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice7,
		LAG(midPrice, 4) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice6,
		LAG(midPrice, 5) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice5,
		LAG(midPrice, 6) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice4,
		LAG(midPrice, 7) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice3,
		LAG(midPrice, 8) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice2,
		LAG(midPrice, 9) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice1,
		LAG(midPrice, 10) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS midPrice,
		LAG(VOI, 10) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS VOI1,
		LAG(VOI, 11) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS VOI2
	FROM currentPriceAndVOI
),

Verileri özellik vektörlerine yeniden şekillendirme

Sonraki CTE, fiyat ve VOI dizilerini iki değişkenli doğrusal model için özellik vektörleri olarak yeniden şekillendirir; burada VOI değerleri bağımsız değişkenlerdir (x1, x2) ve gelecekteki ortalama fiyat değişikliği bağımlı değişkendir (y). Eksik verileri olan olaylar filtrelenir.

modelInput AS (
    /* create feature vector, x being VOI, y being delta price */
	SELECT
		symbol,
		(midPrice1 + midPrice2 + midPrice3 + midPrice4 + midPrice5 + midPrice6 + midPrice7 + midPrice8 + midPrice9 + midPrice10)/10.0 - midPrice AS y,
		VOI1 AS x1,
		VOI2 AS x2
	FROM shiftedPriceAndShiftedVOI
	WHERE
		midPrice1 IS NOT NULL AND
		midPrice2 IS NOT NULL AND
		midPrice3 IS NOT NULL AND
		midPrice4 IS NOT NULL AND
		midPrice5 IS NOT NULL AND
		midPrice6 IS NOT NULL AND
		midPrice7 IS NOT NULL AND
		midPrice8 IS NOT NULL AND
		midPrice9 IS NOT NULL AND
		midPrice10 IS NOT NULL AND
		midPrice IS NOT NULL AND
		VOI1 IS NOT NULL AND
		VOI2 IS NOT NULL
),

SUM ve AVG ile doğrusal regresyon modelini eğitme

Azure Stream Analytics yerleşik doğrusal regresyon işlevi olmadığından sorgu, iki değişkenli doğrusal regresyon modelinin katsayılarını (a, b1, b2) hesaplamak için SUM ve AVG toplamlarını kullanır. Model, 24 saatlik devrilen bir pencere kullanılarak günlük olarak yeniden eğitilmektedir.

Hesaplama modeli katsayıları için doğrusal regresyon matematik formülünü gösteren diyagram.

modelagg AS (
    /* get aggregates for linear regression calculation,
     http://faculty.cas.usf.edu/mbrannick/regression/Reg2IV.html */
	SELECT
		symbol,
		SUM(x1 * x1) AS x1x1,
		SUM(x2 * x2) AS x2x2,
		SUM(x1 * y) AS x1y,
		SUM(x2 * y) AS x2y,
		SUM(x1 * x2) AS x1x2,
		AVG(y) AS avgy,
		AVG(x1) AS avgx1,
		AVG(x2) AS avgx2
	FROM modelInput
	GROUP BY symbol, TumblingWindow(hour, 24, -4)
),
modelparambs AS (
    /* calculate b1 and b2 for the linear model */
	SELECT
		symbol,
		(x2x2 * x1y - x1x2 * x2y)/(x1x1 * x2x2 - x1x2 * x1x2) AS b1,
		(x1x1 * x2y - x1x2 * x1y)/(x1x1 * x2x2 - x1x2 * x1x2) AS b2,
		avgy,
		avgx1,
		avgx2
	FROM modelagg
),
model AS (
    /* calculate a for the linear model */
	SELECT
		symbol,
		avgy - b1 * avgx1 - b2 * avgx2 AS a,
		b1,
		b2
	FROM modelparambs
),

Mevcut teklifleri önceki günün modeliyle puanla

Mevcut olayı puanlamak için önceki gün eğitilmiş doğrusal regresyon modelini kullanmak üzere sorgu, kotasyonları model katsayılarıyla birleştirir. Sorgu, JOIN kullanmak yerine UNION kullanarak model olaylarını ve alıntı olaylarını tek bir akışta birleştirir. Ardından, olayları önceki günün modeliyle eşleştirmek için LAG kullanır, böylece tam olarak bir eşleşme elde edersiniz. Hafta sonu nedeniyle sorgu üç gün (72 saat) geriye bakar. Doğrudan bir JOIN kullanılsaydı, her fiyat teklifi olayı için üç model elde ederdiniz.

shiftedVOI AS (
    /* get two consecutive VOIs */
	SELECT
		symbol,
		midPrice,
		VOI AS VOI1,		
		LAG(VOI, 1) OVER (PARTITION BY symbol LIMIT DURATION(hour, 1)) AS VOI2
	FROM currentPriceAndVOI
),
VOIAndModel AS (
    /* combine VOIs and models */
	SELECT
		'voi' AS type,
		symbol,
		midPrice,
		VOI1,
		VOI2,
        0.0 AS a,
        0.0 AS b1,
        0.0 AS b2
	FROM shiftedVOI
	UNION
	SELECT
		'model' AS type,
		symbol,
        0.0 AS midPrice,
        0 AS VOI1,
        0 AS VOI2,
		a,
		b1,
		b2
	FROM model
),
VOIANDModelJoined AS (
    /* match VOIs with the latest model within 3 days (72 hours, to take the weekend into account) */
	SELECT
		symbol,
		midPrice,
		VOI1 as x1,
		VOI2 as x2,
		LAG(a, 1) OVER (PARTITION BY symbol LIMIT DURATION(hour, 72) WHEN type = 'model') AS a,
		LAG(b1, 1) OVER (PARTITION BY symbol LIMIT DURATION(hour, 72) WHEN type = 'model') AS b1,
		LAG(b2, 1) OVER (PARTITION BY symbol LIMIT DURATION(hour, 72) WHEN type = 'model') AS b2
	FROM VOIAndModel
	WHERE type = 'voi'
),

Tahminlerden ticari sinyaller oluşturma

Son CTE'ler doğrusal regresyon formülünü () uygulayarak beklenen gelecekteki fiyat değişikliğini (a + b1 * x1 + b2 * x2efpc) hesaplar ve ardından ±0,02 eşiğine göre alış/satış sinyalleri oluşturur. 10'unun ticari değeri satın almaktır. -10 işlem değeri, sat anlamına gelir.

prediction AS (
    /* make prediction if there is a model */
	SELECT
		symbol,
		midPrice,
		a + b1 * x1 + b2 * x2 AS efpc
	FROM VOIANDModelJoined
	WHERE
		a IS NOT NULL AND
		b1 IS NOT NULL AND
		b2 IS NOT NULL AND
        x1 IS NOT NULL AND
        x2 IS NOT NULL
),
tradeSignal AS (
    /* generate buy/sell signals */
	SELECT
        DateAdd(hour, -7, System.Timestamp) AS time,
		symbol,		
		midPrice,
        efpc,
		CASE WHEN (efpc > 0.02) THEN 10 ELSE (CASE WHEN (efpc < -0.02) THEN -10 ELSE 0 END) END AS trade,
		DATETIMEFROMPARTS(DATEPART(year, System.Timestamp), DATEPART(month, System.Timestamp), DATEPART(day, System.Timestamp), 0, 0, 0, 0) as date
	FROM prediction
),

Simülasyon ile ticaret stratejisini test edin

Alım satım sinyallerini üretdikten sonra, ticaret stratejisinin gerçek alım satım olmadan ne kadar etkili olduğunu test edin.

Bu test, her dakika atlayan bir atlamalı pencereye sahip bir UDA kullanır. Tarihe göre gruplandırma ve HAVING ifadesi, pencerenin yalnızca aynı güne ait olayları dikkate almasını sağlar. İki güne yayılan bir kayan pencere için, GROUP BY tarihi gruplandırmayı önceki gün ve içinde bulunulan gün olarak ayırır. HAVING ifadesi, içinde bulunulan günde sona eren ancak önceki günde gruplanan pencerelerin elenmesini sağlar.

simulation AS
(
    /* perform trade simulation for the past 7 hours to cover an entire trading day, and generate output every minute */
	SELECT
        DateAdd(hour, -7, System.Timestamp) AS time,
		symbol,
		date,
		uda.TradeSimulation(tradeSignal) AS s
	FROM tradeSignal
	GROUP BY HoppingWindow(minute, 420, 1), symbol, date
	Having DateDiff(day, date, time) < 1 AND DATEPART(hour, time) < 13
)

JavaScript UDA işlevindeki init tüm biriktiricileri başlatır, pencereye eklenen her olayla durum geçişini hesaplar ve pencerenin sonunda simülasyon sonuçlarını döndürür. Simülasyon, işlem başına bir hissede 10 adet uzun ya da kısa pozisyon alır. İşlem maliyeti düzdür $8. Aşağıdaki tabloda UDA'nın gerçekleştirdiği dört işlem eylemi gösterilmektedir:

Condition Sinyal Action Sonraki konum
Geçerli tutma yok Satın Al (10) Açmak için satın alın Long
Geçerli tutma yok Satış (-10) Açığa satış (kısa pozisyon) Short
Uzun pozisyon Satış (-10) Pozisyon kapatmak için sat, ardından açığa satışla pozisyon aç Short
Kısa pozisyon Satın Al (10) Kapatmak için satın alın, ardından açmak için satın alın Long
function main() {
	var TRADE_COST = 8.0;
	var SHARES = 10;
	this.init = function () {
		this.own = false;
		this.pos = 0;
		this.pnl = 0.0;
		this.tradeCosts = 0.0;
		this.buyPrice = 0.0;
		this.sellPrice = 0.0;
		this.buySize = 0;
		this.sellSize = 0;
		this.buyTotal = 0.0;
		this.sellTotal = 0.0;
	}
	this.accumulate = function (tradeSignal, timestamp) {
		if(!this.own && tradeSignal.trade == 10) {
		  // Buy to open
		  this.own = true;
		  this.pos = 1;
		  this.buyPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.buySize += SHARES;
		  this.buyTotal += SHARES * tradeSignal.midprice;
		} else if(!this.own && tradeSignal.trade == -10) {
		  // Sell to open
		  this.own = true;
		  this.pos = -1
		  this.sellPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.sellSize += SHARES;
		  this.sellTotal += SHARES * tradeSignal.midprice;
		} else if(this.own && this.pos == 1 && tradeSignal.trade == -10) {
		  // Sell to close
		  this.own = false;
		  this.pos = 0;
		  this.sellPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.pnl += (this.sellPrice - this.buyPrice)*SHARES - 2*TRADE_COST;
		  this.sellSize += SHARES;
		  this.sellTotal += SHARES * tradeSignal.midprice;
		  // Sell to open
		  this.own = true;
		  this.pos = -1;
		  this.sellPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.sellSize += SHARES;		  
		  this.sellTotal += SHARES * tradeSignal.midprice;
		} else if(this.own && this.pos == -1 && tradeSignal.trade == 10) {
		  // Buy to close
		  this.own = false;
		  this.pos = 0;
		  this.buyPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.pnl += (this.sellPrice - this.buyPrice)*SHARES - 2*TRADE_COST;
		  this.buySize += SHARES;
		  this.buyTotal += SHARES * tradeSignal.midprice;
		  // Buy to open
		  this.own = true;
		  this.pos = 1;
		  this.buyPrice = tradeSignal.midprice;
		  this.tradeCosts += TRADE_COST;
		  this.buySize += SHARES;		  
		  this.buyTotal += SHARES * tradeSignal.midprice;
		}
	}
	this.computeResult = function () {
		var result = {
			"pnl": this.pnl,
			"buySize": this.buySize,
			"sellSize": this.sellSize,
			"buyTotal": this.buyTotal,
			"sellTotal": this.sellTotal,
			"tradeCost": this.tradeCost
			};
		return result;
	}
}

Note

Azure Stream Analytics için Power BI çıkış bağlayıcısı kullanımdan kaldırılıyor. Azure Veri Gezgini, Azure Synapse Analytics veya Power BI DirectQuery veya içeri aktarma yoluyla bağlanabileceği bir veri deposu gibi alternatif çıkış hedeflerini kullanmayı göz önünde bulundurun. Daha fazla bilgi için Azure Stream Analytics'in Power BI çıktısı bölümüne bakın.

Son olarak görselleştirme için Power BI panosuna çıkış.

SELECT * INTO tradeSignalDashboard FROM tradeSignal /* output tradeSignal to PBI */
SELECT
    symbol,
    time,
    date,
    TRY_CAST(s.pnl as float) AS pnl,
    TRY_CAST(s.buySize as bigint) AS buySize,
    TRY_CAST(s.sellSize as bigint) AS sellSize,
    TRY_CAST(s.buyTotal as float) AS buyTotal,
    TRY_CAST(s.sellTotal as float) AS sellTotal
    INTO pnlDashboard
FROM simulation /* output trade simulation to PBI */

Alım satım simülasyonu için Power BI panosunda görselleştirilen alım satım sinyallerini gösteren grafik.

 Alım satım simülasyonu için bir Power BI panosunda kar ve zarar sonuçlarını gösteren grafik.

Summary

Bu makalede, Azure Stream Analytics'de orta derecede karmaşık bir sorguyla gerçekçi bir yüksek frekanslı ticaret modelinin nasıl uygulaneceği gösterilmektedir. Azure Stream Analytics yerleşik doğrusal regresyon işlevi içermediğinden model beş yerine iki giriş değişkeni kullanır. Ancak JavaScript UDA'ları olarak daha yüksek boyutlara sahip daha gelişmiş algoritmalar da uygulayabilirsiniz.

Sorgu geliştirme, test etme ve hata ayıklama için Visual Studio Code için Azure Stream Analytics araçlarını kullanarak JavaScript UDA dışında sorgunun çoğunu test edebilir ve hatalarını ayıklayabilirsiniz.