示例#1
0
        private Execution ExecuteArbitrageParallel(Arbitrage arbitrage)
        {
            Execution execution = new Execution(arbitrage);

            Parallel.ForEach(execution.GetSequence(), sequence =>
            {
                Int32 offset        = sequence.Item1;
                TriangulationStep x = sequence.Item2;
                TriangulationStep y = sequence.Item3;

                if (!Config.TradingEnabled)
                {
                    m_ExchangeEngine.TestOrder(x.Position, x.Symbol, arbitrage.GetQuantity(offset));
                    return;
                }

                OrderResult result = m_ExchangeEngine.PlaceOrder(x.Position, x.Symbol, arbitrage.GetQuantity(offset));

                if (x.Position == Position.Buy)
                {
                    x.Out = result.OtherQuantity;
                    y.In  = result.ExecutedQuantity;
                }
                else
                {
                    x.Out = result.ExecutedQuantity;
                    y.In  = result.OtherQuantity;
                }

                execution.Fees += result.Fees;
            });

            return(execution);
        }
示例#2
0
        private void ExecuteArbitrage(Arbitrage arbitrage)
        {
            MessageCollection message = new MessageCollection(true, Utilities.FormatMessage(Resources.ArbitrageFound, arbitrage.Identifier, $"{arbitrage.Profit:F4}"));

            if (Config.TradingEnabled && (Config.TradingExecutionsCap > 0) && (m_Executions.Count >= Config.TradingExecutionsCap))
            {
                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageDiscardedCap, Config.TradingExecutionsCap));
                m_MessagePump.Signal(message);
                return;
            }

            if (arbitrage.Profit < Config.TradingThresholdProfit)
            {
                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageDiscardedProfit, $"{Config.TradingThresholdProfit:F4}"));
                return;
            }

            if (m_ExecutionSymbols.Any(arbitrage.GetReferenceAssets().Contains))
            {
                message.AppendMessage(Resources.ArbitrageDiscardedAssets);
                m_MessagePump.Signal(message);
                return;
            }

            if (m_Executions.Count(x => x.Key >= DateTime.Now.AddSeconds(-1d)) > 1)
            {
                message.AppendMessage(Resources.ArbitrageDiscardedCooldown);
                m_MessagePump.Signal(message);
                return;
            }

            Int32 age = (DateTime.Now - arbitrage.ReferenceTime).Milliseconds;

            if (age > Config.TradingThresholdAge)
            {
                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageDiscardedAge, age, Config.TradingThresholdAge));
                m_MessagePump.Signal(message);
                return;
            }

            foreach (String referenceAsset in arbitrage.GetReferenceAssets())
            {
                m_ExecutionSymbols.Add(referenceAsset);
            }

            try
            {
                Execution execution;

                if (Config.TradingStrategy == Strategy.Parallel)
                {
                    execution = ExecuteArbitrageParallel(arbitrage);
                }
                else
                {
                    execution = ExecuteArbitrageSequential(arbitrage);
                }

                m_Executions[DateTime.Now] = execution;

                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageSucceded, Config.TradingStrategy.ToString().ToUpperInvariant()));

                foreach (var zip in arbitrage.GetSequence().Zip(execution.GetSequence(), (e, o) => new { Expected = e, Observed = o }))
                {
                    Int32 offset = zip.Expected.Item1;

                    TriangulationStep eX = zip.Expected.Item2;
                    TriangulationStep eY = zip.Expected.Item3;

                    TriangulationStep oX = zip.Observed.Item2;
                    TriangulationStep oY = zip.Observed.Item3;

                    message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageStep, offset));
                    message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageExpectedConversion, $"{eX.Out:F8}", eX.ReferenceAsset, $"{eY.Out:F8}", eY.ReferenceAsset));
                    message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageObservedConversion, $"{oX.Out:F8}", oX.ReferenceAsset, $"{oY.Out:F8}", oY.ReferenceAsset));
                }

                message.AppendMessage(Resources.ArbitrageDeltas);

                foreach (TriangulationStep step in execution.GetSteps())
                {
                    Decimal eDelta   = step.Delta;
                    Decimal ePercent = (eDelta / step.Out) * 100M;

                    message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageDelta, step.ReferenceAsset, (eDelta < 0M) ? String.Empty : " ", $"{eDelta:F8}", $"{ePercent:F4}"));
                }

                message.AppendMessage(Resources.ArbitrageOthers);
                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageCommission, $"{(-1M * execution.Fees):F8}"));
            }
            catch (Exception e)
            {
                message.AppendMessage(Utilities.FormatMessage(Resources.ArbitrageFailed, Config.TradingStrategy.ToString().ToUpperInvariant(), Utilities.GetExceptionMessage(e)));
            }

            foreach (String referenceAsset in arbitrage.GetReferenceAssets())
            {
                m_ExecutionSymbols.Remove(referenceAsset);
            }

            m_MessagePump.Signal(message);
        }