Esempio n. 1
0
        /// <summary> Transition function through the graph </summary>
        /// <param name="data"> Current graph state to transition </param>
        /// <param name="place"> New vertex to transition to </param>
        /// <returns> Results of transition </returns>
        public WorkData Step(WorkData data, string place)
        {
            // If data is not already at the place we want to transition it to
            if (data.at != place)
            {
                WorkData next = new WorkData();
                // Started at the same place
                next.start = data.start;
                // Now at the new place
                next.at = place;
                // Apply the rate
                next.rate = data.rate * this[data.at][place];
                // Score the node based on gain per trades
                next.score = (next.rate - 1.0) / data.path.Count;
                // Copy all elements from the previous path into the new one
                next.path = new List <string>(data.path);
                // Then add the place it is at now
                next.path.Add(place);

                // Return built node
                return(next);
            }
            // Already there? Return what we were given
            return(data);
        }
Esempio n. 2
0
        /// <summary> Entry point </summary>
        /// <param name="args"> Command line args</param>
        static void Main(string[] args)
        {
            // Read text from file
            string text = File.ReadAllText(SourceFileDirectory() + "/stuff.dat");

            // Split into lines
            string[] lines = text.Split('\n');
            // Create data structures
            Graph            graph      = new Graph();
            Queue <WorkData> queue      = new Queue <WorkData>();
            List <WorkData>  profitable = new List <WorkData>();

            // Loop over lines in file
            foreach (string line in lines)
            {
                // Split each line, and remove empty strings
                string[] parts = line.Split(' ', '\t').Where(it => (it != "")).ToArray();
                // Skip lines that are not exactly 3 long
                if (parts.Length != 3)
                {
                    continue;
                }
                // Extract data from line: [ from, to, rate ]
                string from = parts[0];
                string to   = parts[1];
                double rate;
                // Skip lines that don't have a number in 3rd element
                if (!double.TryParse(parts[2], out rate))
                {
                    continue;
                }

                // Add new verticies if they don't already exist
                if (!graph.ContainsKey(from))
                {
                    graph[from] = new Dictionary <string, double>();
                }
                if (!graph.ContainsKey(to))
                {
                    graph[to] = new Dictionary <string, double>();
                }

                // Set transition rate into graph
                graph[from][to] = rate;
                graph[to][from] = 1.0 / rate;
            }

            // Loop over key/value pairs in graph
            foreach (var pair in graph)
            {
                // Create a new work data that starts at each vertex,
                WorkData data = new WorkData();
                data.start = pair.Key;
                data.at    = pair.Key;
                data.rate  = 1.0;
                data.score = 0.0;
                data.path  = new List <string>();
                data.path.Add(pair.Key);

                // and add it to our queue
                queue.Enqueue(data);
            }

            Console.WriteLine("Ready. Running.");
            // Time how long it takes
            DateTime start = DateTime.UtcNow;

            // While queue has stuff in it...
            while (queue.Count > 0)
            {
                // Get front thing in queue
                WorkData data = queue.Dequeue();
                // Score this data to see how good it is
                WorkData compare = graph.Step(data, data.start);

                // Loop over graph:
                foreach (var pair in graph)
                {
                    // If we haven't been to that vertex yet
                    if (!data.path.Contains(pair.Key))
                    {
                        // Take transition to that location
                        WorkData next = graph.Step(data, pair.Key);
                        // Score the new data to see how good it is
                        WorkData final = graph.Step(next, data.start);

                        // See if it is profitable, then add it to the list of profitable trades
                        if (final.rate > 1)
                        {
                            profitable.Add(final);
                        }

                        // Ignore anywhere we lose money, even if it's still profitable
                        if (final.rate >= compare.rate)
                        {
                            queue.Enqueue(next);
                        }
                    }
                }
            }
            // Finished! Take the time
            DateTime end  = DateTime.UtcNow;
            TimeSpan diff = end - start;

            // Sort our data in Ascending order
            profitable.Sort((a, b) => (a.rate - b.rate) < 0 ? -1 : 1);
            // Effecient output building (lots of text to append, avoid using += )
            StringBuilder output = new StringBuilder();

            // loop over all profitable paths
            foreach (var profit in profitable)
            {
                // Console.WriteLine(profit.ShortString());
                output.Append(profit.ShortString());
                output.Append('\n');
            }

            Console.WriteLine("\n\nFinished in " + diff.TotalMilliseconds + "ms");
            output.Append("\n\nFinished in " + diff.TotalMilliseconds + "ms");

            // Sort our data in Decending order
            profitable.Sort((a, b) => (a.rate - b.rate) > 0 ? -1 : 1);
            Console.WriteLine("\n\nBest Overall Arbitrage: \n" + profitable[0]);
            output.Append("\n\nBest Overall Arbitrage: \n" + profitable[0]);

            // Sort our data in Decending order by scores instead:
            profitable.Sort((a, b) => (a.score - b.score) > 0 ? -1 : 1);
            Console.WriteLine("\n\nMost Efficient Arbitrage: \n" + profitable[0]);
            output.Append("\n\nMost Efficient Arbitrage: \n" + profitable[0]);

            // Dump output to file
            File.WriteAllText(SourceFileDirectory() + "/outputcs.txt", output.ToString());

            // Pause console, Don't need this unless running in VS2017
            // Console.WriteLine("\nPress Enter to continue...");
            // Console.Read();
        }