/*
* Copyright (c) 2012 Jeremy Goetsch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jgoetsch.eventtrader.extractor;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jgoetsch.eventtrader.Msg;
import com.jgoetsch.eventtrader.TradeSignal;
import com.jgoetsch.tradeframework.Contract;
/**
* Regex based parser to extract a TradeSignal from a textual trade alert service, i.e. TimAlerts.
* The regex supplied accommodates various common irregularities.
*
* alertPattern is the regex and should yield the following groups
* 1: Action - bought, sold, shorted, covered
* 2: Position size
* 3: Symbol
* 4: Price
* 5: optional price unit ("cents")
*
* @author jgoetsch
*
*/
public class AlertTradeExtractor extends TradeExtractor {
private static Pattern alertPattern = Pattern.compile(
"(?:\\w+:?\\s*)?(?:[Jj]ust)?\\s*([Cc]over(?:ed)|(?:[Rr]e)?[Ss]hort(?:ed)?|[Bb]oug?h?t|[Bb]uy|[Ss]old|[Ss]ell)\\s*([\\d\\,\\.kK]*|[Aa]ll)\\s*([A-Z]+)\\s+(?:\\w+\\s+){0,5}?(?:[Aa]t\\s+)\\$?(\\d*\\.?\\d*)\\s*([Cc]ents?)?");
public Collection<TradeSignal> parseTrades(Msg msg) {
Matcher mAlert = getAlertPattern().matcher(msg.getMessage());
if (mAlert.lookingAt()) {
TradeSignal trade = new TradeSignal(msg);
if (mAlert.group(1).equalsIgnoreCase("Shorted") || mAlert.group(1).equalsIgnoreCase("Short") || mAlert.group(1).equalsIgnoreCase("Reshorted"))
trade.setType(TradeSignal.TYPE_SHORT);
else if (mAlert.group(1).equalsIgnoreCase("Covered") || mAlert.group(1).equalsIgnoreCase("Cover"))
trade.setType(TradeSignal.TYPE_COVER);
else if (mAlert.group(1).equalsIgnoreCase("Bought") || mAlert.group(1).equalsIgnoreCase("Buy"))
trade.setType(TradeSignal.TYPE_BUY);
else if (mAlert.group(1).equalsIgnoreCase("Sold") || mAlert.group(1).equalsIgnoreCase("Sell"))
trade.setType(TradeSignal.TYPE_SELL);
if (mAlert.group(2).length() > 0 && !mAlert.group(2).equalsIgnoreCase("all")) {
try {
float shares = NumberFormat.getInstance().parse(mAlert.group(2)).floatValue();
if (mAlert.group(2).endsWith("k") || mAlert.group(2).endsWith("K"))
shares *= 1000;
trade.setNumShares(Math.round(shares));
} catch (ParseException e) { }
}
trade.setContract(Contract.stock(mAlert.group(3)));
try {
trade.setPrice(Double.parseDouble(mAlert.group(4)));
} catch (NumberFormatException e) { }
if ("cents".equalsIgnoreCase(mAlert.group(5)))
trade.setPrice(trade.getPrice() / 100);
return Collections.singletonList(trade);
}
else
return null;
}
public static void setAlertPattern(String alertPattern) {
AlertTradeExtractor.alertPattern = Pattern.compile(alertPattern);
}
public static void setAlertPattern(Pattern alertPattern) {
AlertTradeExtractor.alertPattern = alertPattern;
}
public static Pattern getAlertPattern() {
return alertPattern;
}
}