Bitcoin Exchange Project Part 2: Order Matching Algorithm

Posted by & filed under Uncategorized.

Introduction to this project.

Order Matching Algorithm Description (Rough Draft – 2013/10/16)

Summary: A currency exchange is a system for buyers and sellers of different currencies to exchange different types of currency. The other matching module matches buy and sell orders, creates transactions to record the process, and updates the customers account balances.

Part One: Basic Order Processing

Action: A customer enters the quantity and prices of the orders and clicks “buy” or “sell”

1: Website creates record in OrderBook with Pending order status. The order is filed to be processed. [PlaceBuyBid

Then, the Order Matching Service iterates through the list of pending orders. [public int PlaceBuyBid(int customerId, decimal quantityOfBTC, decimal pricePerBTC, DateTime ?expirationDate = null) and public int PlaceSellOffer(int customerId, decimal quantityOfBTC, decimal pricePerBTC, DateTime ?expirationDate = null)] For each order:

2: Re-verify order status to ensure that it is still pending/active. If expired, the order is Cancelled

3: Validate the order funding. [public bool ValidateOrderFunding(Order order)] The customer must have sufficient assets to process the order. If not, the order is Suspended (it may be re-actived if funds become available later.) If order passes validation:
a: the order status is changed to Active
b: the assets needed to pay for the order are added to the Frozen balance. The prevents the customer from placing orders on more assets than he has. This feature may be removed later – we can allow spending greater than the available balance if we check the balance before processin the transaction.

4: The Order Matching Service tries to find a match to the buy or sell order. To find a match, we search all Active orders which match the specified price. [ISpecification IsMatchingOrderQuery(decimal price, int orderTypeId, int wantAssetTypeId,int offerAssetTypeId, bool? isMarketOrder)]

*If the order is a buy, we look for a price less than or equal.
*If the order is a sell, we look for a price greater than or equal.
*If it’s a market order, we find the highest (sell) or lowest (buy) price.

We sort the matches ascending for buy orders, and descending for sell orders. Then we sort by date if the price matches.  [ISpecification IsMatchingOrderQuery(decimal price, int orderTypeId, int wantAssetTypeId,int offerAssetTypeId, bool? isMarketOrder)]

5: We load the top 3 matches into memory. The reason we take 3 matches is in case one of the orders fails validation, we can try with the order 2 orders.

6: We compare the order and the match. This is a double check with C# – the order should have been already matched by the database query above. The orders should match: assets ($/BTC, order types (buy/sell),non-two market orders, and have matching prices (as above). [OrderComparisonResult CompareOrders(Order firstOrder, Order secondOrder)]

7: If the orders comparison succeds, we generate a Transaction to record the match [Transaction GetTransactionForTwoOrders(OrderComparisonResult comparisonResult)].
*A_Order is the buy order
*B_Order is the sell order
(A and B are used because I’m still not sure whether ordering should be Buy/Sell, chronological, or something else)

8: If the order quantities do not match exactly, we must generate a split order with the remainder of the larger order.

9: We run [ActivateTakeProfitAndStopLossOrders(Order order)] – TODO – should not be done here, but scheduled. (See separate post for advanced orders – take proft, stop loss, trigger, stop order, etc.)

10: We process the transaction to record the result [public Order ProcessTransaction(Transaction transaction)] (note: this module is a database transaction)

a: add the transaction and the split orders to the DB
b: for both orders in the transaction:

  •  subtract the debit access (customers balance of $ or BTC)
  •  increment the credit asset (customers balance of $ or BTC)
  •  record the commision in the commision account
  •  unfreeze frozen balances
  •  save changes

11: Repeat the process on each split order, until there is either no remaining quantity (entire order is fullfilled) or we
run out of matching orders; the remaining split order stays open as an active order


foreach (OrderProcessResultModel n in ProcessOrder(splitOrder.OrderId))
{
yield return n;
}

12: If the remaining quantity is 0, set the status to Completed

OrderBook Schema

Open Source Bitcoin Trading Engine

Posted by & filed under code.

I am developing a Bitcoin exchange trading engine.  It’s written in C# and ASP.Net MVC4/Razor.  The UI layer is service-based using knockout.js and jqGrid to bind to JSON web services.    Order processing done in a service process.

Is anyone interested learning more about the design?  Update: OK!  Graphics below updated and first detail post added.

I think it will take at least 10 posts to document this project:

Continue reading “Open Source Bitcoin Trading Engine” »

Creating a .Net compatible code signing certificate

Posted by & filed under Uncategorized.

The purpose of this workaround is to bypass the lack of support for CNG certificates in the .Net Framework.   I used OpenSSL to convert the certificate obtained from the Certificate Authority (Verisign, Thawte, etc) to a format supported by .Net.  This tutorial builds on the workaround in the Microsoft Connect bug report.

Ingredients:

1: Certificate text

2: Certificate imported into Windows certificate store from a root CA

3: OpenSSL

Steps:

1: Create a new file (CERT_ONLY.crt) with the certificate (text from —-BEGIN CERTIFICATE—– to —–END CERTIFICATE—–)

2: Import the certificate into certificate store via the CA website, then export it to file EF.pfx.  Include the private key.

3: Generate PEM file with the private key only:

openssl pkcs12 -in EF.pfx -nocerts -out EF.pem

4: Convert private key to RSA format

openssl rsa -in EF.pem -out EF_RSA.pem

5: Generate the code signing certificate

 openssl pkcs12 -export -out EFnew.pfx -inkey EF_RSA.pem -in CERT_ONLY.crt

6: Delete the existing certificate from the certificate store (backup first) then import the newly generated certificate

Converting Picasa ini dates to directory dates

Posted by & filed under Uncategorized.

One issue I faced in the process of migrating from Picasa to Adobe Lightroom is that Picasa stores event dates in .picasa.ini files. I had spent many hours setting correct dates in my events (folders) and wanted to import them. So I wrote the following C# script (should work for Windows and OS X – I ran in via Mono).

Update: This code is on github @ https://github.com/DavidVeksler/EmbedPicasaProperties

The below will not be updated.

using System;
using System.IO;
 
namespace ConvertPicasaToFolderDates
{
	class MainClass
	{
		private const string IniFileName = @".picasa.ini";
 
		private static void Main(string[] args)
		{
			string startFolder = @"/Users/davidv/Pictures/";
 
			Console.WriteLine(startFolder);
 
			UpdateFoldersInPath(startFolder);
 
		}
 
		private static void UpdateFoldersInPath(string folder)
		{
			string[] directories = Directory.GetDirectories(folder);
 
			if (directories.Length > 0)
				Console.WriteLine("{0} folders in {1}", directories.Length, folder);
 
			foreach (string directory in directories)
			{
				try
				{
					string iniPath = Path.Combine(directory, IniFileName);
 
					if (File.Exists(iniPath))
					{
						Console.WriteLine("Parse " + iniPath);
 
						foreach (string line in File.ReadAllLines(iniPath))
						{
							// date=29586.603900
							if (!line.StartsWith("date=")) continue;
 
							string dateString = line.Substring(5);
 
							DateTime date = ConverPicasaDateToDateTime(dateString);
 
							DateTime originalTime = Directory.GetCreationTime(directory);
 
							if (originalTime != date && date.Year < 2010)
							{
								Console.WriteLine("{0} to {1}", originalTime, date);
								Directory.SetCreationTime(directory, date);
// (For Mono SetCreationTime did not work correctly, so use SetLastWriteTime.)
								Directory.SetLastWriteTime(directory,date);
							}
 
							break;
						}
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex);
				}
 
				try
				{
					UpdateFoldersInPath(directory);
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex);
				}
			}
		}
 
		// convert =29586.603900 to date time format
		private static DateTime ConverPicasaDateToDateTime(string dateString)
		{
			var startDate = new DateTime(1900, 1, 1);
 
			DateTime date = startDate.AddDays(Convert.ToDouble(dateString) -2);
 
			Console.WriteLine("new date: " + date);
 
			return date;
		}
	}
}

 

Note on Community Server to WordPress migration

Posted by & filed under code.

This post has has the full scoop on the process of migrating blogs from Community Server to WordPress, except for this bit: “ultimately, I just wrote a simple regular expression to reformat all the categories so that their names were in the ID attribute.”  Instead of regex, I wrote a a C# script using LINQ to XML:

const string source = @"D:export.xml";
           string source = @"D:export.xml";
            var doc = XDocument.Load(source);
            var categories = new Dictionary();
            foreach (var cat in doc.Elements().First().Elements().Descendants().Where(cat => cat.Name.LocalName == "tag"))
            {
                if (cat.Attribute("id") != null)
                {
                    categories.Add(Convert.ToInt32(cat.Attribute("id").Value), cat.Elements().First().Value);
                }
                else
                {
                    int refId;
                    if (int.TryParse(cat.Attribute("ref").Value, out refId)) // in case it was already run
                    {
                        cat.Attribute("ref").Value = categories[refId];
                    }
                }
            }
            doc.Save(source);