Die Stromnetzhandelsstrategie
(www.fmz.com)
Die Grundidee des Grid-Tradings ist sehr einfach. Statt einen Handel zu platzieren, platzieren wir mehrere Trades, die ein Rastermuster bilden. Normalerweise werden diese als
Was ist Netzhandel und wie funktioniert er? Grid-Trading ist ein Spiel mit der Marktvolatilität. Es gibt zwei Gründe, warum es von den Händlern bevorzugt wird.
Zweitens funktioniert es gut auf volatilen Märkten, wo es keinen klaren Trend gibt.
Grid-Trading ist eine Art von technischer Analyse, die auf Bewegung innerhalb bestimmter Grid-Muster basiert. Grid-Trading ist im Devisenhandel beliebt. Insgesamt versucht die Technik, die normale Preisvolatilität in den Märkten zu nutzen, indem Kauf- und Verkaufsaufträge in bestimmten regelmäßigen Abständen über und unter einem vordefinierten Basispreis platziert werden. Solche Kauf- und Verkaufsaufträge, die im Allgemeinen in 10 oder 15 Einheiten von Intervallen verteilt sind, schaffen ein Handelsgrid.
Gitter kann die Richtung anpassen
Grundlegender Handel: zuerst kaufen und dann verkaufen.
Das Raster beginnt, Kaufbestellungen zu einem Preis zu senden, der unter dem ersten Preis liegt, dem Preis, der vom ersten Preis gefolgt ist (zweiter letzter Kaufpreis, dritter letzter Kaufpreis... usw.). Jeder Kaufbefehl wird durch den
Nach Abschluss einer Kaufbestellung wird das Programm auf der Grundlage des Kaufpreises sein, fügen Sie den Preis des
Erst kurz verkaufen und dann kaufen, um sich zu decken: das Gegenteil der Situation
Das größte Risiko dieser Strategie besteht darin, wenn sich der Markttrend einseitig bewegt und die Preisschwankungen das Netz überschreiten.
Der folgende Code hat das Raster mit automatischem Stoppverlust und Bewegungsfunktion erstellt.
Anmerkungen:
Die Strategie verwendet ein virtuelles Ausstehendes Auftragsdesign, das eine große Menge Verarbeitung für die Börse zur Verfügung stellt, um die Anzahl der ausstehenden Aufträge zu begrenzen, und löst das Problem flexibel.
Die Rasterlogik ist flexibel gestaltet und intelligent aufgebaut.
Profit-und-Loss-Berechnung, jeder numerische statistische Algorithmus kann als Referenz verwendet werden, und jeder Zustand Detektion Design ist streng. (für die Möglichkeit von BUG zu minimieren)
Der Quellcode ist es wert, gelernt zu werden.
Weitere Informationen finden Sie unter:
https://www.fmz.com/strategy/112633
Quelle:
// Quelle: /* Schnittstellenparameter (im Code als globale Variablen angezeigt) OpType Gitterrichtung Dropdown-Box (gewählt) Kaufen zuerst und dann verkaufen. FirstPriceAuto Anfangspreis automatisch Boolean (wahr/falsch) wahr Erster Preis@!Erster PreisAuto Anfangspreis numerisch (Nummer) 100 AllNummer Gesamtzahl numerische (Nummer) 10 Preissystem Preisintervall numerisch (Nummer) 1 Preisdifferenz numerische Differenz (Nummer) 2 BetragTyp Bestellgröße Dropdown-Box (gewählt) Kaufen und verkaufen Sie die gleiche Menge SummeOnce@AmountType==0 Einmalige Transaktionsmenge numerisch (Nummer) 0,1 BAmountOnce@AmountType==1 Bestellgröße numerische (Nummer) 0.1 SAmountOnce@AmountType==1 Verkaufsbestellungsgröße (Nummer) 0,1 QuantityCoefficient@AmountType==0 Mengenunterschied Zeichenfolge (Zeilenfolge) *1 QuantityDot Die Zahl mit dem Dezimalpunkt (Nummer) 3 AktivierenProtectDiff Aktivieren des Spread-Schutzes Boolean (true/false) falsch ProtectDiff@EnableProtectDiff Einstiegsspread Preisschutz numerisch (Nummer) 20 CancelAllWS stop annulliert alle ausstehenden Aufträge Boolean (true/false) true CheckInterval Zahl des Wahlintervalls (Nummer) 2000 Intervallfehler Wiederversuchsintervall (Nummer) 1300 RestoreProfit stellt den letzten Gewinn wieder her Boolean (true/false) false LastProfit@RestoreProfit Letzter Gewinn (Nummer) 0 ProfitAsOrg@RestoreProfit Letzter Gewinn, der als Durchschnittspreis gezählt wird Boolean (true/false) false AktivierenAccountCheck Aktivieren Sie die Bilanzüberprüfung Boolean (true/false) true AktivierenStopLoss@AktivierenAccountCheck öffnen Stop Loss Boolean (true/false) falsch StopLoss@EnableStopLoss maximaler schwebender Verlust (Nummer) 100 StopLossMode@EnableStopLoss Post-Stop-Loss-Operation Dropdown-Box (gewählt) Recycling und Ausgang EnableStopWin@EnableAccountCheck Aktivieren von Take Profit Boolean (wahr/falsch) falsch StopWin@EnableStopWin Maximaler variabler Gewinn Nummer (Nummer) 120 StopWinMode@EnableStopWin nach Gewinngewinn-Operation Dropdown-Box (gewählt) Recycling und Ausgang AutoMove@EnableAccountCheck AutoMove Boolean (wahr/falsch) falsch MaxDistance@AutoMove Höchstdistanz (Nummer) 20 MaxIdle@AutoMove maximale Leerlaufzeit (Sekunden) numerische (Nummer) 7200 EnableDynamic Dreht an dynamischen ausstehenden Aufträgen an Boolean (true/false) false DynamicMax@EnableDynamic Order Ablaufdistanz Nummer (Nummer) 30 ResetData löscht alle Daten beim Starten Boolean (true/false) true Präzisionspreis (Nummer) 5 */
Funktion hasOrder ((Orders, orderId) { // Überprüfen Sie, ob in Parameterordnungen eine Bestellung mit Order-ID vorhanden ist für (var i = 0; i < orders.length; i++) { // Überqueren Sie Befehle, um zu überprüfen, ob es gleiche IDs gibt, wenn es gibt, dann geben Sie true zurück wenn (Orders[i].Id == orderId) { zurückkehren true; - Ich weiß. - Ich weiß. return false; // Alle durchlaufen, kein Auslöser, wenn bedeutet, die Reihenfolge mit der ID-OrderId nicht gefunden haben, return false - Ich weiß.
Funktion annulPending() { // Alle ausstehenden Auftragsfunktionen stornieren VAR RET = FALSE; // Variablen für die Erfolgsmarkierung zurücksetzen while (true) { // während der Schleife wenn (ret) { // Wenn ret wahr ist dann Schlaf für eine bestimmte Zeit Schlaf ((Intervall); - Ich weiß. Var orders = _C(exchange.GetOrders); // Ruf die API an, um die Auftragsinformationen zu erhalten, die der Austausch nicht ausgeführt hat. wenn (orders.length == 0) { // Wenn ein leeres Array zurückgegeben wird, hat der Austausch keine nicht ausgeführten Aufträge. Break; // Aus der While-Schleife springen - Ich weiß.
for (var j = 0; j < orders.length; j++) { // Traverse the unfinished order array and use orders[j].Id one by one to cancel the order based on the index j.
exchange.CancelOrder(orders[j].Id, orders[j]);
ret = true; // Once there is a cancel operation, ret is assigned a value of true. Used to trigger above Sleep, wait for re-exchange.GetOrders detection
}
}
return ret; // return ret
}
FunktionswerteToString(Werte, pos) { // Wert in eine Zeichenfolge umgewandelt
Var-Ergebnis =
Funktion Trader() { // Trader-Funktion, die Schließungen verwendet.
VAR vId = 0; // Auftragsinkrement ID
VAR OrderBooks = []; // Auftragsbuch
Var hisBooks = []; // Historische Reihenfolge
Var orderBooksLen = 0; // Länge des Auftragsbuchs
this.Buy = Funktion ((Preis, Betrag, Extra) { // Kauffunktion, Parameter: Preis, Menge, erweiterte Informationen
wenn (typeof(extra) ===
wenn (orders[i].Id == order.Id) { // Wenn Sie eine Bestellung mit derselben Order-ID in orderBooks finden, geben Sie einen Wert von true zu finden, was finden bedeutet.
gefunden = wahr;
Break; // Aus der aktuellen Schleife springen
- Ich weiß.
- Ich weiß.
wenn (!found) { // Wenn nicht gefunden, drücken Sie orderBooks[orderId] auf Orders.
orders.push ((orderBooks[orderId]); // Warum wollen Sie so drücken?
- Ich weiß.
- Ich weiß.
Rückgabeaufträge; // Rückgabeaufträge
- Ich weiß.
Das hier.GetOrder = Funktion ((orderId) { // Order erhalten
wenn (typeof(orderId) ===
var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Assign the corresponding API function reference to pfn according to the type of the order.
// That is, if the order type is a buy order, pfn is a reference to the exchange.Buy function, the same as the sell order.
if (order.Id == 0 && diff <= priceDiff) { // If the order order in the order book is not activated (ie Id is equal to 0) and the current price is less than or
// equal to the order plan price, the priceDiff passed in the parameter.
var realId = pfn(order.Price, order.Amount, order.Extra + "(distance: " + diff + (order.Type == ORDER_TYPE_BUY ? (" ask price: " + ticker.Buy) : (" bid price: " + ticker.Sell))+")");
// Execute order function, parameter passing price, quantity, order extension information + pending order distance + market data (ask price or bid price), return exchange order id
if (typeof(realId) === 'number') { // If the returned realId is a numeric type
order.Id = realId; // Assign the Id attribute of the current order order to the order book.
}
} else if (order.Id > 0 && diff > (priceDiff + 1)) { // If the order is active and the current distance is greater than the distance passed in by the parameter
var ok = true; // Declare a variable for tagging Initially set true
do { // Execute "do" first and then judge while
ok = true; // Ok assign true
exchange.CancelOrder(order.Id, "unnecessary" + (order.Type == ORDER_TYPE_BUY ? "buying" : "selling"), "placed order price:", order.Price, "volume:", order.Amount, ", distance:",
diff, order.Type == ORDER_TYPE_BUY ? ("ask price: " + ticker.Buy) : ("bid price: " + ticker.Sell));
// Cancel the pending order that is out of range. After canceling the order, print the current order information and the current distance diff.
Sleep(200); // Wait 200 milliseconds
orders = _C(exchange.GetOrders); // Call the API to get an uncompleted order in the exchange.
for (var i = 0; i < orders.length; i++) { // Traverse these unfinished orders.
if (orders[i].Id == order.Id) { // If the cancelled order is found in the list of orders that have not been completed by the exchange
ok = false; // Assign ok this variable to false, that is, no cancellation is successful.
}
}
} while (!ok); // If ok is false, then !ok is true and while will continue to repeat the loop, continue to cancel the order,
// and check if the cancellation is successful.
order.Id = 0; // Assigning a value of 0 to order.Id means that the current order is inactive.
}
}
};
}
Funktion BalanceAccount (orgAccount, initAccount) { // Balance Account Function Parameter Initial account information when the strategy is started (Initielle Kontoinformation, wenn die Strategie gestartet wird)
Call the custom function cancelPending() to cancel all pending orders (Call die benutzerdefinierte Funktion cancelPending() um alle ausstehenden Bestellungen zu stornieren.
Variable nowAccount = _C ((exchange.GetAccount); // Declare a variable nowAccount to record the latest information about the account at the moment. Die Variable nowAccount wird von einem anderen Variablen verwendet, um die neuesten Informationen über das Konto zu erfassen.
// Set the slip price when placing the order as 0.2 Das Slip-Preis wird bei der Platzierung des Auftrags als 0.2 festgelegt.
Variable war initially set true.
while (true) { // während Loop
Der Unterschied zwischen dem aktuellen Konto und dem anfänglichen Konto wird berechnet.
Wenn der absolute Wert der Währungsdifferenz kleiner ist als das minimale Transaktionsvolumen der Börse, dann ist die Währungsdifferenz der Währungsdifferenz, wenn der absolute Wert der Währungsdifferenz kleiner ist als das minimale Transaktionsvolumen der Börse, dann ist die Währungsdifferenz der Währungsdifferenz kleiner als das minimale Transaktionsvolumen der Börse.
// der Break springt aus der Schleife und führt keine Balancing Operationen durch.
Ich bin nicht derjenige.
Wir sind hier.
VAR DEEPTH = _C (exchange.GetDepth); // Get the exchange depth information Zuordnen Sie die erklärte Tiefe-Variable
VAR books = diff > 0? depth.Bids : depth.Asks; // According the difference of the currency is greater than 0 or less than 0, extract the buy order array or
// sell order array in depth (gleich 0 wird nicht verarbeitet, es wird gebrochen, wenn es als weniger als GetMinStock beurteilt wird)
// Die Differenz zwischen den Coins ist größer als 0 um den Saldo zu verkaufen, also schauen Sie sich das Buy-Order-Array an,
// die Differenz zwischen den Münzen ist weniger als 0 ist das Gegenteil.
Das ist der Punkt, an dem die Angabe n initial 0 ist.
Der Preis ist 0;
for (var i = 0; i < books.length; i++) { // Traversing the buy or sell order array
n += books[i].Amount; // Accumulate Amount (order quantity) for each order based on the index i traversed Die Anzahl der Bücher, die ich bestelle
if (n >= Math.abs ((diff)) { // If the cumulative order quantity n is greater than or equal to the currency difference, then: Wenn die kumulative Ordermenge n größer oder gleich der Währungsdifferenz ist, dann:
price = books[i].Price; // Get the price of the current indexed order, assign it to price (Erhalten Sie den Preis der aktuellen indizierten Bestellung und geben Sie ihn dem Preis zu)
break; // Jump out of the current for traversal cycle (Springen Sie sich aus dem Strom für den Durchlaufzyklus)
Wir sind hier.
Wir sind hier.
- Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn. - Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn. - Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn. - Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn
// basierend auf der Währungsdifferenz größer als 0 oder kleiner als 0
Der Betrag der Order, die ausgeglichen werden soll, ist diff, die Differenz in der Währung, zugewiesen an die erklärte Betrag variable.
(Price + slidePrice); // The direction of buying and selling according to the difference in the currency, increase or decrease the difference in the currency Die Richtung des Kaufs und Verkaufs entsprechend der Differenz in der Währung, increase or decrease the
// Slip price based on the price (Slip price is to make it easier to trade), und dann zuordnen Sie es zum Preis
Log ((
var STATE_WAIT_OPEN = 0; // Wird für den Zustand jedes Knoten in der fishTable verwendet Die Daten werden von den zuständigen Behörden des Mitgliedstaats übermittelt. Die Daten werden in der Tabelle aufgeführt. var ProfitCount = 0; // Gewinn- und Verlustrechnung Var BuyFirst = true; // Anfangsparameter der Schnittstelle var IsSupportGetOrder = true; // bestimmen Sie den Austausch der GetOrder API-Funktion, einer globalen Variablen, die zum Beginn der Hauptfunktion verwendet wird var LastBusy = 0; // Das letzte verarbeitete Zeitobjekt aufgezeichnet
Funktion setBusy() { // Setze Busy Zeit LastBusy = new Date(); // LastBusy dem aktuellen Zeitobjekt zuweisen - Ich weiß.
Funktion isTimeout() { // Bestimmen, ob es Zeit abläuft wenn (MaxIdle <= 0) { // Maximale Leerlaufzeit (je nachdem, ob das Gitter automatisch verschoben wird), // wenn die maximale Leerlaufzeit MaxIdle kleiner oder gleich 0 ist return false; // Gibt false zurück, beurteilt nicht den Timeout. Das heißt, immer false ohne Timeout zurück. - Ich weiß. Var now = new Date ((); // Erhalten Sie das aktuelle Zeitobjekt wenn (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { // Verwenden Sie die Funktion getTime des aktuellen Zeitobjekts, um den Zeitstempel und den Zeitstempel von LastBusy zu erhalten, um den Unterschied zu berechnen, // Teilen Sie durch 1000, um die Anzahl der Sekunden zwischen den beiden Zeitobjekten zu berechnen. // Bestimmen Sie, ob es größer ist als die maximale Leerlaufzeit MaxIdle LastBusy = jetzt; // Wenn es größer ist als, aktualisieren LastBusy zum aktuellen Zeitobjekt jetzt return true; // Gibt true zurück, was ein Timeout ist. - Ich weiß. zurückkehren false; // zurückkehren false no timeout - Ich weiß.
Funktion onexit() { // Die Schließfunktion, wenn das Programm beendet wird.
wenn (CancelAllWS) { // Um alle ausstehenden Bestellungen zu stornieren, rufen Sie cancelPending ((() an, um alle ausstehenden Bestellungen zu stornieren.
Log ((
Funktion Fischerei ((orgZahl, FischZahl) { // Gießparameter: Kontoinformationen, Anzahl der Gießen
setBusy(); // LastBuys auf den aktuellen Zeitstempel setzen
var account = _C(exchange.GetAccount); // Deklarieren Sie eine Kontovariable, um die Informationen zum aktuellen Konto zu erhalten und zuzuweisen.
Log ((account); // Ausgabe der Kontoinformationen zu Beginn des Anrufs an die Fischereifunktion.
War InitAccount = Konto; // Deklarieren Sie eine Variable InitAccount und zuweisen Sie es mit Konto.
// dieses Gießen, verwendet, um schwebenden Gewinn und Verlust zu berechnen.
Var ticker = _C(exchange.GetTicker); // Erhalten Sie den Angabewert, der der angegebenen Ticker-Variablen zugeordnet ist
var amount = _N(AmountOnce); // Verwenden Sie _N, um die Dezimalstellen zu verarbeiten (_N ist standardmäßig 2 Bits) und zuweisen Sie diese an amount.
Var amountB = [amount]; // Eine Variable mit dem Namen amountB deklarieren ist ein Array, ein Element mit amount initialisieren
Var amountS = [betrag]; // Eine Variable mit dem Namen amountS deklarieren...
wenn (typeof(AmountType)!==
- Ich weiß.
// Fischtabelle initialisieren
VAR fishTable = {}; // Ein Gitterobjekt deklarieren
Var uuidTable = {}; // Objekt der Identifikationscode-Tabelle
Var needStocks = 0; // erforderliche Münzen variable
Var needMoney = 0; // Erforderliche Geldvariable
Var realNeedMoney = 0; // Eigentlich Geld benötigt
var actualNeedStocks = 0; // tatsächlich benötigte Münzen
var notEnough = false; // Unterfinanzierte Tag-Variable, ursprünglich auf false gesetzt
Var canNum = 0; // Verfügbares Gitter
für (var idx = 0; idx < AllNum; idx++) { // Die Struktur wird nach der Anzahl des Rasters AllNum durchlaufen.
VAR-PRICE = _N((BuyFirst? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid)), Präzision);
// Beim Durchqueren des Konstrukts wird die aktuelle Index-IDX-Preiseinstellung nach BuyFirst festgelegt.
needStocks += amountS[idx]; // Die Anzahl der verkauften Münzen wird im Zyklus allmählich angesammelt.
needMoney += Preis * BetragB[idx]; // Der Geldbetrag, der zum Kauf benötigt wird, wird im Zyklus allmählich angesammelt.
wenn (BuyFirst) { // Handling kaufen zuerst
wenn (_N(bedarfGeld) <= _N(Konto.Guthaben)) { // Wenn das Netz weniger Geld benötigt als der auf dem Konto verfügbare Geldbetrag
realNeedMondy = needMoney; // dem tatsächlichen Geldbetrag zugeordnet
realNeedStocks = needStocks; // Zuweisung an die tatsächliche Anzahl der benötigten Münzen.
canNum++; // Kumulative Anzahl der verfügbaren Gitter
} else { // _N(needMoney) <= _N(account.Balance) Wenn diese Bedingung nicht erfüllt ist, wird die Variable "underfunded" auf "true" gesetzt.
notEnough = wahr;
- Ich weiß.
{ \ cH00FFFF } sonst { \ cH00FFFF } Handling verkaufen zuerst
wenn (_N(bedarfStocks) <= _N(account.Stocks)) { // Überprüfen Sie, ob die erforderliche Anzahl von Münzen kleiner ist als die Anzahl der auf dem Konto verfügbaren Münzen
realNeedMondy = needMoney; // Zuweisung
realNeedStocks = needStocks
canNum++; // Kumulative Anzahl der verfügbaren Gitter
- Nein.
notEnough = true; // Wenn die Finanzierungsbedingungen nicht erfüllt sind, wird true gesetzt
- Ich weiß.
- Ich weiß.
fishTable[idx] = STATE_WAIT_OPEN; // Nach dem aktuellen Index idx den Status des idx-Mitglieds (Gitterknoten) des Gitterobjekts festlegen,
// zunächst STATE_WAIT_OPEN (Wartet auf die Öffnung der Position)
uuidTable[idx] = -1; // Das nummerierte Objekt initialisiert auch seinen eigenen idx-Wert (den Knoten, der dem fishTable entspricht) auf -1 basierend auf der aktuellen idx.
- Ich weiß.
wenn (!EnableAccountCheck && (canNum < AllNum)) { // Wenn die Überprüfung der Mittel nicht aktiviert ist, und die Anzahl der Gitter (die Gesamtzahl der Knoten), bei denen der Knoten kleiner ist
// als die Interface-Parameter-Einstellung geöffnet werden kann.
Log ((
Werfen
var trader = new Trader(); // Constructs a Trader object, assigning it to the trader variable declared here.
var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; // According to whether to buy and sell first, set the open function OpenFunc to refer to exchange.Buy or exchange.Sell
var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; // same as above
if (EnableDynamic) { // Set OpenFunc/CoverFunc again according to whether the interface parameter EnableDynamic is enabled.
OpenFunc = BuyFirst ? trader.Buy : trader.Sell; // The member function Buy that references the trader object is used for dynamic pending orders (mainly because
// some exchanges limit the number of pending orders, so virtual dynamic pending orders are required)
CoverFunc = BuyFirst ? trader.Sell : trader.Buy; // same as above
}
var ts = new Date(); // Create a time object at this time (assigned to ts) to record the time at the moment.
var preMsg = ""; // Declare a variable to record the last message, the initial set to empty string
var profitMax = 0; // Maximum return
while (true) { // The main logic after the grid is casted
var now = new Date(); // Record the time when the current cycle started
var table = null; // Declare a variable
if (now.getTime() - ts.getTime() > 5000) { // Calculate whether the difference between the current time now and the recorded time ts is greater than 5000 milliseconds
if (typeof(GetCommand) == 'function' && GetCommand() == "Receiving grid") { // Check if the strategy interaction control command "receives the grid" is received,
// stops and balances to the initial state.
Log("Start executing commands to perform grid operations"); // Output information
balanceAccount(orgAccount, InitAccount); // Perform a balancing function to balance the number of coins to the initial state
return false; // This time the grid function is fishing and return false
}
ts = now; // Update ts with current time now for next comparison time
var nowAccount = _C(exchange.GetAccount); // Declare the nowAccount variable and initially been set as the current account information.
var ticker = _C(exchange.GetTicker); // Declare the ticker variable and initially been set as the current market information.
if (EnableDynamic) { // If you enable dynamic pending orders
trader.Poll(ticker, DynamicMax); // Call the Poll function of the trader object to detect and process all orders based on the
// current ticker market and the interface parameter DynamicMax.
}
var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); // Calculate the current coin difference
var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); // Calculate the current money difference
var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); // Calculate the current floating profit and loss of this time of casting grid
var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks
- orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
// Calculate the overall floating profit and loss
var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); // If the absolute value of the coin difference at this moment is greater than the minimum trading
// volume of the exchange, it means that the position has been held.
if (isHold) { // If you have already held a position, execute the setBusy() function, which will update the LastBusy time.
setBusy(); // That is, after opening the position, the opening of the opening mechanism is started.
}
profitMax = Math.max(floatProfit, profitMax); // Refresh the maximum floating profit and loss
if (EnableAccountCheck && EnableStopLoss) { // If you initiate account detection and start a stop loss
if ((profitMax - floatProfit) >= StopLoss) { // If the maximum floating profit or loss minus the current floating profit or loss is greater than or equal to
// the maximum floating loss value, execute the code inside the curly braces
Log("Current floating profit a