diff --git a/Projects/Superalgos/Schemas/Docs-Topics/order-management-003-opening-orders.json b/Projects/Superalgos/Schemas/Docs-Topics/order-management-003-opening-orders.json new file mode 100644 index 000000000..e8a642c7c --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/order-management-003-opening-orders.json @@ -0,0 +1,227 @@ +{ + "topic": "Order Management", + "pageNumber": "3", + "type": "Opening Orders", + "definition": { + "text": "Several calculations and validations are required before creating and placing an order.", + "updated": 1610219973766 + }, + "paragraphs": [ + { + "style": "Text", + "text": "Before creating an order, a few calculations to determine what the order should look like are required, in particular about the rate of the order (see Calculate Order Rate) and the size of the order (see Calculate Order Size).", + "updated": 1610219986275 + }, + { + "style": "Text", + "text": "Once the calculations are done, some validations are in order." + }, + { + "style": "Text", + "text": "The size of an order may not be negative." + }, + { + "style": "Javascript", + "text": "(tradingEngineOrder.orderBaseAsset.size.value <= 0)\n(tradingEngineOrder.orderQuotedAsset.size.value <= 0)", + "updated": 1610220014592 + }, + { + "style": "Callout", + "text": "If previous checks pass and it is a forward testing or live trading session, the order is placed at the exchange. If it is a backtesting or paper trading session, the order exists in the data structure of the trading engine only." + }, + { + "style": "Text", + "text": "If the order is placed successfully, then all related data structures in the trading engine are updated accordingly, including size placed for the stage in both assets, episode counters, and the particular order’s details." + }, + { + "style": "Title", + "text": "Calculate Order Rate" + }, + { + "style": "Text", + "text": "The first thing to consider to determine the rate of the order is whether it is a limit or a market order." + }, + { + "style": "Text", + "text": "Limit orders must have a proper definition of the order rate. That is, the order rate node must have a formula that results in a number, and that is greater than zero. If all validations pass, the order rate is stored in tradingEngineOrder.rate.value." + }, + { + "style": "Text", + "text": "For market orders, there is no definition of the rate, as the rate is whatever rate the order fills at the exchange. The initial value is therefore the last known market rate, that is, the rate of the last closed candle: ", + "updated": 1610220046300 + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.rate.value = tradingEngine.current.episode.candle.close.value", + "updated": 1610220056132 + }, + { + "style": "Title", + "text": "Calculate Order Size" + }, + { + "style": "Text", + "text": "The calculation of the size of the order is a bit more elaborate, as several things must be taken into account, with the added intricacy that the user may define the target size for the stage in the base asset or the quoted asset." + }, + { + "style": "Text", + "text": "The three main steps to define the size are the following:" + }, + { + "style": "List", + "text": "To start with, the definitions regarding the size of the order must be valid (see Required Configuration Validation)." + }, + { + "style": "List", + "text": "Then, the size of the order added to the rest of the orders that may have been placed before must not be greater than the target size for the stage (see Not Passing Target Size Validation)." + }, + { + "style": "List", + "text": "Finally, the size of the order must not leave any of the assets in the trading engine’s built-in accounting system with a negative balance (see Not Negative Balance Validation)." + }, + { + "style": "Subtitle", + "text": "Required Configuration Validation" + }, + { + "style": "Text", + "text": "Beyond the target size for the stage, the user produces two more definitions that affect what the order size should be for the particular order: at the level of the execution algorithm’s configuration (percentageOfStageTargetSize parameter) and the level of the order’s configuration (percentageOfAlgorithmSize parameter). Both of these definitions must be valid and numeric." + }, + { + "style": "Text", + "text": "Once the corresponding checks pass, the size of the algorithm is determined as per the definitions:" + }, + { + "style": "Javascript", + "text": "algorithmSizeInBaseAsset =\ntradingEngineStage.stageBaseAsset.targetSize.value *\nexecutionAlgorithm.config.percentageOfStageTargetSize / 100", + "updated": 1610220102815 + }, + { + "style": "Text", + "text": "… and…" + }, + { + "style": "Javascript", + "text": "algorithmSizeInQuotedAsset = \ntradingEngineStage.stageQuotedAsset.targetSize.value *\nexecutionAlgorithm.config.percentageOfStageTargetSize / 100", + "updated": 1610220138568 + }, + { + "style": "Note", + "text": "Notice that it is assumed that the target size for the stage is defined both in base asset and the quoted asset. This is because, although the user defines the target size in one asset only, the system converts the definition to the other asset (at an earlier moment), to keep track of accounts on both assets at all times, which is a design requirement.", + "updated": 1610220163303 + }, + { + "style": "Title", + "text": "Not Passing Target Size Validation" + }, + { + "style": "Text", + "text": "This validation requires handling two possible scenarios separately. Did the user define the target size for the stage in base asset or the quoted asset?" + }, + { + "style": "Note", + "text": "The system discriminates both scenarios to remain faithful to the intent of the definitions. This is a design feature throughout the system, and it is at the core of allowing maximum flexibility, so that users may use trading systems in various ways to achieve different goals.", + "updated": 1610220186307 + }, + { + "style": "Subtitle", + "text": "Stage size defined in base asset" + }, + { + "style": "Text", + "text": "If the stage size was defined in base asset, then the size of the order derives from the definitions that where validated in the previous step (see Required Configuration Validation):" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.size.value =\nalgorithmSizeInBaseAsset *\ntradingSystemOrder.config.percentageOfAlgorithmSize / 100", + "updated": 1610220217663 + }, + { + "style": "Text", + "text": "With the above value, the validation is run to determine if the combined sizes of all orders placed up to this point would be larger than the size defined for the stage. Remember that the size defined for the stage is enforced as a cap. If the defined order size does exceed the stage size limit, then the size is lowered to fit the limit. The re-sizing goes out with a warning, to let the user know why the resizing took place." + }, + { + "style": "Text", + "text": "Once the order size in base asset is final, then the size in quoted asset may be determined multiplying the size in base asset by the order rate determined earlier:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.size.value =\ntradingEngineOrder.orderBaseAsset.size.value *\ntradingEngineOrder.rate.value", + "updated": 1610220243415 + }, + { + "style": "Subtitle", + "text": "Stage size defined in quoted asset" + }, + { + "style": "Text", + "text": "Similarly, in this case the size of the order in quoted asset derives directly from the definitions:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.size.value =\nalgorithmSizeInQuotedAsset *\ntradingSystemOrder.config.percentageOfAlgorithmSize / 100", + "updated": 1610220273076 + }, + { + "style": "Text", + "text": "The same validation is run as with the base asset, and the size of the order in base asset is also determined at the end:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.size.value =\ntradingEngineOrder.orderQuotedAsset.size.value /\ntradingEngineOrder.rate.value", + "updated": 1610220292334 + }, + { + "style": "Title", + "text": "Not Negative Balance Validation" + }, + { + "style": "Text", + "text": "The final validation is there to make sure that no balances become negative if the order is created with the currently defined size." + }, + { + "style": "Subtitle", + "text": "Buy orders" + }, + { + "style": "Text", + "text": "For buy orders (both market and limit), the quoted asset balance minus the order size must be equal to or greater than zero." + }, + { + "style": "Javascript", + "text": "tradingEngine.current.episode.episodeQuotedAsset.balance.value -\ntradingEngineOrder.orderQuotedAsset.size.value => 0", + "updated": 1610220335526 + }, + { + "style": "Text", + "text": "If not, the size of the order is redefined to fit the available balance. The resizing goes out with a warning." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.size.value =\ntradingEngine.current.episode.episodeQuotedAsset.balance.value", + "updated": 1610220358264 + }, + { + "style": "Text", + "text": "And, remember, every time a property changes for one asset, the same property for the other asset must be updated as well:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.size.value =\ntradingEngineOrder.orderQuotedAsset.size.value /\ntradingEngineOrder.rate.value", + "updated": 1610220378073 + }, + { + "style": "Subtitle", + "text": "Sell orders" + }, + { + "style": "Text", + "text": "For market and limit sell orders, the validation is reversed, checking the balance of the base asset instead of the quoted asset." + }, + { + "style": "Note", + "text": "Remember that a sell order always exchanges the base asset for the quoted asset and a buy order does the opposite.", + "updated": 1610220400837 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/order-management-004-maintaining-live-orders.json b/Projects/Superalgos/Schemas/Docs-Topics/order-management-004-maintaining-live-orders.json new file mode 100644 index 000000000..af004ef1a --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/order-management-004-maintaining-live-orders.json @@ -0,0 +1,37 @@ +{ + "topic": "Order Management", + "pageNumber": "4", + "type": "Maintaining Live Orders", + "definition": { + "text": "Orders at the exchange are monitored on every execution to discover the size filled, rates, and other exchange events. Also, the trading bot synchronizes Superalgos with the real transactional information handled by the exchange.", + "updated": 1610220454133 + }, + "paragraphs": [ + { + "style": "Text", + "text": "As hinted in the Overview of the Management Issue page, there are two different paths for maintaining orders. The pages in this section describe the maintenance of real orders sent to the exchange, as opposed to simulated orders that live within Superalgos only.", + "updated": 1610220513296 + }, + { + "style": "Text", + "text": "The maintenance of orders involves a series of tasks that deal with three main concerns:" + }, + { + "style": "List", + "text": "Checking the orders at the exchange, mainly to find out whether they have been filled or not, what size of the order was filled, and at what rate. We also need to know if the order has been arbitrarily canceled, either by the user or the exchange itself." + }, + { + "style": "List", + "text": "Synchronizing the information existing in Superalgos with the actual happenings at the exchange. The original information Superalgos has about orders derive from definitions, but what happens at the exchange is what truly matters." + }, + { + "style": "List", + "text": "Cancelling orders whenever the trading system’s definitions indicate so." + }, + { + "style": "Success", + "text": "It is highly recommended to read these pages and compare with the simulated version of order maintenance. The comparison will greatly help you understand the differences between backtesting or paper trading and live trading sessions.", + "updated": 1610220471695 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/order-management-005-checking-exchange-events.json b/Projects/Superalgos/Schemas/Docs-Topics/order-management-005-checking-exchange-events.json new file mode 100644 index 000000000..9b42dea65 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/order-management-005-checking-exchange-events.json @@ -0,0 +1,163 @@ +{ + "topic": "Order Management", + "pageNumber": "5", + "type": "Checking Exchange Events", + "definition": { + "text": "The trading bot monitors exchange orders to check their status analyzing multiple possible scenarios.", + "updated": 1610220643629 + }, + "paragraphs": [ + { + "style": "Text", + "text": "For forward testing and live trading sessions, the state of orders at the exchange is checked on every execution of the trading bot.", + "updated": 1610220673347 + }, + { + "style": "Text", + "text": "It’s important to note that, when an order is placed, no relevant information is obtained from the exchange other than a confirmation that the order was received. The trading bot must ask the exchange for the status of the order some time after placing it." + }, + { + "style": "Note", + "text": "The trading bot places the order during the second execution cycle and asks the exchange about the order in the next run of the bot, during the first execution cycle. This means that the order is checked one unit of the trading session’s time frame after the order is placed. For example, if the session is running on the 01-min time frame, the order is checked roughly one minute after it is placed.", + "updated": 1610220684415 + }, + { + "style": "Text", + "text": "When the trading bot fetches an order from the exchange, it gets the order information in a text message. What does the trading bot obtain from the exchange?" + }, + { + "style": "Text", + "text": "This is an important question, as the answer conditions what the trading bot may or may not do with each order, and how it may keep a reliable internal accounting system." + }, + { + "style": "Title", + "text": "Orders According to the Exchange", + "updated": 1610220706175 + }, + { + "style": "Text", + "text": "What follows are several examples including a market sell order, a market buy order, a limit sell order, and a limit buy order, all of them in the BTC/USDT market in Binance." + }, + { + "style": "Note", + "text": "Notice that the body section is provided by the CCXT library, and is the same for all exchanges; the info section is provided by the exchange itself, and may vary across exchanges.", + "updated": 1610220717780 + }, + { + "style": "Subtitle", + "text": "Market sell order for 0.1 BTC", + "updated": 1610220735916 + }, + { + "style": "Json", + "text": "Body: \naverage:12930.92\nclientOrderId:\"eLAkNrEoMw3erEp8AeaiTT\"\ncost:1293.24717104\ndatetime:\"2020-10-24T08:47:43.104Z\"\nfee:undefined\nfilled:0.100012\nid:\"3420506109\"\nlastTradeTimestamp:undefined\nprice:12930.92\nremaining:0\nside:\"sell\"\nstatus:\"closed\"\nsymbol:\"BTC/USDT\"\ntimestamp:1603529263104\ntrades:undefined\ntype:\"market\"\n\nInfo: \norderId:3420506109\norderListId:-1\norigQty:\"0.10001200\"\norigQuoteOrderQty:\"1293.25000000\"\nprice:\"0.00000000\"\nside:\"SELL\"\nstatus:\"FILLED\"\nstopPrice:\"0.00000000\"\nsymbol:\"BTCUSDT\"\ntime:1603529263104\ntimeInForce:\"GTC\"\ntype:\"MARKET\"\nupdateTime:1603529263104", + "updated": 1610220759201 + }, + { + "style": "Subtitle", + "text": "Limit sell order for 0.1 BTC", + "updated": 1610220791496 + }, + { + "style": "Json", + "text": "Body: \namount:0.1\naverage:12976.74\nclientOrderId:\"iZbiUF9W1WiKmtMfhA8hIr\"\ncost:1297.674\ndatetime:\"2020-10-24T10:43:47.944Z\"\nfee:undefined\nfilled:0.1\nid:\"3420762036\"\nlastTradeTimestamp:undefined\nprice:12969.83\nremaining:0\nside:\"sell\"\nstatus:\"closed\"\nsymbol:\"BTC/USDT\"\ntimestamp:1603536227944\ntrades:undefined\ntype:\"limit\"\n\nInfo: \nexecutedQty:\"0.10000000\"\nicebergQty:\"0.00000000\"\nisWorking:true\norderId:3420762036\norderListId:-1\norigQty:\"0.10000000\"\norigQuoteOrderQty:\"0.00000000\"\nprice:\"12969.83000000\"\nside:\"SELL\"\nstatus:\"FILLED\"\nstopPrice:\"0.00000000\"\nsymbol:\"BTCUSDT\"\ntime:1603536227944\ntimeInForce:\"GTC\"\ntype:\"LIMIT\"\nupdateTime:1603536227944", + "updated": 1610220811097 + }, + { + "style": "Title", + "text": "Status checks", + "updated": 1610220854490 + }, + { + "style": "Text", + "text": "Once the status of the order is received as in one of the above examples, the trading bot performs multiple checks, each leading to particular actions. The following are the particular cases analyzed and the actions taken." + }, + { + "style": "Subtitle", + "text": "Filled and closed" + }, + { + "style": "Text", + "text": "If the order is filled and closed, the corresponding data structures in the trading engine are updated to indicate so." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.status.value = 'Closed'\ntradingEngineOrder.exitType.value = 'Filled'", + "updated": 1610220873457 + }, + { + "style": "Text", + "text": "But, most importantly, the details in the order are processed to synchronize the information in the trading engine—at this point consisting mostly of information derived from the definitions in the trading system—with the information obtained from the exchange." + }, + { + "style": "Text", + "text": "The data structures to be updated are mostly those related to the actual rate at which the order was filled, the actual size that was filled, the actual fees that were charged, and how those variables affect balances and the overall accounts in various contexts (order, stage, position, episode, etc.)." + }, + { + "style": "Note", + "text": "Notice that definitions in the trading system are—in a way—just a plan. Your definitions tell the trading bot what to do, but there is no certainty on the outcome. That is the reason why the first set of accounts recorded with information derived from the trading system needs to be synchronized in every execution cycle with what actually happened at the exchange until the order is closed.", + "updated": 1610220886259 + }, + { + "style": "Text", + "text": "The calculations involved in the synchronization process are covered in Syncing With the Exchange.", + "updated": 1610221145905 + }, + { + "style": "Subtitle", + "text": "Partially filled and closed" + }, + { + "style": "Text", + "text": "If the order is partially filled and closed, the corresponding data structures in the trading engine are updated to indicate so." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.status.value = 'Closed'\ntradingEngineOrder.exitType.value = 'Closed at the Exchange'", + "updated": 1610220905601 + }, + { + "style": "Text", + "text": "For a limit order to be closed while partially filled, it must be closed manually by the user directly at the exchange, or forcefully closed by the exchange itself, for whatever reason. The system handles such occurrences so that they do not disrupt the trading session or the accounts at Superalgos." + }, + { + "style": "Text", + "text": "The first thing to do with such an order is to update the size placed on the stage so that the stage accounts for the amount that was filled only, instead of the original size of the order (see Accounting)." + }, + { + "style": "Text", + "text": "And then, the same synchronization process described earlier must be applied as well (see Syncing With the Exchange).", + "updated": 1610221158590 + }, + { + "style": "Subtitle", + "text": "Cancelled" + }, + { + "style": "Text", + "text": "These are limit orders canceled by the trading bot upon the triggering of the cancel order event. In such cases, the exit type is set as follows:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.exitType.value = 'Cancelled at the Exchange'" + }, + { + "style": "Text", + "text": "Canceled orders go through the same processes of synchronization (see Syncing With the Exchange) and the recalculation of the size of the stage (see Accounting).", + "updated": 1610221173299 + }, + { + "style": "Subtitle", + "text": "All other instances" + }, + { + "style": "Text", + "text": "The cases described above refer to orders with particular characteristics. Orders that do not match any of the above criteria trigger the synchronization process described earlier (see Syncing With the Exchange).", + "updated": 1610221181661 + }, + { + "style": "Text", + "text": "" + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/order-management-006-syncing-with-the-exchange.json b/Projects/Superalgos/Schemas/Docs-Topics/order-management-006-syncing-with-the-exchange.json new file mode 100644 index 000000000..132fb8e93 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/order-management-006-syncing-with-the-exchange.json @@ -0,0 +1,303 @@ +{ + "topic": "Order Management", + "pageNumber": "6", + "type": "Syncing With the Exchange", + "definition": { + "text": "Syncing with the exchange involves calculating the actual size, the actual rate, the percentage filled, the fees paid, and the size filled, to update the trading engine data structure so that it matches with the actual situation of the order at the exchange.", + "updated": 1610221056957 + }, + "paragraphs": [ + { + "style": "Text", + "text": "The process of synchronizing the data in the trading engine with what actually happens at the exchange is crucial to monitoring and controlling a live trading operation from within Superalgos. It is this process that allows users to access the information at the exchange throughout the life cycle of each order, on the fly.", + "updated": 1610221245028 + }, + { + "style": "Text", + "text": "This is when all calculations involving the actual size, actual rate, actual fees, and so on are made. We will closely look into each of the calculations." + }, + { + "style": "Text", + "text": "Once the synchronization is done, the bot does the accounting (see Accounting), to keep the rest of the variables—like balances and the stage size—up to date with the reality of orders." + }, + { + "style": "Title", + "text": "Actual Size Calculation" + }, + { + "style": "Text", + "text": "While users may define the target size of the stage in either the base asset or the quoted asset, the size of orders is always denominated in the base asset, as per the CCXT Library API, and—likely—most exchange’s APIs." + }, + { + "style": "Note", + "text": "It is a common occurrence that exchanges change the size slightly, for whatever reason, including issues with the precision of decimal places, for example. This is why the size of the order as defined by the user may need to be updated, synchronizing it with the actual size determined by the exchange.", + "updated": 1610221270715 + }, + { + "style": "Text", + "text": "When the actual size of the order as reported by the exchange is different than the size defined by the user, the trading bot makes the adjustments described below." + }, + { + "style": "Subtitle", + "text": "Recalculate Actual Size" + }, + { + "style": "Text", + "text": "The actual size of the base asset is updated with the size reported by the exchange:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.actualSize.value = order.amount" + }, + { + "style": "Text", + "text": "Then it’s time to calculate the actual size in the quoted asset. At this stage, the actual rate of the order hasn’t been established yet, so the existing rate is used temporarily." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.actualSize.value =\ntradingEngineOrder.orderBaseAsset.actualSize.value *\ntradingEngineOrder.rate.value", + "updated": 1610221293179 + }, + { + "style": "Subtitle", + "text": "Recalculate Size Placed" + }, + { + "style": "Text", + "text": "The open stage and close stage sections of the trading engine hierarchy keep track of the accumulated size of the orders that have been placed so that the stage size may be compared to the target size defined in the trading system." + }, + { + "style": "Note", + "text": "Remember that the target size defined acts as a size cap, thus, the system must not place orders in excess of the defined target size.", + "updated": 1610221313060 + }, + { + "style": "Text", + "text": "If the size of the order as determined by the exchange is different from the original size of the order, the current stage size must be recalculated." + }, + { + "style": "Text", + "text": "What the trading bot does in this case is subtracting the original size from the stage size placed, and then add the actual size, as obtained from the exchange. As usual, this is done both for the base asset and the quoted asset." + }, + { + "style": "Text", + "text": "For clarity, each operation is done in two steps." + }, + { + "style": "Javascript", + "text": "tradingEngineStage.stageBaseAsset.sizePlaced.value =\ntradingEngineStage.stageBaseAsset.sizePlaced.value -\ntradingEngineOrder.orderBaseAsset.size.value\n\ntradingEngineStage.stageBaseAsset.sizePlaced.value =\ntradingEngineStage.stageBaseAsset.sizePlaced.value +\ntradingEngineOrder.orderBaseAsset.actualSize.value\n\ntradingEngineStage.stageQuotedAsset.sizePlaced.value =\ntradingEngineStage.stageQuotedAsset.sizePlaced.value -\ntradingEngineOrder.orderQuotedAsset.size.value\n\ntradingEngineStage.stageQuotedAsset.sizePlaced.value =\ntradingEngineStage.stageQuotedAsset.sizePlaced.value +\ntradingEngineOrder.orderQuotedAsset.actualSize.value", + "updated": 1610221350195 + }, + { + "style": "Title", + "text": "Actual Rate Calculation" + }, + { + "style": "Text", + "text": "Market orders are placed without a definition in terms of the rate they will be executed at, as, by definition, a market rate is filled at whatever rate the order book allows.", + "updated": 1610221400343 + }, + { + "style": "Text", + "text": "In the case of limit orders—although the user defines a rate—the exchange may change it slightly, for multiple reasons. For example, due to issues related to decimals precision, or because the order may match existing orders in the order book with a better rate." + }, + { + "style": "Text", + "text": "For those reasons, the trading bot gets the actual rate from the exchange and —in case it differs from the defined rate—makes the updates described below." + }, + { + "style": "Text", + "text": "First of all, the actual rate under the order statistics node is updated with the actual rate provided by the exchange:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderStatistics.actualRate.value = order.price" + }, + { + "style": "Text", + "text": "If the actual rate is the same as the rate of the order as originally defined, then that’s all. Otherwise, the bot goes back and recalculates the size of the order for the quoted asset and the size placed in the quoted asset for the corresponding stage—again." + }, + { + "style": "Callout", + "text": "Let’s do a little recap in case the above is not crystal clear. When the order size in the quoted asset was calculated earlier, the calculation was made by multiplying the actual size in the base asset as reported by the exchange, by the rate as was originally defined. However, if the rate used earlier is not the actual rate at which the order was filled at the exchange, the trading bot needs to go back and calculate the size in the quoted asset again. The same goes for the size placed in the quoted asset." + }, + { + "style": "Text", + "text": "Both calculations are virtually the same as described earlier, so we are not going to go over the details again. Suffice to say that the only difference is that the actual rate is used instead of the original rate as defined in the trading system." + }, + { + "style": "Text", + "text": "And remember, the size in the base asset does not need to be recalculated, as it is not affected by the differences in rates." + }, + { + "style": "Title", + "text": "Percentage Filled Calculation" + }, + { + "style": "Text", + "text": "This is a simple calculation to determine what percentage of the order has been filled, which is relevant later on to calculate fees and balances:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderStatistics.percentageFilled.value = \norder.filled * 100 / \ntradingEngineOrder.orderBaseAsset.actualSize.value", + "updated": 1610221437484 + }, + { + "style": "Note", + "text": "As you can see, the actual size in the base asset is used, as the size is always denominated in the base asset according to the exchange.", + "updated": 1610221445535 + }, + { + "style": "Title", + "text": "Fees Paid Calculation" + }, + { + "style": "Text", + "text": "Exchange fees are a crucial aspect of trading, as they may greatly affect the profitability of strategies." + }, + { + "style": "Callout", + "text": "Surprisingly, the exchange does not explicitly report how much is charged in fees on each order. This apparent contradiction must be resolved by Superalgos, so let’s dive into the details." + }, + { + "style": "Text", + "text": "There are a few fundamental workings that affect the calculations:" + }, + { + "style": "Text", + "text": "The fees are not explicitly reported by the exchange, hence the need to calculate them." + }, + { + "style": "Important", + "text": "To calculate fees, the user bears the ultimate responsibility in supplying the trading bot with the correct parameters defined in the fee structure session parameters. It is these values of maker and taker fees that the system uses to calculate fees. If the parameters are wrong, the calculated fees will be wrong as well.", + "updated": 1610221483105 + }, + { + "style": "Text", + "text": "The taker fee parameter is used to calculate the fees on market orders, while the maker fee parameter is used to calculate fees for limit orders." + }, + { + "style": "Text", + "text": "The exchange charges fees denominated in the asset that the user is acquiring in the transaction. For example, in the BTC/USDT market, a sell order exchanges BTC for USDT, and the exchange charges fees in USDT, because that is the asset you are acquiring. On the contrary, a buy order in the BTC/USDT market exchanges USDT for BTC, thus fees are charged in BTC." + }, + { + "style": "Callout", + "text": "Properly calculating fees is crucial to keeping an accurate accounting system, as they directly affect balances. This is why: The actual size reported by the exchange is not representative of the actual amount of the asset acquired in the transaction. This is because the exchange fills the order, determines the size filled, and then subtracts the fees from the size filled. That is, the size filled reported by the exchange is greater than the amount you receive. In fact, the amount you receive is the actual size filled minus the fees. That calculation is the one used to estimate the balances for both assets in Superalgos so that they match the balances at the exchange." + }, + { + "style": "Text", + "text": "Because orders (in particular limit orders) may be partially filled, the system uses the percentage filled calculated earlier to determine the fees to be paid for the portion filled, as the exchange charges fees for the amount filled only." + }, + { + "style": "Text", + "text": "All of the above considerations are captured in the following calculations." + }, + { + "style": "Subtitle", + "text": "Market buy orders" + }, + { + "style": "Text", + "text": "Because you are acquiring the base asset, fees paid are calculated using the base asset actual size. Because it’s a market order, the taker fees parameter is used." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.feesPaid.value =\ntradingEngineOrder.orderBaseAsset.actualSize.value *\nsessionParameters.feeStructure.config.taker / 100 *\ntradingEngineOrder.orderStatistics.percentageFilled.value / 100", + "updated": 1610221512567 + }, + { + "style": "Subtitle", + "text": "Limit buy orders" + }, + { + "style": "Text", + "text": "Like with market buy orders, because you are acquiring the base asset, fees paid are calculated using the base asset actual size. Because it’s a limit order, the maker fees parameter is used." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.feesPaid.value =\ntradingEngineOrder.orderBaseAsset.actualSize.value *\nsessionParameters.feeStructure.config.maker / 100 *\ntradingEngineOrder.orderStatistics.percentageFilled.value / 100", + "updated": 1610221532644 + }, + { + "style": "Subtitle", + "text": "Market sell orders" + }, + { + "style": "Text", + "text": "Because you are acquiring the quoted asset, fees paid are calculated using the base asset actual size. Because it’s a market order, the taker fees parameter is used." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.feesPaid.value =\ntradingEngineOrder.orderQuotedAsset.actualSize.value *\nsessionParameters.feeStructure.config.taker / 100 *\ntradingEngineOrder.orderStatistics.percentageFilled.value / 100", + "updated": 1610221581263 + }, + { + "style": "Subtitle", + "text": "Limit sell orders" + }, + { + "style": "Text", + "text": "Like with market sell orders, because you are acquiring the quoted asset, fees paid are calculated using the quoted asset actual size. Because it’s a limit order, the maker fees parameter is used." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.feesPaid.value =\ntradingEngineOrder.orderQuotedAsset.actualSize.value *\nsessionParameters.feeStructure.config.maker / 100 *\ntradingEngineOrder.orderStatistics.percentageFilled.value / 100", + "updated": 1610221607990 + }, + { + "style": "Title", + "text": "Size Filled Calculation" + }, + { + "style": "Text", + "text": "As mentioned earlier, and as may be inferred from the example orders presented earlier, the size filled is always reported by the exchange denominated in the base asset. That is:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.sizeFilled.value = order.filled" + }, + { + "style": "Text", + "text": "Therefore, the trading bot needs to calculate the size filled in the quoted asset:" + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.sizeFilled.value =\ntradingEngineOrder.orderQuotedAsset.actualSize.value *\ntradingEngineOrder.orderStatistics.percentageFilled.value / 100", + "updated": 1610221632885 + }, + { + "style": "Title", + "text": "Amount Received Calculation" + }, + { + "style": "Text", + "text": "The amount received is a simple calculation to facilitate the comprehension of the trade, given that the exchange does not provide that basic information. Remember that only the size filled is reported and that fees are subtracted from the size filled." + }, + { + "style": "Subtitle", + "text": "Market and limit buy orders" + }, + { + "style": "Text", + "text": "In these cases, the user receives the amount in the base asset." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderBaseAsset.amountReceived.value =\ntradingEngineOrder.orderBaseAsset.sizeFilled.value -\ntradingEngineOrder.orderBaseAsset.feesPaid.value", + "updated": 1610221660430 + }, + { + "style": "Subtitle", + "text": "Market and limit sell orders" + }, + { + "style": "Text", + "text": "In these cases, the user receives the amount in the quoted asset." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.orderQuotedAsset.amountReceived.value =\ntradingEngineOrder.orderQuotedAsset.sizeFilled.value -\ntradingEngineOrder.orderQuotedAsset.feesPaid.value", + "updated": 1610221674345 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Topics/order-management-007-canceling-orders.json b/Projects/Superalgos/Schemas/Docs-Topics/order-management-007-canceling-orders.json new file mode 100644 index 000000000..e6c513b6d --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Topics/order-management-007-canceling-orders.json @@ -0,0 +1,74 @@ +{ + "topic": "Order Management", + "pageNumber": "7", + "type": "Canceling Orders", + "definition": { + "text": "After running a few checks, if the Cancel Order Event is triggered, the order is canceled, the synchronization is run, and accounts are updated.", + "updated": 1610221990441 + }, + "paragraphs": [ + { + "style": "Title", + "text": "Check Cancel Order Event", + "updated": 1610222003919 + }, + { + "style": "Text", + "text": "Before evaluating the cancel order event, a few checks are in order." + }, + { + "style": "List", + "text": "Orders are not canceled if the stage is closing." + }, + { + "style": "Javascript", + "text": "(tradingEngineStage.status.value === 'Closing')" + }, + { + "style": "List", + "text": "Orders may only be canceled if the status is Open." + }, + { + "style": "Javascript", + "text": "(tradingEngineOrder.status.value === 'Open')" + }, + { + "style": "Text", + "text": "If both checks pass, then the cancel order event is evaluated. If a situation in the event is true, then the following actions take place:", + "updated": 1610222066264 + }, + { + "style": "List", + "text": "If it’s a backtesting or paper trading session, the order cancelation must be simulated (see Simulating Order Cancelation).", + "updated": 1610222051378 + }, + { + "style": "List", + "text": "If it’s a forward testing or live trading session, the order must be canceled at the exchange." + }, + { + "style": "Title", + "text": "Canceling Orders" + }, + { + "style": "Text", + "text": "When the cancel order event as defined in the trading system is triggered, the trading bot sends the cancel order request to the exchange, and waits for an answer. No further action is taken until the exchange confirms the order has been closed." + }, + { + "style": "Text", + "text": "Once the confirmation is in, a new request to check the order is sent, so as to determine if the size filled for the order changed between the last time it was checked and the moment of the cancellation." + }, + { + "style": "Text", + "text": "Once the trading bot gets the order details, it runs the synchronization (see Syncing with the exchange) and the recalculation of the stage size again (see Accounting), to make up and account for any differences that may exist compared to the last known state of the order" + }, + { + "style": "Text", + "text": "The order is not closed until the order details are received from the exchange." + }, + { + "style": "Javascript", + "text": "tradingEngineOrder.status.value = 'Closed'" + } + ] +} \ No newline at end of file